Spring 5支持的WebFlux对于全局异常的捕捉与以前的WebMVC框架有了不同,不能靠@ControllerAdvice@RestControllerAdvice打天下了。目前国内的资料比较少,而且语焉不详,下面我将处理方式分享出来,文末有我的项目代码供参考。

核心要点是要继承AbstractErrorWebExceptionHandler这个WebFlux下的全局异常处理类,然后重写getRoutingFunction

需要注意的是AbstractErrorWebExceptionHandler中的构造方法中未对messageWriters进行初始化,源码如下:

private List<HttpMessageWriter<?>> messageWriters = Collections.emptyList();

messageWriters是用于最终生成response body的,所以我们必须在实现类中对它进行初始化:

public GlobalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ResourceProperties resourceProperties,
ServerCodecConfigurer serverCodecConfigurer,
ApplicationContext applicationContext) {
super(errorAttributes, resourceProperties, applicationContext); //引用父类构造
this.setMessageWriters(serverCodecConfigurer.getWriters());//配置messageWriters
}

getRoutingFunction中可以通过RouterFunctions.route()设置Response的内容。

@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(
RequestPredicates.all(), this::your_handle_function);
}

RouterFunctions.route()接受两个参数,第一个参数是RequestPredicate类,第二个参数是一个方法。我们通过第一个参数去匹配要处理的Request,通过第二个参数去实现异常处理逻辑,比如重写Response。这个方法的返回值必须是ServerResponse对象。

另外AbstractErrorWebExceptionHandler类中还定义了一个getErrorAttributes方法,通过这个方法我们能获得异常的一些详细信息,比如异常类型,异常的消息描述,异常的TRACK信息等。这样有助于我们对异常做针对性的处理。

Map<String, Object> errorPropertiesMap = getErrorAttributes(request,
ErrorAttributeOptions.of(ErrorAttributeOptions.Include.BINDING_ERRORS,
ErrorAttributeOptions.Include.EXCEPTION,
ErrorAttributeOptions.Include.STACK_TRACE,
ErrorAttributeOptions.Include.MESSAGE));

最后还需要注意对这个自定义的全局异常处理类需要定义它的优先级,至少要小于*-1,因为Spring 5中默认实现的DefaultErrorWebExceptionHandle的优先级就是-1*。在自定义全局异常处理类的时候,大可以借鉴默认处理类的写法。

以上。具体实例可以参考我的GitHub上的完整代码:点击访问