我有两个用@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_PRECDENCE(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;
}