前言
由于Spring Clod Gateway使用了Web Flux实现,因此无法使用@ControllerAdvice的方法进行全局统一异常处理,需要使用ErrorWebExceptionHandler接口的实现类进行处理,因此我们继承DefaultErrorWebExceptionHandler实现自定义统一异常处理。
CustomErrorWebExceptionHandler实现
/**
* 描述:自定义全局异常处理器
*
* @author xhsf
* @create 2020/11/26 12:35
*/
public class CustomErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
public CustomErrorWebExceptionHandler(
ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
ErrorProperties errorProperties, ApplicationContext applicationContext) {
super(errorAttributes, resourceProperties, errorProperties, applicationContext);
}
/**
* 获取异常属性
* @param request ServerRequest
* @param includeStackTrace includeStackTrace
* @return Map<String, Object>
*/
@Override
protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
Map<String, Object> map = new HashMap<>();
map.put("success", false);
map.put("data", null);
Throwable error = super.getError(request);
map.put("message", error.getMessage());
map.put("errorCode", ErrorCode.INVALID_PARAMETER);
// 网关的异常
if (error instanceof NotFoundException) {
map.put("errorCode", ErrorCode.INVALID_PARAMETER_NOT_FOUND);
}
return map;
}
/**
* 指定响应处理方法为JSON处理的方法
*
* @param errorAttributes ErrorAttributes
* @return RouterFunction<ServerResponse>
*/
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
/**
* 获取对应的HttpStatus
*
* @param errorAttributes Map<String, Object>
* @return HttpStatus
*/
@Override
protected int getHttpStatus(Map<String, Object> errorAttributes) {
ErrorCode errorCode = (ErrorCode) errorAttributes.get("errorCode");
return errorCode.getHttpStatus().value();
}
}
这里重点是getErrorAttributes()和getHttpStatus()方法。getErrorAttributes()用于获取异常,根据异常的类型自定义响应结果,这里我封装了项目统一使用的{success, data, message, errorCode}结构。
getHttpStatus()用于根据getErrorAttributes()的结果自定义HTTP状态码,因为ErrorCode里已经附带了HTTP状态码,因此直接取出即可。
ErrorHandlerConfig
该类用于配置自定义的handler。
/**
* 描述:覆盖默认全局异常处理
*
* @author xhsf
* @create 2020/11/26 12:38
*/
@Configuration
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class ErrorHandlerConfig {
private final ServerProperties serverProperties;
private final ApplicationContext applicationContext;
private final ResourceProperties resourceProperties;
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public ErrorHandlerConfig(ServerProperties serverProperties,
ResourceProperties resourceProperties,
ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer,
ApplicationContext applicationContext) {
this.serverProperties = serverProperties;
this.applicationContext = applicationContext;
this.resourceProperties = resourceProperties;
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
CustomErrorWebExceptionHandler exceptionHandler = new CustomErrorWebExceptionHandler(
errorAttributes, resourceProperties, serverProperties.getError(), applicationContext);
exceptionHandler.setViewResolvers(viewResolvers);
exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
return exceptionHandler;
}
}