普通的Spring(Boot)有办法进行全局异常处理吗?或者至少能捕获任何未被捕获异常(例如可能随机发生的RuntimeException
)吗?
我已经在Google上搜索过,但我找到的所有内容都是关于控制器的@ControllerAdvice
@ExceptionHandler
的。没有关于一般全局异常处理程序的任何信息。
我基本上只想确保如果发生了一些我还没有捕获的异常,那么我可以记录它,以便我知道这个问题。
通过AOP添加自己的内容,例如下面这样:
@Aspect
@Component
public class ExceptionHandler {
@AfterThrowing(pointcut = "within(*.*)", throwing = "t")
public void log(Throwable t) {
t.printStackTrace();
}
}
查看速查表以帮助理解切入点。
Thread.UncaughtExceptionHandler
中,但它没有起作用。 - GuiRitterResponseEntityExceptionHandler
类并以您想要的方式进行自定义,例如:import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.validation.ValidationException;
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(ValidationException.class)
protected ResponseEntity<Object> handle(ValidationException ex) {
return new ResponseEntity<>(getError(HttpStatus.BAD_REQUEST, ex), new HttpHeaders(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler
protected ResponseEntity<Object> handle(Exception ex, WebRequest request) {
try {
return super.handleException(ex, request);
} catch (Exception e) {
return handleExceptionInternal(ex, null, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.Series.SERVER_ERROR == status.series()) {
log.error("Unexpected error.", ex);
}
return new ResponseEntity<>(getError(status, ex), headers, status);
}
private ApiError getError(HttpStatus status, Exception ex) {
return ApiError.builder()
.status(status.value())
.message(ex.getMessage())
.build();
}
}
通过这种方式,您可以覆盖Spring的默认错误响应体,声明您自定义的异常(例如ValidationException
),以及允许Spring处理在ResponseEntityExceptionHandler
中声明的默认异常。
请注意,尽管在Spring 4.x中不需要在
super.handleException(ex, request)
周围使用try-catch,但由于底层ResponseEntityExceptionHandler
实现的更改,在Spring 5.x中有必要这样做。
@ControllerAdvice
是正确的方式。为什么不呢? - Jack FlampErrorController
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/web/ErrorController.html,它比ControllerAdvice或ExceptionHandler高一级。但不确定这是否符合您的要求。 - pvpkiran@Scheduled
自动触发任务。 - samanime