From 235bcb8c9c51ba4f28d002512a58b5b1722f4e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johnny=20Miller=20=28=E9=94=BA=E4=BF=8A=29?= Date: Wed, 23 Dec 2020 11:34:49 +0800 Subject: [PATCH] perf($ApiGateway): handle service not available exception --- .../handler/GlobalExceptionHandler.java | 9 ++++--- .../maf/common/bean/ResponseBodyBean.java | 19 ++++++++++++++- .../package-info.java | 1 - .../util/ResponseUtil.java | 24 +++++++++++-------- 4 files changed, 38 insertions(+), 15 deletions(-) delete mode 100644 reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/package-info.java diff --git a/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/universal/handler/GlobalExceptionHandler.java b/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/universal/handler/GlobalExceptionHandler.java index 83d674d7..92b9f8ef 100644 --- a/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/universal/handler/GlobalExceptionHandler.java +++ b/api-gateway/src/main/java/com/jmsoftware/maf/apigateway/universal/handler/GlobalExceptionHandler.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.jmsoftware.maf.common.bean.ResponseBodyBean; import com.jmsoftware.maf.muscleandfitnessserverreactivespringbootstarter.util.RequestUtil; +import com.netflix.hystrix.exception.HystrixRuntimeException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.val; @@ -37,10 +38,9 @@ public class GlobalExceptionHandler implements ErrorWebExceptionHandler { @SuppressWarnings("NullableProblems") public Mono handle(ServerWebExchange exchange, Throwable ex) { val request = exchange.getRequest(); - log.error("Exception occurred when [{}] requested access. Request URL: [{}] {}", - RequestUtil.getRequestIpAndPort(request), request.getMethod(), request.getURI()); + log.error("Exception occurred when [{}] requested access. Exception message: {}. Request URL: [{}] {}", + RequestUtil.getRequestIpAndPort(request), ex.getMessage(), request.getMethod(), request.getURI(), ex); ServerHttpResponse response = exchange.getResponse(); - log.error(ex.getMessage(), ex.fillInStackTrace()); if (response.isCommitted()) { return Mono.error(ex); } @@ -69,6 +69,9 @@ private ResponseBodyBean setResponseBody(ServerHttpResponse response, Throwab if (ex instanceof ResponseStatusException) { response.setStatusCode(((ResponseStatusException) ex).getStatus()); return ResponseBodyBean.ofStatus(((ResponseStatusException) ex).getStatus()); + } else if (ex instanceof HystrixRuntimeException) { + response.setStatusCode(HttpStatus.SERVICE_UNAVAILABLE); + return ResponseBodyBean.ofStatus(HttpStatus.SERVICE_UNAVAILABLE, ex.getMessage()); } response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); return ResponseBodyBean.ofStatus(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage()); diff --git a/common/src/main/java/com/jmsoftware/maf/common/bean/ResponseBodyBean.java b/common/src/main/java/com/jmsoftware/maf/common/bean/ResponseBodyBean.java index b775ce29..aa43f538 100644 --- a/common/src/main/java/com/jmsoftware/maf/common/bean/ResponseBodyBean.java +++ b/common/src/main/java/com/jmsoftware/maf/common/bean/ResponseBodyBean.java @@ -70,6 +70,23 @@ public static ResponseBodyBean ofSt .build(); } + /** + * Of status response body bean. + * + * @param the type parameter + * @param status the status + * @param message the message + * @return the response body bean + */ + public static ResponseBodyBean ofStatus(@NonNull final HttpStatus status, + @NonNull final String message) { + return ResponseBodyBean.builder() + .timestamp(new Date()) + .status(status.value()) + .message(message) + .build(); + } + /** *

Respond to client with IUniversalStatus and data.

*

ATTENTION:

@@ -82,7 +99,7 @@ public static ResponseBodyBean ofSt * @return response body for ExceptionControllerAdvice */ public static ResponseBodyBean ofStatus(@NonNull final HttpStatus status, - @NonNull final ResponseBodyDataType data) { + final ResponseBodyDataType data) { return ResponseBodyBean.builder() .timestamp(new Date()) .status(status.value()) diff --git a/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/package-info.java b/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/package-info.java deleted file mode 100644 index 04f0469b..00000000 --- a/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package com.jmsoftware.maf.muscleandfitnessserverreactivespringbootstarter; diff --git a/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/util/ResponseUtil.java b/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/util/ResponseUtil.java index a430ddd1..8041f787 100644 --- a/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/util/ResponseUtil.java +++ b/reactive-spring-boot-starter/src/main/java/com/jmsoftware/maf/muscleandfitnessserverreactivespringbootstarter/util/ResponseUtil.java @@ -1,19 +1,17 @@ package com.jmsoftware.maf.muscleandfitnessserverreactivespringbootstarter.util; -import cn.hutool.json.JSON; -import cn.hutool.json.JSONUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.jmsoftware.maf.common.bean.ResponseBodyBean; import lombok.NonNull; import lombok.SneakyThrows; import lombok.val; -import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.http.HttpStatus; import org.springframework.lang.Nullable; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; -import java.nio.charset.StandardCharsets; - /** * Description: ResponseUtil, change description here. * @@ -31,13 +29,19 @@ public class ResponseUtil { @SneakyThrows public static Mono renderJson(@NonNull ServerWebExchange exchange, @NonNull HttpStatus httpStatus, @Nullable Object data) { + ObjectMapper objectMapper = new ObjectMapper(); exchange.getResponse().setStatusCode(httpStatus); val response = exchange.getResponse(); - JSON json = ResponseBodyBean.of(httpStatus.getReasonPhrase(), data, httpStatus.value()); - val responseBodyBytes = JSONUtil.toJsonStr(json).getBytes(StandardCharsets.UTF_8); - DataBuffer dataBuffer = response.bufferFactory().wrap(responseBodyBytes); response.setStatusCode(httpStatus); - response.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); - return response.writeWith(Mono.just(dataBuffer)); + response.getHeaders().set("Content-Type", "application/json;charset=UTF-8"); + return response.writeWith(Mono.fromSupplier(() -> { + DataBufferFactory bufferFactory = response.bufferFactory(); + final var responseBody = ResponseBodyBean.ofStatus(httpStatus, data); + try { + return bufferFactory.wrap(objectMapper.writeValueAsBytes(responseBody)); + } catch (JsonProcessingException e) { + return bufferFactory.wrap(new byte[0]); + } + })); } }