我有 2 个异常处理程序类,用
@RestControllerAdvice
和: 注释
我使用第一个作为全局异常处理程序来捕获异常:
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@Override
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
protected ResponseEntity<Object> handleMethodArgumentNotValid(...) {
// ...
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity<Object> handleAllUncaughtException(Exception ex, WebRequest request) {
// ...
}
// code omitted for clarity
}
第二个用于验证异常(我创建自定义验证):
@RestControllerAdvice
public class ValidationExceptionHandler { // did not extend from extends ResponseEntityExceptionHandler
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
protected ValidationErrorResponse onConstraintValidationException(ConstraintViolationException e) {
// ...
}
}
当我将
onConstraintValidationException
移动到 GlobalExceptionHandler
类时,我捕获验证异常并显示相应的消息。但是当它在第二个 ControllerAdvice 类 (ValidationExceptionHandler
) 中时,如上所示,代码不会命中 onConstraintValidationException
方法。
我也尝试过从
ResponseEntityExceptionHandler
延长第二堂课,但没有任何意义。
那么,问题是什么以及如何解决它?
在你的情况下,这可能是优先级问题......第一个异常处理程序具有最高优先级,并且可能handleAllUncaughtException将捕获所有异常。
要在第二个处理程序 (ValidationExceptionHandler) 中捕获 ConstraintViolationException,您应该给予它最高优先级,如下所示:
@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ValidationExceptionHandler {
以及第一个最低的:
@RestControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
可以看看这个讨论,了解更多关于它是如何工作的并有一些替代解决方案可能会很有趣: 设置多个@ControllerAdvice @ExceptionHandlers的优先级
编辑:如果您需要更灵活的东西或创建更复杂的处理程序层次结构,您可以在 Order 注释中使用简单的整数。 最低值,最高优先级。 所以像这样的东西也可以工作:
@RestControllerAdvice
@Order(-1)
public class ValidationExceptionHandler {
//...
@RestControllerAdvice
@Order(0)
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
//...
在订购的源代码中,您有:
public interface Ordered {
/**
* Useful constant for the highest precedence value.
* @see java.lang.Integer#MIN_VALUE
*/
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
/**
* Useful constant for the lowest precedence value.
* @see java.lang.Integer#MAX_VALUE
*/
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
在 Order 注释中,您可以看到默认值是 LOWEST_PRECEDENCE (Integer.MAX_VALUE):
public @interface Order {
/**
* The order value.
* <p>Default is {@link Ordered#LOWEST_PRECEDENCE}.
* @see Ordered#getOrder()
*/
int value() default Ordered.LOWEST_PRECEDENCE;
}