前言
之前 spring web 常用的全局异常处理方法如下:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MyException.class)
// 处理函数...
}
在 webFlux 基于注解的路由编程方法(eg: @GetMapping()),上述方法中仍然可用
但如果想尝试新的 RouterFunction 路由方式,方法抛出的异常不会被全局异常抓到,而是走了 webFlux默认的异常处理,显示一大堆信息
方案一
- 只需要像注册接口路由 RouterFunction 一样,注册一个bean
@Bean
WebFilter reqExceptionToBadRequest() {
return (exchange, next) -> next.filter(exchange)
.onErrorResume(MyException.class, e -> {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.BAD_REQUEST);
return response.setComplete();
});
}
- 上面这个过滤器会捕获MyException,自定义处理后响应信息
上面只修改了状态码,如果想要自定义响应体,参考下面:
private byte[] jsonToByteArray(Object json) {
try {
return new ObjectMapper().writeValueAsBytes(json);
} catch (JsonProcessingException ex) {
// 可以自定义其他逻辑,这里简单起见
return ex.getMessage().getBytes();
}
}
@Bean
WebFilter reqExceptionToBadRequest() {
return (exchange, next) -> next.filter(exchange)
.onErrorResume(WebRequestException.class, e -> {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.BAD_REQUEST);
response.getHeaders().add(
"Content-Type", "application/json"
);
var resp = Map.of("message", "自定义信息");
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(
jsonToByteArray(resp)
);
return response.writeWith(Mono.just(buffer));
});
}
方案二
- 也可以对只特定的路由生效
@Bean
RouterFunction<ServerResponse> route() {
return RouterFunctions
.route(GET("/foo"), request -> Mono.error(new DataNotFoundException()))
.andRoute(GET("/bar"), request -> Mono.error(new DataNotFoundException()))
.filter(dataNotFoundToBadRequest());
}
private HandlerFilterFunction<ServerResponse, ServerResponse> dataNotFoundToBadRequest() {
return (request, next) -> next.handle(request)
.onErrorResume(DataNotFoundException.class, e -> ServerResponse.badRequest().build());
}
参考: