|
|
|
@ -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<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) { |
|
|
|
|
int code = 500; |
|
|
|
|
Throwable error = super.getError(request); |
|
|
|
|
if (error instanceof NotFoundException) { |
|
|
|
|
code = 404; |
|
|
|
|
public Mono<Void> 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<ServerResponse> 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<String, Object> 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<String, Object> 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(": "); |
|
|
|
|