diff --git a/pom.xml b/pom.xml index 5c6adba..c1a5d7e 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,7 @@ udf-starter-core + udf-starter-exception-alert udf-starter-swagger2 udf-starter-rms udf-starter-cors @@ -78,6 +79,12 @@ udf-starter-core ${udf-starter.version} + + + org.itkk.udf + udf-starter-exception-alert + ${udf-starter.version} + org.itkk.udf diff --git a/udf-starter-core/src/main/java/org/itkk/udf/core/RestResponse.java b/udf-starter-core/src/main/java/org/itkk/udf/core/RestResponse.java index 894ce6b..1fee9a8 100644 --- a/udf-starter-core/src/main/java/org/itkk/udf/core/RestResponse.java +++ b/udf-starter-core/src/main/java/org/itkk/udf/core/RestResponse.java @@ -3,6 +3,7 @@ package org.itkk.udf.core; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.ToString; import org.itkk.udf.core.exception.ErrorResult; import org.springframework.http.HttpStatus; @@ -16,6 +17,7 @@ import java.util.UUID; */ @ApiModel(description = "响应消息体") @Data +@ToString public class RestResponse implements Serializable { /** diff --git a/udf-starter-core/src/main/java/org/itkk/udf/core/exception/alert/IExceptionAlert.java b/udf-starter-core/src/main/java/org/itkk/udf/core/exception/alert/IExceptionAlert.java new file mode 100644 index 0000000..7784b0f --- /dev/null +++ b/udf-starter-core/src/main/java/org/itkk/udf/core/exception/alert/IExceptionAlert.java @@ -0,0 +1,15 @@ +package org.itkk.udf.core.exception.alert; + +import org.itkk.udf.core.RestResponse; + +/** + * IExceptionAlert + */ +public interface IExceptionAlert { + /** + * alert + * + * @param errorResponse errorResponse + */ + void alert(RestResponse errorResponse); +} diff --git a/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionController.java b/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionController.java index aa3d13f..5aca299 100644 --- a/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionController.java +++ b/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionController.java @@ -6,6 +6,7 @@ import org.itkk.udf.core.RestResponse; import org.itkk.udf.core.exception.AuthException; import org.itkk.udf.core.exception.ErrorResult; import org.itkk.udf.core.exception.PermissionException; +import org.itkk.udf.core.exception.alert.IExceptionAlert; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.web.AbstractErrorController; import org.springframework.boot.autoconfigure.web.ErrorAttributes; @@ -66,6 +67,12 @@ public class ExceptionController extends AbstractErrorController { @Autowired private ExceptionCors exceptionCors; + /** + * iExceptionAlert + */ + @Autowired(required = false) + private IExceptionAlert iExceptionAlert; + /** * Create a new {@link ExceptionController} instance. * @@ -115,6 +122,11 @@ public class ExceptionController extends AbstractErrorController { model.put(KEY_MESSAGE, restResponse.getError().getMessage()); response.setStatus(status.value()); ModelAndView modelAndView = resolveErrorView(request, response, status, model); + //发出通知 + if (iExceptionAlert != null) { + iExceptionAlert.alert(restResponse); + } + log.error(restResponse.getId() + ":" + restResponse.toString()); return (modelAndView == null ? new ModelAndView("error", model) : modelAndView); } @@ -134,6 +146,11 @@ public class ExceptionController extends AbstractErrorController { Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); RestResponse restResponse = getRestResponse(request, status, body); + //发出通知 + if (iExceptionAlert != null) { + iExceptionAlert.alert(restResponse); + } + log.error(restResponse.getId() + ":" + restResponse.toString()); return new ResponseEntity<>(restResponse, HttpStatus.valueOf(Integer.parseInt(restResponse.getCode()))); } diff --git a/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionHandle.java b/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionHandle.java index aaa28ae..b86d3de 100644 --- a/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionHandle.java +++ b/udf-starter-core/src/main/java/org/itkk/udf/core/exception/handle/ExceptionHandle.java @@ -8,6 +8,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.itkk.udf.core.ApplicationConfig; import org.itkk.udf.core.RestResponse; import org.itkk.udf.core.exception.*; +import org.itkk.udf.core.exception.alert.IExceptionAlert; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -54,6 +55,12 @@ public class ExceptionHandle extends ResponseEntityExceptionHandler { @Autowired private HttpServletResponse httpServletResponse; + /** + * iExceptionAlert + */ + @Autowired(required = false) + private IExceptionAlert iExceptionAlert; + /** * 异常处理 * @@ -100,8 +107,13 @@ public class ExceptionHandle extends ResponseEntityExceptionHandler { throw new SystemRuntimeException(e); } } - log.error(ex.getClass().getName(), ex); - return super.handleExceptionInternal(ex, new RestResponse<>(localHttpStatus, errorResult), headers, localHttpStatus, request); + RestResponse restResponse = new RestResponse<>(localHttpStatus, errorResult); + //发出通知 + if (iExceptionAlert != null) { + iExceptionAlert.alert(restResponse); + } + log.error(restResponse.getId(), ex); + return super.handleExceptionInternal(ex, restResponse, headers, localHttpStatus, request); } /** diff --git a/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlert.java b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlert.java new file mode 100644 index 0000000..4baa96b --- /dev/null +++ b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlert.java @@ -0,0 +1,106 @@ +package org.itkk.udf.exception.alert; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.itkk.udf.amqp.rabbitmq.Rabbitmq; +import org.itkk.udf.amqp.rabbitmq.RabbitmqMessage; +import org.itkk.udf.core.RestResponse; +import org.itkk.udf.core.exception.alert.IExceptionAlert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * ExceptionAlert + */ +@Component +@Slf4j +public class ExceptionAlert implements IExceptionAlert { + + /** + * exceptionAlertProperties + */ + @Autowired + private ExceptionAlertProperties exceptionAlertProperties; + + /** + * 描述 : springApplicationName + */ + @Value("${spring.application.name}") + private String springApplicationName; + + /** + * port + */ + @Value("${server.port}") + private Integer port; + + /** + * profiles + */ + @Value("${spring.profiles.active}") + private String profiles; + + /** + * 描述 : rabbitmq + */ + @Autowired + private Rabbitmq rabbitmq; + + @Override + public void alert(RestResponse errorResponse) { //NOSONAR + //开关打开,才进行异常信息发送 + if (exceptionAlertProperties.getEnable()) { + //发送消息标志位 + boolean sendFlg = true; + //逻辑判断 + if (errorResponse.getError() == null) { //error的空判断 + log.warn("errorResponse error is null"); + sendFlg = false; + } + if (StringUtils.isNotBlank(errorResponse.getError().getType()) && StringUtils.isNotBlank(exceptionAlertProperties.getExcludeType())) { //类型的排除判断 + String[] excludeTypes = exceptionAlertProperties.getExcludeType().split(","); + for (String excludeType : excludeTypes) { + if (errorResponse.getError().getType().contains(excludeType)) { + log.warn("exclude type : " + excludeType); + sendFlg = false; + } + } + } + if (StringUtils.isNotBlank(errorResponse.getError().getMessage()) && StringUtils.isNotBlank(exceptionAlertProperties.getExcludeMessage())) { //信息的排除判断 + String[] excludeMessages = exceptionAlertProperties.getExcludeMessage().split(","); + for (String excludeMessage : excludeMessages) { + if (errorResponse.getError().getMessage().contains(excludeMessage)) { + log.warn("exclude message : " + excludeMessage); + sendFlg = false; + } + } + } + if (StringUtils.isNotBlank(errorResponse.getError().getStackTrace()) && StringUtils.isNotBlank(exceptionAlertProperties.getExcludeStackTrace())) { //堆栈的排除判断 + String[] excludeStackTraces = exceptionAlertProperties.getExcludeStackTrace().split(","); + for (String excludeStackTrace : excludeStackTraces) { + if (errorResponse.getError().getStackTrace().contains(excludeStackTrace)) { + log.warn("exclude stackTrace : " + excludeStackTrace); + sendFlg = false; + } + } + } + //发送消息 + if (sendFlg) { + //构造消息头 + Map header = new HashMap<>(); + header.put("springApplicationName", springApplicationName); + header.put("port", String.valueOf(port)); + header.put("profiles", profiles); + //构造消息 + RabbitmqMessage> alert = new RabbitmqMessage<>(header, errorResponse); + //发送消息 + rabbitmq.convertAndSend(ExceptionAlertConstant.EXCHANGE_EXCEPTION_ALERT.class.getSimpleName(), ExceptionAlertConstant.EXCHANGE_EXCEPTION_ALERT.ALERT.name(), alert); + } + } + } + +} diff --git a/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertConfig.java b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertConfig.java new file mode 100644 index 0000000..badafa3 --- /dev/null +++ b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertConfig.java @@ -0,0 +1,35 @@ +package org.itkk.udf.exception.alert; + +import org.springframework.amqp.core.DirectExchange; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 描述 : ExceptionAlertConfig + * + * @author wangkang + */ +@Configuration +public class ExceptionAlertConfig { + + /** + * exchangeExceptionAlert + * + * @return DirectExchange + */ + @Bean + public DirectExchange exchangeExceptionAlert() { + return new DirectExchange(ExceptionAlertConstant.EXCHANGE_EXCEPTION_ALERT.class.getSimpleName(), true, false); + } + + /** + * exchangeExceptionAlertDlx + * + * @return DirectExchange + */ + @Bean + public DirectExchange exchangeExceptionAlertDlx() { + return new DirectExchange(ExceptionAlertConstant.EXCHANGE_EXCEPTION_ALERT_DLX.class.getSimpleName(), true, false); + } + +} diff --git a/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertConstant.java b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertConstant.java new file mode 100644 index 0000000..43aea4f --- /dev/null +++ b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertConstant.java @@ -0,0 +1,36 @@ +package org.itkk.udf.exception.alert; + +/** + * 描述 : ExceptionAlertConstant + * + * @author Administrator + */ +public class ExceptionAlertConstant { + + /** + * (EXCHANGE)消息记录 + */ + public enum EXCHANGE_EXCEPTION_ALERT { + /** + * 提醒 + */ + ALERT + } + + /** + * (EXCHANGE)异常提醒(死信) + */ + public enum EXCHANGE_EXCEPTION_ALERT_DLX { + /** + * 提醒 + */ + ALERT_DLX + } + + /** + * 描述 : 私有化构造函数 + */ + private ExceptionAlertConstant() { + } + +} diff --git a/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertProperties.java b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertProperties.java new file mode 100644 index 0000000..514352b --- /dev/null +++ b/udf-starter-exception-alert/src/main/java/org/itkk/udf/exception/alert/ExceptionAlertProperties.java @@ -0,0 +1,35 @@ +package org.itkk.udf.exception.alert; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * ExceptionAlertProperties + */ +@Component +@ConfigurationProperties(prefix = "org.itkk.exception.alert.properties") +@Data +public class ExceptionAlertProperties { + + /** + * enable + */ + private Boolean enable = true; + + /** + * excludeType + */ + private String excludeType; + + /** + * excludeMessage + */ + private String excludeMessage; + + /** + * excludeStackTrace + */ + private String excludeStackTrace; + +}