From a9e190487eca7eca010e70046b2f8145ea3cfabc Mon Sep 17 00:00:00 2001 From: liaozan <378024053@qq.com> Date: Thu, 1 Jun 2023 14:34:14 +0800 Subject: [PATCH] Improve exceptionHanding --- .../web/ExceptionHandingConfiguration.java | 14 +++++- .../exception/DefaultExceptionTranslator.java | 31 +++++++++++++ .../DefaultGlobalExceptionHandler.java | 43 ++++++++++--------- .../web/exception/ExceptionTranslator.java | 23 ++++++++++ 4 files changed, 89 insertions(+), 22 deletions(-) create mode 100644 commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java create mode 100644 commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java b/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java index 7d9bbb4..6be2a55 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/ExceptionHandingConfiguration.java @@ -2,11 +2,14 @@ package com.schbrain.common.web; import com.schbrain.common.web.exception.*; import com.schbrain.common.web.properties.WebProperties; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import java.util.stream.Collectors; + /** * @author liaozan * @since 2023-05-08 @@ -16,8 +19,15 @@ public class ExceptionHandingConfiguration { @Bean @ConditionalOnMissingBean - public GlobalExceptionHandler defaultGlobalExceptionHandler() { - return new DefaultGlobalExceptionHandler(); + public GlobalExceptionHandler defaultGlobalExceptionHandler(ObjectProvider exceptionTranslators) { + return new DefaultGlobalExceptionHandler(exceptionTranslators.orderedStream().collect(Collectors.toList())); + } + + @Bean + @ConditionalOnMissingBean + @ConditionalOnBean(GlobalExceptionHandler.class) + public ExceptionTranslator defaultExceptionTranslator() { + return new DefaultExceptionTranslator(); } @Bean diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java new file mode 100644 index 0000000..bed00ba --- /dev/null +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultExceptionTranslator.java @@ -0,0 +1,31 @@ +package com.schbrain.common.web.exception; + +import com.schbrain.common.exception.BaseException; +import com.schbrain.common.util.EnvUtils; +import com.schbrain.common.web.result.ResponseDTO; +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.Ordered; + +/** + * @author liaozan + * @since 2023-06-01 + */ +public class DefaultExceptionTranslator implements ExceptionTranslator { + + @Override + public ResponseDTO translate(Throwable throwable, int code, int action, String message) { + if (throwable instanceof BaseException) { + return ResponseDTO.error((BaseException) throwable); + } + if (EnvUtils.isProduction() || StringUtils.isBlank(message)) { + return ResponseDTO.error("系统错误", code); + } + return ResponseDTO.error(message, code, action); + } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } + +} \ No newline at end of file diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionHandler.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionHandler.java index 2d33ddf..dce828f 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionHandler.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/DefaultGlobalExceptionHandler.java @@ -2,11 +2,10 @@ package com.schbrain.common.web.exception; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.util.StrUtil; +import com.schbrain.common.constants.ResponseActionConstants; import com.schbrain.common.exception.BaseException; -import com.schbrain.common.util.EnvUtils; import com.schbrain.common.web.result.ResponseDTO; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.hibernate.validator.internal.engine.path.PathImpl; import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; @@ -37,11 +36,17 @@ import static com.schbrain.common.constants.ResponseCodeConstants.*; @ResponseStatus(HttpStatus.OK) public class DefaultGlobalExceptionHandler implements GlobalExceptionHandler { + private final List exceptionTranslators; + + public DefaultGlobalExceptionHandler(List exceptionTranslators) { + this.exceptionTranslators = exceptionTranslators; + } + /************************************* Base Exception Handing *************************************/ @ExceptionHandler(BaseException.class) public ResponseDTO handleBaseException(BaseException ex) { logError(ex); - return ResponseDTO.error(ex); + return buildResponse(ex, ex.getCode(), ex.getAction(), ex.getMessage()); } /************************************* Common Exception Handing *************************************/ @@ -185,25 +190,31 @@ public class DefaultGlobalExceptionHandler implements GlobalExceptionHandler { return buildResponse(ex, PARAM_INVALID, errorMsg); } - protected ResponseDTO loggingThenBuildResponse(Throwable throwable, int errorCode) { + protected ResponseDTO loggingThenBuildResponse(Throwable throwable, int code) { Throwable rootCause = ExceptionUtil.getRootCause(throwable); logError(rootCause); - return buildResponse(rootCause, errorCode, rootCause.getMessage()); + return buildResponse(rootCause, code, rootCause.getMessage()); } protected ResponseDTO buildResponse(Throwable throwable, int code, String message) { - boolean isProduction = EnvUtils.isProduction(); - ResponseDTO responseDTO = getExceptionResponseMapping(throwable, isProduction); + return buildResponse(throwable, code, ResponseActionConstants.ALERT, message); + } + + protected ResponseDTO buildResponse(Throwable throwable, int code, int action, String message) { + ResponseDTO responseDTO = translateException(throwable, code, action, message); if (responseDTO != null) { return responseDTO; } - if (isProduction || StringUtils.isBlank(message)) { - return ResponseDTO.error("系统错误", code); - } - return ResponseDTO.error(message, code); + return ResponseDTO.error(message, code, action); } - protected ResponseDTO getExceptionResponseMapping(Throwable throwable, boolean isProduction) { + protected ResponseDTO translateException(Throwable throwable, int code, int action, String message) { + for (ExceptionTranslator exceptionTranslator : exceptionTranslators) { + ResponseDTO responseDTO = exceptionTranslator.translate(throwable, code, action, message); + if (responseDTO != null) { + return responseDTO; + } + } return null; } @@ -235,15 +246,7 @@ public class DefaultGlobalExceptionHandler implements GlobalExceptionHandler { protected void logError(Throwable throwable) { String exMsg = ExceptionUtil.getMessage(throwable); - if (hasCause(throwable)) { - exMsg = exMsg + ", " + ExceptionUtil.getRootCauseMessage(throwable); - throwable = ExceptionUtil.getRootCause(throwable); - } log.error(exMsg, throwable); } - private boolean hasCause(Throwable throwable) { - return throwable.getCause() != null; - } - } \ No newline at end of file diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java b/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java new file mode 100644 index 0000000..68eab6e --- /dev/null +++ b/commons/web-common/src/main/java/com/schbrain/common/web/exception/ExceptionTranslator.java @@ -0,0 +1,23 @@ +package com.schbrain.common.web.exception; + +import com.schbrain.common.web.result.ResponseDTO; +import org.springframework.core.Ordered; + +/** + * @author liaozan + * @since 2023-06-01 + */ +@FunctionalInterface +public interface ExceptionTranslator extends Ordered { + + /** + * Translate the exception to {@link ResponseDTO} + */ + ResponseDTO translate(Throwable throwable, int code, int action, String message); + + @Override + default int getOrder() { + return Ordered.LOWEST_PRECEDENCE - 100; + } + +} \ No newline at end of file -- GitLab