相关类
WebExceptionHandler
/**
* Contract for handling exceptions during web server exchange processing.
*/
public interface WebExceptionHandler {
/**
*
*/
Mono<Void> handle(ServerWebExchange exchange, Throwable ex);
}
ErrorWebExceptionHandler
@FunctionalInterface
public interface ErrorWebExceptionHandler extends WebExceptionHandler {
}
自定义全局异常处理
GlobalExceptionHandler
@Component
@Slf4j
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
// 打印日志时使用
private static final String ERROR_STACKTRACE = "Stacktrace:";
// 异常返回的状态码
private static final String KEY_STATUS = "httpStatus";
// 异常返回信息主体
private static final String KEY_BODY = "body";
private Tracer tracer;
public void setTracer(Tracer tracer) {
this.tracer = tracer;
}
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* MessageReader
*/
private List<HttpMessageReader<?>> messageReaders = Collections.emptyList();
/**
* MessageWriter
*/
private List<HttpMessageWriter<?>> messageWriters = Collections.emptyList();
/**
* ViewResolvers
*/
private List<ViewResolver> viewResolvers = Collections.emptyList();
/**
* 存储处理异常后的信息
*/
private final ThreadLocal<Map<String, Object>> exceptionHandlerResult = new ThreadLocal<>();
/**
* 参考AbstractErrorWebExceptionHandler
*/
public void setMessageReaders(List<HttpMessageReader<?>> messageReaders) {
Assert.notNull(messageReaders, "'messageReaders' must not be null");
this.messageReaders = messageReaders;
}
/**
* 参考AbstractErrorWebExceptionHandler
*/
public void setViewResolvers(List<ViewResolver> viewResolvers) {
this.viewResolvers = viewResolvers;
}
/**
* 参考AbstractErrorWebExceptionHandler
*/
public void setMessageWriters(List<HttpMessageWriter<?>> messageWriters) {
Assert.notNull(messageWriters, "'messageWriters' must not be null");
this.messageWriters = messageWriters;
}
/**
* 全局异常处理器 根据需求自定义
*
* @param serverWebExchange exchange
* @param throwable throwable
* @return void
*/
@SneakyThrows
@Override
public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
// 按照异常类型进行处理
Map<String, Object> result = new HashMap<>(2, 1);
ServerHttpRequest request = serverWebExchange.getRequest();
// 异常处理 此处添加自定义异常处理
if (throwable instanceof ResponseStatusException) {
ResponseStatusException exception = (ResponseStatusException) throwable;
CustomExceptionResponse customExceptionResponse =
new CustomExceptionResponse(String.valueOf(exception.getRawStatusCode()),
exception.getReason(),request.getURI().getPath());
log.debug("ResponseStatusException occurred, url: {}", request.getURI().getPath());
log.debug(ERROR_STACKTRACE, exception);
String body = objectMapper.writeValueAsString(customExceptionResponse);
result.put(KEY_STATUS, exception.getStatus());
result.put(KEY_BODY, body);
} else {
log.error("Exception occurred, url: {}", request.getURI().getPath());
log.error(ERROR_STACKTRACE, throwable);
CustomExceptionResponse customExceptionResponse =
new CustomExceptionResponse(null,throwable.getMessage(),
request.getURI().getPath());
String body = objectMapper.writeValueAsString(customExceptionResponse);
result.put(KEY_STATUS, HttpStatus.INTERNAL_SERVER_ERROR);
result.put(KEY_BODY, body);
}
//参考AbstractErrorWebExceptionHandler
if (serverWebExchange.getResponse().isCommitted()) {
return Mono.error(throwable);
}
exceptionHandlerResult.set(result);
ServerRequest newRequest = ServerRequest.create(serverWebExchange, this.messageReaders);
Span span = tracer.currentSpan();
if (span != null) {
span.tag("exception", throwable.toString());
span.flush();
}
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse).route(newRequest)
.switchIfEmpty(Mono.error(throwable))
.flatMap((handler) -> handler.handle(newRequest))
.flatMap((response) -> write(serverWebExchange, response));
}
/**
* 参考DefaultErrorWebExceptionHandler
*/
protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
Map<String, Object> result = exceptionHandlerResult.get();
return ServerResponse.status((HttpStatus) result.get(KEY_STATUS))
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(result.get(KEY_BODY)));
}
/**
* 参考AbstractErrorWebExceptionHandler
*/
private Mono<? extends Void> write(ServerWebExchange exchange,
ServerResponse response) {
exchange.getResponse().getHeaders()
.setContentType(response.headers().getContentType());
return response.writeTo(exchange, new ResponseContext());
}
/**
* 参考AbstractErrorWebExceptionHandler
*/
private class ResponseContext implements ServerResponse.Context {
@Override
public List<HttpMessageWriter<?>> messageWriters() {
return GlobalExceptionHandler.this.messageWriters;
}
@Override
public List<ViewResolver> viewResolvers() {
return GlobalExceptionHandler.this.viewResolvers;
}
}
}
CustomExceptionResponse :
/**
* 错误返回的类型
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class CustomExceptionResponse {
private String errorCode;
private String message;
private String path;
}
ExceptionConfig:
/**
* 异常配置
*/
@Configuration
public class ExceptionConfig {
/**
* 自定义异常处理[@@]注册Bean时依赖的Bean,会从容器中直接获取,所以直接注入即可
*/
@Primary
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public ErrorWebExceptionHandler errorWebExceptionHandler(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer,
Tracer tracer) {
GlobalExceptionHandler globalExceptionHandler = new GlobalExceptionHandler();
globalExceptionHandler.setTracer(tracer);
globalExceptionHandler.setViewResolvers(viewResolversProvider.getIfAvailable(Collections::emptyList));
globalExceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
globalExceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
return globalExceptionHandler;
}
}