目录
- 1 相关代码位置
- 2 接口JobAlarm
- 3 email 警告
- 4 JobAlarmer
1 相关代码位置
我们下载了xxl-job 的源码,找到这个alarm 目录,这个目录里面的代码就是整个项目和发送警告相关的代码,alarm 中文翻译就是警告;
整个项目里面只有alarm 目录下有关于使用email发送警告的代码
2 接口JobAlarm
这个目录下一共有3个文件,首先是这个接口,这个接口的源码是:
为什么要使用接口,因为对于告警信息进行预报,不仅仅我们可以发送email,而且还可以发送qq,微信,短信等其他的通讯;所以只要重新写一个类,实现这个接口,就可以了,当前的xxl-job,这个项目,只是支持email告警,我们可以扩展,相当于写了接口,就是可拓展性强,便于维护。
3 email 警告
我们要实现email进行警告,所以写一个类,实现上面的接口就可以了,xxl-job 这个项目就是只是 支持email,所以后续我们想要自己实现短信,就自己写一个类,实现这个接口,重写里面的方法就可以了
现在解读xxl-job 源码里面,还有email进行发送警告的代码:
看这个实现类 里面的东西:
源码里面的每一行代码,都做 了注释,直接看下面的源码
代码语言:javascript复制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 这两个类,所以在项目启动的时候,就加载这个类
这个类的作用就是
代码语言:javascript复制在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 这个人家的项目,只是实现了这一个告警
代码语言:javascript复制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;
}
}