:spakles: Merge pull request #15 from lingting-gzm/master
新增异常通知功能,默认不处理
This commit is contained in:
@@ -1,38 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ballcat-common</artifactId>
|
||||
<groupId>com.hccake</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ballcat-common</artifactId>
|
||||
<groupId>com.hccake</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ballcat-common-conf</artifactId>
|
||||
<artifactId>ballcat-common-conf</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-common-core</artifactId>
|
||||
</dependency>
|
||||
<!--mybatis plus-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-extend-ding-talk</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-spring-boot-starter-mail</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!--mybatis plus-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.hccake.ballcat.common.conf.config;
|
||||
|
||||
import com.hccake.ballcat.common.conf.exception.ExceptionHandleTypeEnum;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/6/12 0:15
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "ballcat.exception")
|
||||
public class ExceptionHandleConfig {
|
||||
/**
|
||||
* 处理类型
|
||||
*/
|
||||
private ExceptionHandleTypeEnum type = ExceptionHandleTypeEnum.NONE;
|
||||
/**
|
||||
* 通知间隔时间 单位秒 默认 5分钟
|
||||
*/
|
||||
private long time = TimeUnit.MINUTES.toSeconds(5);
|
||||
/**
|
||||
* 消息阈值 即便间隔时间没有到达设定的时间, 但是异常发生的数量达到阈值 则立即发送消息
|
||||
*/
|
||||
private long max = 5;
|
||||
/**
|
||||
* 堆栈转string 的长度
|
||||
*/
|
||||
private int length = 3000;
|
||||
/**
|
||||
* 接收异常通知邮件的邮箱
|
||||
*/
|
||||
private Set<String> receiveEmails = new HashSet<>();
|
||||
}
|
||||
@@ -1,8 +1,18 @@
|
||||
package com.hccake.ballcat.common.conf.exception;
|
||||
|
||||
import com.hccake.ballcat.common.core.exception.handler.DefaultGlobalExceptionHandler;
|
||||
import com.hccake.ballcat.common.conf.config.ExceptionHandleConfig;
|
||||
import com.hccake.ballcat.common.conf.exception.handler.DefaultGlobalExceptionHandler;
|
||||
import com.hccake.ballcat.common.conf.exception.handler.DingTalkGlobalExceptionHandler;
|
||||
import com.hccake.ballcat.common.conf.exception.handler.MailGlobalExceptionHandler;
|
||||
import com.hccake.ballcat.common.core.exception.handler.GlobalExceptionHandler;
|
||||
import com.hccake.ballcat.common.mail.service.MailSender;
|
||||
import com.hccake.extend.ding.talk.DingTalkSender;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
@@ -13,29 +23,60 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
||||
* @date 2019/10/15 18:20
|
||||
*/
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class ExceptionHandleAutoConfiguration {
|
||||
@Value("${spring.application.name}")
|
||||
private String applicationName;
|
||||
|
||||
/**
|
||||
* 默认的日志处理器
|
||||
* @return DefaultExceptionHandler
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(GlobalExceptionHandler.class)
|
||||
public GlobalExceptionHandler globalExceptionHandler(){
|
||||
return new DefaultGlobalExceptionHandler();
|
||||
}
|
||||
/**
|
||||
* 默认的日志处理器
|
||||
*
|
||||
* @return DefaultExceptionHandler
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(GlobalExceptionHandler.class)
|
||||
@ConditionalOnProperty(prefix = "ballcat.exception", name = "type", havingValue = "NONE")
|
||||
public GlobalExceptionHandler defaultGlobalExceptionHandler() {
|
||||
return new DefaultGlobalExceptionHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* 钉钉消息通知的日志处理器
|
||||
*
|
||||
* @author lingting 2020-06-12 00:32:40
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(GlobalExceptionHandler.class)
|
||||
@ConditionalOnProperty(prefix = "ballcat.exception", name = "type", havingValue = "DING_TALK")
|
||||
public GlobalExceptionHandler dingTalkGlobalExceptionHandler(ExceptionHandleConfig exceptionHandleConfig, ApplicationContext context) {
|
||||
return new DingTalkGlobalExceptionHandler(exceptionHandleConfig, context.getBean(DingTalkSender.class), applicationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮件消息通知的日志处理器
|
||||
*
|
||||
* @author lingting 2020-06-12 00:32:40
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnClass(MailSender.class)
|
||||
@ConditionalOnMissingBean(GlobalExceptionHandler.class)
|
||||
@ConditionalOnProperty(prefix = "ballcat.exception", name = "type", havingValue = "MAIL")
|
||||
public GlobalExceptionHandler mailGlobalExceptionHandler(ExceptionHandleConfig exceptionHandleConfig, ApplicationContext context) {
|
||||
return new MailGlobalExceptionHandler(exceptionHandleConfig, context.getBean(MailSender.class), applicationName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 默认的日志处理器
|
||||
* @return DefaultExceptionHandler
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(GlobalExceptionHandlerResolver.class)
|
||||
public GlobalExceptionHandlerResolver globalExceptionHandlerResolver(GlobalExceptionHandler globalExceptionHandler){
|
||||
return new GlobalExceptionHandlerResolver(globalExceptionHandler);
|
||||
}
|
||||
/**
|
||||
* 默认的日志处理器
|
||||
*
|
||||
* @return DefaultExceptionHandler
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(GlobalExceptionHandlerResolver.class)
|
||||
public GlobalExceptionHandlerResolver globalExceptionHandlerResolver(GlobalExceptionHandler globalExceptionHandler) {
|
||||
return new GlobalExceptionHandlerResolver(globalExceptionHandler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.hccake.ballcat.common.conf.exception;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 异常处理类型
|
||||
*
|
||||
* @author lingting 2020/6/12 0:18
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ExceptionHandleTypeEnum {
|
||||
/**
|
||||
* 异常处理通知类型 说明
|
||||
*/
|
||||
NONE("不通知"),
|
||||
DING_TALK("通过钉钉通知"),
|
||||
MAIL("邮件通知"),
|
||||
;
|
||||
private final String text;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.hccake.ballcat.common.conf.exception;
|
||||
|
||||
import com.hccake.ballcat.common.core.exception.handler.GlobalExceptionHandler;
|
||||
import com.hccake.ballcat.common.core.exception.BusinessException;
|
||||
import com.hccake.ballcat.common.core.exception.handler.GlobalExceptionHandler;
|
||||
import com.hccake.ballcat.common.core.result.R;
|
||||
import com.hccake.ballcat.common.core.result.SystemResultCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*
|
||||
* @author Hccake
|
||||
*/
|
||||
@Slf4j
|
||||
@@ -31,12 +32,13 @@ public class GlobalExceptionHandlerResolver {
|
||||
|
||||
/**
|
||||
* 全局异常捕获
|
||||
*
|
||||
* @param e the e
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public R handleGlobalException(Exception e) {
|
||||
public R<String> handleGlobalException(Exception e) {
|
||||
log.error("全局异常信息 ex={}", e.getMessage(), e);
|
||||
globalExceptionHandler.handle(e);
|
||||
return R.failed(SystemResultCode.SERVER_ERROR, e.getLocalizedMessage());
|
||||
@@ -47,12 +49,13 @@ public class GlobalExceptionHandlerResolver {
|
||||
* 自定义业务异常捕获
|
||||
* 业务异常响应码推荐使用200
|
||||
* 用 result 结构中的code做为业务错误码标识
|
||||
*
|
||||
* @param e the e
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public R handleBallCatException(BusinessException e) {
|
||||
public R<String> handleBallCatException(BusinessException e) {
|
||||
log.error("自定义异常信息 ex={}", e.getMessage(), e);
|
||||
globalExceptionHandler.handle(e);
|
||||
return R.failed(e.getCode(), e.getMsg());
|
||||
@@ -67,7 +70,7 @@ public class GlobalExceptionHandlerResolver {
|
||||
*/
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public R handleAccessDeniedException(AccessDeniedException e) {
|
||||
public R<String> handleAccessDeniedException(AccessDeniedException e) {
|
||||
String msg = SpringSecurityMessageSource.getAccessor()
|
||||
.getMessage("AbstractAccessDecisionManager.accessDenied"
|
||||
, e.getMessage());
|
||||
@@ -84,13 +87,13 @@ public class GlobalExceptionHandlerResolver {
|
||||
*/
|
||||
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleBodyValidException(Exception exception) {
|
||||
public R<String> handleBodyValidException(Exception exception) {
|
||||
List<FieldError> fieldErrors;
|
||||
if(exception instanceof BindException){
|
||||
BindException bindException = (BindException)exception;
|
||||
if (exception instanceof BindException) {
|
||||
BindException bindException = (BindException) exception;
|
||||
fieldErrors = bindException.getBindingResult().getFieldErrors();
|
||||
}else{
|
||||
MethodArgumentNotValidException e = (MethodArgumentNotValidException)exception;
|
||||
} else {
|
||||
MethodArgumentNotValidException e = (MethodArgumentNotValidException) exception;
|
||||
fieldErrors = e.getBindingResult().getFieldErrors();
|
||||
}
|
||||
|
||||
@@ -105,17 +108,17 @@ public class GlobalExceptionHandlerResolver {
|
||||
/**
|
||||
* 单体参数校验异常
|
||||
* validation Exception
|
||||
*
|
||||
* @param e the e
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler(ValidationException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleValidationException(Exception e) {
|
||||
public R<String> handleValidationException(Exception e) {
|
||||
log.error("参数绑定异常 ex={}", e.getMessage(), e);
|
||||
globalExceptionHandler.handle(e);
|
||||
return R.failed(SystemResultCode.BAD_REQUEST, e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.hccake.ballcat.common.conf.exception.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 异常通知消息
|
||||
*
|
||||
* @author lingting 2020/6/12 16:07
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
public class ExceptionMessage {
|
||||
/**
|
||||
* 消息
|
||||
*/
|
||||
private String message;
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private int number;
|
||||
/**
|
||||
* 堆栈
|
||||
*/
|
||||
private String stack;
|
||||
/**
|
||||
* 最新的触发时间
|
||||
*/
|
||||
private String time;
|
||||
/**
|
||||
* 机器地址
|
||||
*/
|
||||
private String mac;
|
||||
/**
|
||||
* 线程id
|
||||
*/
|
||||
private long threadId;
|
||||
/**
|
||||
* 服务名
|
||||
*/
|
||||
private String applicationName;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "服务名称:" + applicationName
|
||||
+ "\n机器地址:" + mac
|
||||
+ "\n触发时间:" + time
|
||||
+ "\n线程id:" + threadId
|
||||
+ "\n数量:" + number
|
||||
+ "\n堆栈:" + stack;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.hccake.ballcat.common.conf.exception.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 异常消息通知响应
|
||||
*
|
||||
* @author lingting 2020/6/12 19:07
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
public class ExceptionNoticeResponse {
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private boolean success;
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String errMsg;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.hccake.ballcat.common.conf.exception.handler;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.date.TimeInterval;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import com.hccake.ballcat.common.conf.config.ExceptionHandleConfig;
|
||||
import com.hccake.ballcat.common.conf.exception.domain.ExceptionMessage;
|
||||
import com.hccake.ballcat.common.conf.exception.domain.ExceptionNoticeResponse;
|
||||
import com.hccake.ballcat.common.core.exception.handler.GlobalExceptionHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 消息通知顶层类
|
||||
*
|
||||
* @author lingting 2020/6/12 0:35
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractNoticeGlobalExceptionHandler extends Thread implements GlobalExceptionHandler {
|
||||
protected final ExceptionHandleConfig config;
|
||||
/**
|
||||
* 通知消息存放 e.message 堆栈信息
|
||||
*/
|
||||
private Map<String, ExceptionMessage> messages = new ConcurrentHashMap<>(10);
|
||||
/**
|
||||
* 异常发生数
|
||||
*/
|
||||
private long number = 0;
|
||||
/**
|
||||
* 用来当做锁
|
||||
*/
|
||||
private final String lock = "";
|
||||
/**
|
||||
* 本地物理地址
|
||||
*/
|
||||
private String mac;
|
||||
private final String applicationName;
|
||||
|
||||
public AbstractNoticeGlobalExceptionHandler(ExceptionHandleConfig config, String applicationName) {
|
||||
this.config = config;
|
||||
this.applicationName = applicationName;
|
||||
try {
|
||||
byte[] mac = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()).getHardwareAddress();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < mac.length; i++) {
|
||||
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
|
||||
}
|
||||
this.mac = sb.toString();
|
||||
} catch (Exception e) {
|
||||
mac = "获取失败!";
|
||||
}
|
||||
|
||||
this.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Throwable e) {
|
||||
synchronized (lock) {
|
||||
number++;
|
||||
ExceptionMessage message = messages.get(e.getMessage());
|
||||
|
||||
if (message == null) {
|
||||
message = new ExceptionMessage().setNumber(0).setMac(mac).setApplicationName(applicationName);
|
||||
}
|
||||
|
||||
message.setNumber(message.getNumber() + 1)
|
||||
.setStack(ExceptionUtil.stacktraceToString(e, config.getLength()).replaceAll("\\r", ""))
|
||||
.setTime(DateUtil.now())
|
||||
.setThreadId(Thread.currentThread().getId());
|
||||
messages.put(e.getMessage(), message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.setName("exception-notice-thread-" + config.getType().name());
|
||||
log.debug("异常消息通知线程启动!");
|
||||
TimeInterval interval = new TimeInterval();
|
||||
while (true) {
|
||||
try {
|
||||
if (interval.intervalSecond() >= config.getTime() || number >= config.getMax()) {
|
||||
if (messages.size() == 0) {
|
||||
interval.restart();
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, ExceptionMessage> sendMessages;
|
||||
synchronized (lock) {
|
||||
sendMessages = messages;
|
||||
messages = new ConcurrentHashMap<>(10);
|
||||
number = 0;
|
||||
interval.restart();
|
||||
}
|
||||
sendMessages.forEach((k, v) -> {
|
||||
ExceptionNoticeResponse response = send(v);
|
||||
if (!response.isSuccess()) {
|
||||
log.error("消息通知发送失败! msg: {}", response.getErrMsg());
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("消息通知异常!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送通知
|
||||
*
|
||||
* @param sendMessage 发送的消息
|
||||
* @return 返回消息发送状态,如果发送失败需要设置失败信息
|
||||
* @author lingting 2020-06-12 00:37:23
|
||||
*/
|
||||
public abstract ExceptionNoticeResponse send(ExceptionMessage sendMessage);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.hccake.ballcat.common.conf.exception.handler;
|
||||
|
||||
import com.hccake.ballcat.common.core.exception.handler.GlobalExceptionHandler;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* @version 1.0
|
||||
* @date 2019/10/18 17:06
|
||||
* 默认的异常日志处理类
|
||||
*/
|
||||
public class DefaultGlobalExceptionHandler implements GlobalExceptionHandler {
|
||||
/**
|
||||
* 在此处理日志
|
||||
* 默认什么都不处理
|
||||
*
|
||||
* @param throwable 异常信息
|
||||
*/
|
||||
@Override
|
||||
public void handle(Throwable throwable) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.hccake.ballcat.common.conf.exception.handler;
|
||||
|
||||
import com.hccake.ballcat.common.conf.config.ExceptionHandleConfig;
|
||||
import com.hccake.ballcat.common.conf.exception.domain.ExceptionMessage;
|
||||
import com.hccake.ballcat.common.conf.exception.domain.ExceptionNoticeResponse;
|
||||
import com.hccake.extend.ding.talk.DingTalkResponse;
|
||||
import com.hccake.extend.ding.talk.DingTalkSender;
|
||||
import com.hccake.extend.ding.talk.message.DingTalkTextMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 钉钉消息通知
|
||||
*
|
||||
* @author lingting 2020/6/12 0:25
|
||||
*/
|
||||
@Slf4j
|
||||
public class DingTalkGlobalExceptionHandler extends AbstractNoticeGlobalExceptionHandler {
|
||||
private final DingTalkSender sender;
|
||||
|
||||
public DingTalkGlobalExceptionHandler(ExceptionHandleConfig config, DingTalkSender sender, String applicationName) {
|
||||
super(config, applicationName);
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExceptionNoticeResponse send(ExceptionMessage sendMessage) {
|
||||
DingTalkResponse response = sender.sendMessage(new DingTalkTextMessage().setContent(sendMessage.toString()));
|
||||
return new ExceptionNoticeResponse()
|
||||
.setErrMsg(response.getResponse())
|
||||
.setSuccess(response.isSuccess());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.hccake.ballcat.common.conf.exception.handler;
|
||||
|
||||
import com.hccake.ballcat.common.conf.config.ExceptionHandleConfig;
|
||||
import com.hccake.ballcat.common.conf.exception.domain.ExceptionMessage;
|
||||
import com.hccake.ballcat.common.conf.exception.domain.ExceptionNoticeResponse;
|
||||
import com.hccake.ballcat.common.mail.dto.MailDTO;
|
||||
import com.hccake.ballcat.common.mail.service.MailSender;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 钉钉消息通知
|
||||
*
|
||||
* @author lingting 2020/6/12 0:25
|
||||
*/
|
||||
@Slf4j
|
||||
public class MailGlobalExceptionHandler extends AbstractNoticeGlobalExceptionHandler {
|
||||
private final MailSender sender;
|
||||
|
||||
public MailGlobalExceptionHandler(ExceptionHandleConfig config, MailSender sender, String applicationName) {
|
||||
super(config, applicationName);
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExceptionNoticeResponse send(ExceptionMessage sendMessage) {
|
||||
MailDTO mail = new MailDTO();
|
||||
mail.setTo(String.join(MailDTO.MAIL_DELIMITER, config.getReceiveEmails()));
|
||||
mail.setSubject("异常警告");
|
||||
mail.setContent(sendMessage.toString());
|
||||
sender.sendMail(mail);
|
||||
// 邮箱发送失败会抛出异常,否则视作发送成功
|
||||
return new ExceptionNoticeResponse().setSuccess(mail.getSuccess()).setErrMsg(mail.getErrorMsg());
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.hccake.ballcat.common.conf.config.JacksonConfig,\
|
||||
com.hccake.ballcat.common.conf.exception.ExceptionHandleAutoConfiguration,\
|
||||
com.hccake.ballcat.common.conf.mybatis.MybatisPlusConfig,\
|
||||
com.hccake.ballcat.common.conf.web.WebMvcConfig
|
||||
com.hccake.ballcat.common.conf.web.WebMvcConfig,\
|
||||
com.hccake.ballcat.common.conf.config.ExceptionHandleConfig
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.hccake.ballcat.common.core.exception.handler;
|
||||
|
||||
/**
|
||||
* @author Hccake
|
||||
* @version 1.0
|
||||
* @date 2019/10/18 17:06
|
||||
* 默认的异常日志处理类
|
||||
*/
|
||||
public class DefaultGlobalExceptionHandler implements GlobalExceptionHandler {
|
||||
/**
|
||||
* 在此处理日志
|
||||
* 默认什么都不处理
|
||||
* @param throwable 异常信息
|
||||
*/
|
||||
@Override
|
||||
public void handle(Throwable throwable) {}
|
||||
}
|
||||
@@ -29,6 +29,10 @@ public class MarkdownBuilder {
|
||||
*/
|
||||
private StringBuilder lineTextBuilder;
|
||||
|
||||
public MarkdownBuilder() {
|
||||
this.lineTextBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加自定义内容
|
||||
*
|
||||
@@ -153,14 +157,21 @@ public class MarkdownBuilder {
|
||||
* @author lingting 2020-06-10 22:58:04
|
||||
*/
|
||||
public MarkdownBuilder quote(String content) {
|
||||
forceLineBreak();
|
||||
lineTextBuilder.append(QUOTE_PREFIX).append(content);
|
||||
// 下面得换行两次
|
||||
forceLineBreak();
|
||||
forceLineBreak();
|
||||
lineBreak();
|
||||
this.content.add(QUOTE_PREFIX + content);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加引用后 强制换行
|
||||
*
|
||||
* @author lingting 2020-06-12 15:50:29
|
||||
*/
|
||||
public MarkdownBuilder quoteLineBreak(String content) {
|
||||
quote(content);
|
||||
return forceLineBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制换行
|
||||
*
|
||||
@@ -191,7 +202,8 @@ public class MarkdownBuilder {
|
||||
* @author lingting 2020-06-10 22:55:39
|
||||
*/
|
||||
private MarkdownBuilder title(int i, String content) {
|
||||
lineTextBuilder = new StringBuilder();
|
||||
// 如果当前操作行已有字符,需要换行
|
||||
lineBreak();
|
||||
for (int j = 0; j < i; j++) {
|
||||
lineTextBuilder.append(TITLE_PREFIX);
|
||||
}
|
||||
@@ -231,12 +243,9 @@ public class MarkdownBuilder {
|
||||
* @author lingting 2020-06-11 22:55:40
|
||||
*/
|
||||
public String build() {
|
||||
if (lineTextBuilder.length() != 0) {
|
||||
// 最后一个操作的 如果不为空,也需要添加进入list
|
||||
content.add(lineTextBuilder.toString());
|
||||
}
|
||||
lineBreak();
|
||||
StringBuilder res = new StringBuilder();
|
||||
content.forEach(content -> res.append(content).append("\\n"));
|
||||
content.forEach(content -> res.append(content).append(" \n"));
|
||||
return res.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.hccake.ballcat.common.core.util;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lingting 2020/6/12 16:36
|
||||
*/
|
||||
@Component
|
||||
public class ApplicationContextUtil implements ApplicationContextAware {
|
||||
private static ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
context = applicationContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取环境
|
||||
*
|
||||
* @author lingting 2020-06-12 16:38:56
|
||||
*/
|
||||
public Environment getEnvironment() {
|
||||
return context.getEnvironment();
|
||||
}
|
||||
|
||||
public ApplicationContext getContext() {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.hccake.ballcat.common.core.util.ApplicationContextUtil
|
||||
Reference in New Issue
Block a user