当前位置:网站首页>xxl-job 实现email发送警告的代码解析(一行一行代码解读)
xxl-job 实现email发送警告的代码解析(一行一行代码解读)
2022-08-03 17:41:00 【一天不写程序难受】
目录
1 相关代码位置
我们下载了xxl-job 的源码,找到这个alarm 目录,这个目录里面的代码就是整个项目和发送警告相关的代码,alarm 中文翻译就是警告;
整个项目里面只有alarm 目录下有关于使用email发送警告的代码
2 接口JobAlarm
这个目录下一共有3个文件,首先是这个接口,这个接口的源码是:
为什么要使用接口,因为对于告警信息进行预报,不仅仅我们可以发送email,而且还可以发送qq,微信,短信等其他的通讯;所以只要重新写一个类,实现这个接口,就可以了,当前的xxl-job,这个项目,只是支持email告警,我们可以扩展,相当于写了接口,就是可拓展性强,便于维护。
3 email 警告
我们要实现email进行警告,所以写一个类,实现上面的接口就可以了,xxl-job 这个项目就是只是 支持email,所以后续我们想要自己实现短信,就自己写一个类,实现这个接口,重写里面的方法就可以了
现在解读xxl-job 源码里面,还有email进行发送警告的代码:
看这个实现类 里面的东西:
源码里面的每一行代码,都做 了注释,直接看下面的源码
package com.xxl.job.admin.core.alarm.impl;
import com.xxl.job.admin.core.alarm.JobAlarm;
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.core.biz.model.ReturnT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.mail.internet.MimeMessage;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* job alarm by email
* 通过电子邮件通知 告警信息
* @author xuxueli 2020-01-19
*/
@Component
public class EmailJobAlarm implements JobAlarm {
// 定义当前的 日志对象
private static Logger logger = LoggerFactory.getLogger(EmailJobAlarm.class);
/**
* fail alarm
* 失败报警 逻辑
* 开始进行 报警的逻辑
* @param jobLog
*/
@Override
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog){
// 定义报警结果状态
boolean alarmResult = true;
// send monitor email
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
// 如果 任务信息不为空,报警邮件不为空
// alarmContent 报警内容
String alarmContent = "Alarm Job LogId=" + jobLog.getId(); // 记录日志id
if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) {
// 如果 日志的 调度结果 不成功 ,内容保存 调度-日志
alarmContent += "<br>TriggerMsg=<br>" + jobLog.getTriggerMsg();
}
if (jobLog.getHandleCode()>0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) {
// 如果 执行-状态 不为空,内容保存 执行-日志具体结果信息
alarmContent += "<br>HandleCode=" + jobLog.getHandleMsg();
}
// email info
// 根据项目 id 查询出 执行器(项目)
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(Integer.valueOf(info.getJobGroup()));
// 警告信息 发送人
String personal = I18nUtil.getString("admin_name_full");// 值为这个: 分布式任务调度平台XXL-JOB
// 告警信息 标题
String title = I18nUtil.getString("jobconf_monitor"); // 值为这个:任务调度中心监控报警
// 根据模板,填充信息
String content = MessageFormat.format(loadEmailJobAlarmTemplate(),
group!=null?group.getTitle():"null", // 项目名称
info.getId(), // 任务id
info.getJobDesc(),// 任务 描述
alarmContent); // 报警内容
// 多个 报警邮件
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
for (String email: emailSet) {
// 遍历多个报警邮件
// make mail
try {
// 创建邮件发送者 对象
MimeMessage mimeMessage = XxlJobAdminConfig.getAdminConfig().getMailSender().createMimeMessage();
// 创建 邮件发送线程
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
// 从配置文件里面获取自己配置的发送者 的邮箱,发送者的姓名
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailFrom(), personal);
// 将邮件发送给谁
helper.setTo(email);
// 发送的标题
helper.setSubject(title);
// 发送的内容
helper.setText(content, true);
// 进行发送
XxlJobAdminConfig.getAdminConfig().getMailSender().send(mimeMessage);
} catch (Exception e) {
logger.error(">>>>>>>>>>> xxl-job, job fail alarm email send error, JobLogId:{}", jobLog.getId(), e);
alarmResult = false;
}
}
}
// 返回报警状态(是否成功报警,默认 是)
return alarmResult;
}
/**
* load email job alarm template
* 加载邮件作业告警模板,,前端的页面模板
* @return
*/
private static final String loadEmailJobAlarmTemplate(){
String mailBodyTemplate = "<h5>" + I18nUtil.getString("jobconf_monitor_detail") + ":</span>" +
"<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n" +
" <thead style=\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\" >" +
" <tr>\n" +
" <td width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobgroup") +"</td>\n" +
" <td width=\"10%\" >"+ I18nUtil.getString("jobinfo_field_id") +"</td>\n" +
" <td width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobdesc") +"</td>\n" +
" <td width=\"10%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_title") +"</td>\n" +
" <td width=\"40%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_content") +"</td>\n" +
" </tr>\n" +
" </thead>\n" +
" <tbody>\n" +
" <tr>\n" +
" <td>{0}</td>\n" +
" <td>{1}</td>\n" +
" <td>{2}</td>\n" +
" <td>"+ I18nUtil.getString("jobconf_monitor_alarm_type") +"</td>\n" +
" <td>{3}</td>\n" +
" </tr>\n" +
" </tbody>\n" +
"</table>";
return mailBodyTemplate;
}
}
4 JobAlarmer
这个类,因为继承ApplicationContextAware, InitializingBean 这两个类,所以在项目启动的时候,就加载这个类
这个类的作用就是
在JobAlarmer类中容器初始化时从spring上下文中获取
JobAlarm类的对象list:jobAlarmList,(主要代码:
applicationContext.getBeansOfType(JobAlarm.class);)
alarm方法中遍历jobAlarmList调用重写的doAlarm方法
(报警具体实现),当需要触发报警时,
只需要调用JobAlarmer类的alarm方法,
即可自动触发所有的报警实现,因xxl默认只有邮箱报警,
所本文代码只贴出了邮箱报警EmailJobAlarm类的代码,
此方式的好处是当需要其他报警方式:如短信报警,
只需要添加类实现JobAlarm接口,使用@Component注解,
并重写方法doAlarm即可,便会在JobAlarm类的alarm方法
jobAlarmList中触发调用子类实现的短信报警方法,
可拓展性强,便于维护。
这个类核心就是 从spring管理器里面获取JobAlarm 接口的所有实现类,都放到list里面,遍历这个list,实现多种方式的告警;
目前只有一个email,因为xxl-job 这个人家的项目,只是实现了这一个告警
package com.xxl.job.admin.core.alarm;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 上下文,项目初始化的时候 加载这个
*/
@Component
public class JobAlarmer implements ApplicationContextAware, InitializingBean {
// 定义 当前类 日志对象
private static Logger logger = LoggerFactory.getLogger(JobAlarmer.class);
// 上下文 管理器
private ApplicationContext applicationContext;
// 发送告警信息 list
// 多个报警类 bean对象的 集合
private List<JobAlarm> jobAlarmList;
/**
* 设置上下文
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 设置上下文
*/
@Override
public void afterPropertiesSet() throws Exception {
// 从spring管理器 里面 获取到 报警类的 bean对象
// 根据类型获取 多个bean对象
Map<String, JobAlarm> serviceBeanMap = applicationContext.getBeansOfType(JobAlarm.class);
if (serviceBeanMap != null && serviceBeanMap.size() > 0) {
jobAlarmList = new ArrayList<JobAlarm>(serviceBeanMap.values());
}
}
/**
* job alarm
*
* @param info
* @param jobLog
* @return
*/
public boolean alarm(XxlJobInfo info, XxlJobLog jobLog) {
boolean result = false;
// 如果 多个报警类 bean对象的 集合 不为空
if (jobAlarmList!=null && jobAlarmList.size()>0) {
// result = true 意味的 全部的 报警email 发放 都成功了
result = true; // success means all-success
for (JobAlarm alarm: jobAlarmList) {
// 遍历 每一个 email发送类对象
// 每一个 email发送类对象 是否发送成功
boolean resultItem = false;
try {
// 发送email
resultItem = alarm.doAlarm(info, jobLog);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
if (!resultItem) {
result = false;
}
}
}
return result;
}
}
边栏推荐
- 软件测试<用例篇>
- 被误解的 MVC 和被神化的 MVVM(一)
- 借助Web3盘活日本优质IP:UneMeta 与 OpenSea 的差异化竞争
- 走进通信:为什么4G信号满格,却上不了网呢
- SkyWalking概要介绍
- PMP考试通关宝典-敏捷专题
- 405. Convert a Number to Hexadecimal
- China Hashpower Conference Ascension Kunpeng Ecological Forum was held; Kuaishou established an independent to B business department…
- 全尺度表示的上下文非局部对齐,南科大&优图提出NAFS解决基于文本的Re ID
- JS 字符串转 GBK 编码超精简实现
猜你喜欢
随机推荐
es6新增-Generator(异步编程的解决方案2)
isNotBlank与isNotEmpty
【机器学习】机器学习基本概念/术语3
CC2530_ZigBee+华为云IOT:设计一套属于自己的冷链采集系统
使用o.execute_sql 查询很很很小的表, 要7/8秒钟, 这个怎么解决
383. Ransom Note
China Hashpower Conference Ascension Kunpeng Ecological Forum was held; Kuaishou established an independent to B business department…
借助Web3盘活日本优质IP:UneMeta 与 OpenSea 的差异化竞争
ICDAR比赛技术分享
【Deliberately practice the view of the back tube】deliberately practice
【白话模电2】二极管特性和分类
深度学习跟踪DLT (deep learning tracker)
【保姆级示例向】观察者模式
为什么我用了Redis之后,系统的性能却没有提升
2022爱分析· 银行数字化厂商全景报告
域名抢注“卷”到了表情包?ENS逆势上涨的新推力
揭秘deepin 23,从这里开始!
MySQL database account management and optimization
【技术白皮书】第一章:OCR智能文字识别新发展——深度学习的文本信息抽取
全尺度表示的上下文非局部对齐,南科大&优图提出NAFS解决基于文本的Re ID