diff --git a/blade-gateway/src/main/java/org/springblade/gateway/config/ErrorHandlerConfiguration.java b/blade-gateway/src/main/java/org/springblade/gateway/config/ErrorHandlerConfiguration.java index 879c43ba9..eae509514 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/config/ErrorHandlerConfiguration.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/config/ErrorHandlerConfiguration.java @@ -17,25 +17,15 @@ package org.springblade.gateway.config; +import com.fasterxml.jackson.databind.ObjectMapper; import org.springblade.gateway.handler.ErrorExceptionHandler; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.web.ResourceProperties; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.reactive.error.ErrorAttributes; -import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.web.reactive.result.view.ViewResolver; - -import java.util.Collections; -import java.util.List; /** * 异常处理配置类 @@ -47,40 +37,9 @@ import java.util.List; @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class}) public class ErrorHandlerConfiguration { - private final ServerProperties serverProperties; - - private final ApplicationContext applicationContext; - - private final ResourceProperties resourceProperties; - - private final List viewResolvers; - - private final ServerCodecConfigurer serverCodecConfigurer; - - public ErrorHandlerConfiguration(ServerProperties serverProperties, - ResourceProperties resourceProperties, - ObjectProvider> 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) { - ErrorExceptionHandler exceptionHandler = new ErrorExceptionHandler( - errorAttributes, - this.resourceProperties, - this.serverProperties.getError(), - this.applicationContext); - exceptionHandler.setViewResolvers(this.viewResolvers); - exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters()); - exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders()); - return exceptionHandler; + public ErrorExceptionHandler globalExceptionHandler(ObjectMapper objectMapper) { + return new ErrorExceptionHandler(objectMapper); } } diff --git a/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java b/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java index 5e5c6df7c..b00d981b9 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java @@ -16,15 +16,19 @@ */ package org.springblade.gateway.handler; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; import org.springblade.gateway.provider.ResponseProvider; -import org.springframework.boot.autoconfigure.web.ErrorProperties; -import org.springframework.boot.autoconfigure.web.ResourceProperties; -import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler; -import org.springframework.boot.web.reactive.error.ErrorAttributes; -import org.springframework.cloud.gateway.support.NotFoundException; -import org.springframework.context.ApplicationContext; -import org.springframework.web.reactive.function.server.*; +import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; +import org.springframework.core.annotation.Order; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.server.ResponseStatusException; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; import java.util.Map; @@ -33,65 +37,54 @@ import java.util.Map; * * @author Chill */ -public class ErrorExceptionHandler extends DefaultErrorWebExceptionHandler { +@Order(-1) +@RequiredArgsConstructor +public class ErrorExceptionHandler implements ErrorWebExceptionHandler { - public ErrorExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, - ErrorProperties errorProperties, ApplicationContext applicationContext) { - super(errorAttributes, resourceProperties, errorProperties, applicationContext); - } + private final ObjectMapper objectMapper; - /** - * 获取异常属性 - */ @Override - protected Map getErrorAttributes(ServerRequest request, boolean includeStackTrace) { - int code = 500; - Throwable error = super.getError(request); - if (error instanceof NotFoundException) { - code = 404; + public Mono handle(ServerWebExchange exchange, Throwable ex) { + ServerHttpRequest request = exchange.getRequest(); + ServerHttpResponse response = exchange.getResponse(); + + if (response.isCommitted()) { + return Mono.error(ex); } - if (error instanceof ResponseStatusException) { - code = ((ResponseStatusException) error).getStatus().value(); + + response.getHeaders().setContentType(MediaType.APPLICATION_JSON); + if (ex instanceof ResponseStatusException) { + response.setStatusCode(((ResponseStatusException) ex).getStatus()); } - return ResponseProvider.response(code, this.buildMessage(request, error)); - } - /** - * 指定响应处理方法为JSON处理的方法 - * - * @param errorAttributes - */ - @Override - protected RouterFunction getRoutingFunction(ErrorAttributes errorAttributes) { - return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse); + return response.writeWith(Mono.fromSupplier(() -> { + DataBufferFactory bufferFactory = response.bufferFactory(); + try { + int status = 500; + if (response.getStatusCode() != null) { + status = response.getStatusCode().value(); + } + Map result = ResponseProvider.response(status, this.buildMessage(request, ex)); + return bufferFactory.wrap(objectMapper.writeValueAsBytes(result)); + } catch (JsonProcessingException e) { + return bufferFactory.wrap(new byte[0]); + } + })); } - /** - * 根据code获取对应的HttpStatus - * - * @param errorAttributes - */ - @Override - protected int getHttpStatus(Map errorAttributes) { - return (int) errorAttributes.get("code"); - } /** * 构建异常信息 - * - * @param request - * @param ex - * @return */ - private String buildMessage(ServerRequest request, Throwable ex) { - String uri = request.uri().toString(); + private String buildMessage(ServerHttpRequest request, Throwable ex) { + String uri = request.getURI().toString(); if (uri.endsWith("doc.html")) { return "[Swagger聚合网关] 已迁移至 [blade-swagger] 服务,请开启 [blade-swagger] 服务并访问 [http://127.0.0.1:18000/doc.html]"; } StringBuilder message = new StringBuilder("Failed to handle request ["); - message.append(request.methodName()); + message.append(request.getMethodValue()); message.append(" "); - message.append(request.uri()); + message.append(request.getURI()); message.append("]"); if (ex != null) { message.append(": ");