Webflux中DefaultErrorWebExceptionHandler与@ControllerAdvice的冲突解决
解决GlobalErrorWebExceptionHandler与ExceptionHandling的冲突问题
在Spring WebFlux中,实现了ProblemHandling的@ControllerAdvice类会优先拦截控制器抛出的异常,而你的GlobalErrorWebExceptionHandler作为全局错误处理器在下游生效,所以引入前者后,原本该由后者处理的输入无效请求被前者接管了。下面是几种可行的解决办法:
方案1:限定ExceptionHandling的处理范围
让ExceptionHandling只处理你需要的特定异常,把输入验证类异常(比如MethodArgumentNotValidException、BindException)排除,让这类异常交给GlobalErrorWebExceptionHandler处理。
修改后的ExceptionHandling代码示例:
@ControllerAdvice public class ExceptionHandling implements ProblemHandling { // 仅处理自定义业务异常 @ExceptionHandler(CustomBusinessException.class) public ResponseEntity<Problem> handleCustomBusinessException(CustomBusinessException ex) { return create(ex, Status.INTERNAL_SERVER_ERROR); } // 覆盖默认方法,跳过输入验证异常的处理,让异常继续向下传递 @Override public ResponseEntity<Problem> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, NativeWebRequest request) { return null; } @Override public ResponseEntity<Problem> handleBindException(BindException ex, NativeWebRequest request) { return null; } }
方案2:调整两者的优先级顺序
给ExceptionHandling添加@Order注解,让它的优先级低于GlobalErrorWebExceptionHandler(你已经给后者加了@Order(-2),所以给前者设一个更大的数值即可):
@ControllerAdvice @Order(1) // 数值越大优先级越低,确保比-2大 public class ExceptionHandling implements ProblemHandling { // 你的handler方法 }
同时修改GlobalErrorWebExceptionHandler,遇到需要交给ExceptionHandling处理的异常时重新抛出:
@Override protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) { Throwable error = getError(request); // 如果是业务异常,抛出给ExceptionHandling处理 if (error instanceof CustomBusinessException) { return Mono.error(error); } // 其他异常按原逻辑返回 Map<String, Object> errorPropertiesMap = getErrorAttributes(request, ErrorAttributeOptions.defaults()); return ServerResponse.status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(errorPropertiesMap)); }
方案3:自定义ProblemHandling的异常筛选逻辑
重写ProblemHandling的supports方法,指定只处理特定类型的异常:
@ControllerAdvice public class ExceptionHandling implements ProblemHandling { @Override public boolean supports(Class<? extends Throwable> type) { // 仅处理自定义业务异常,排除输入验证相关异常 return CustomBusinessException.class.isAssignableFrom(type) && !MethodArgumentNotValidException.class.isAssignableFrom(type) && !BindException.class.isAssignableFrom(type); } // 你的handler方法 }
内容的提问来源于stack exchange,提问作者Omkar Shetkar
相关产品推荐
相关产品推荐

