场景描述
在现有异常捕获的基础上加入异常捕获并推送钉钉群机器人,因为我们项目中使用的全局异常捕获是组件提供的包,所以我们不能自定义全局异常处理类,因为会覆盖掉组件包中的异常处理逻辑(这部分视公司使用特性而定,可能包含AJAX请求、Zipkin链路日志处理)。所以我们要使用java语言类的继承特性,继承组件包,重写日志捕获方法,调用父类包中的日志处理逻辑,加上我们自己的扩展,以此完成该功能。
本项目中异常处理器
/**
* @Author: zhangdc
* @Date: 2021/5/27 18:30
*/
@Component
public class GlobalExceptionHandler extends 组件全局异常处理器 {
@Autowired
private DingTalkTool dingTalkTool;
//是否启用环境配置
@Value("${xxx.xxx.dingTalkEnable}")
private Boolean dingTalkIsEnable;
@Override
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception e) {
//调用父类的默认处理逻辑
ModelAndView modelAndView = super.doResolveHandlerMethodException(request, response, handlerMethod, e);
//加上我们自己的扩展
//是否启用钉钉群机器人异常推送
if (Boolean.TRUE.equals(dingTalkIsEnable)) {
try {
//推送钉钉机器人通知
dingTalkTool.sendDingTalkMsg();
} catch (ApiException apiException) {
apiException.printStackTrace();
}
}
return modelAndView;
}
}
dingTalk工具
/**
* @Author: zhangdc
* @Date: 2021/5/26 15:30
*/
@Component
@Slf4j
public class DingTalkTool {
//zipkinURL
@Value("${xxx.xxx.zipkinURL}")
private String zipkinURL;
//Webhook
@Value("${xxx.xxx.dingTalkWebhook}")
private String dingTalkWebhook;
//阿波罗配置信息获取
private static final ConfigUtil CONFIG = ApolloInjector.getInstance(ConfigUtil.class);
private static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String MSGTYPE = "markdown";
private static final String TITLE = "监控报警通知";
public void sendDingTalkMsg() throws ApiException {
//url为钉钉机器人webHook地址
DefaultDingTalkClient client = new DefaultDingTalkClient(dingTalkWebhook);
//构建钉钉消息
OapiRobotSendRequest request = buildMeaages();
//发送请求到钉钉
OapiRobotSendResponse response = client.execute(request);
log.info("=====================钉钉机器人发送消息{}", response.getErrcode());
}
private OapiRobotSendRequest buildMeaages() {
OapiRobotSendRequest request = new OapiRobotSendRequest();
//通过阿波罗获取环境信息
Env env = CONFIG.getApolloEnv();
//获取链路
String traceId = ZipkinUtils.getTraceId(null);
//获取当前线程用户信息
UserInfoEntity userInfo = LoginDataHelper.getUserInfo();
//获取当前请求对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest req = attributes.getRequest();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(DATEFORMAT);
request.setMsgtype(MSGTYPE);
//初始化发送的markdown信息
OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
markdown.setTitle(TITLE);
markdown.setText("## 监控报警通知\n" +
"\n" +
"> 环境:\n" + env + "\n" +
"\n" +
"> 请求方式:\n" + req.getMethod() + "\n" +
"\n" +
"> 请求地址:\n" + req.getRequestURI() + "\n" +
"\n" +
"> 操作人:" + userInfo.getPersonName() + "\n" +
"\n" +
"> email:\n" + userInfo.getEmail() + "\n" +
"\n" +
"> 异常时间:\n" + sdf.format(date) + "\n" +
"\n" +
"> zipkinURL:\n" + zipkinURL + traceId);
request.setMarkdown(markdown);
return request;
}
}
至此我们已经实现了将异常信息推送至钉钉群的功能,并且包含了开关、多环境的切换,可配置化增强。
以下是钉钉机器人截图: