1.2 报警信息: 二.需要增改的类和文件 2.1 只迭代调度中心xxl-job-admin的module 2.2 增改的代码内容 2.3 新增类、文件功能简介:
robot.sql 数据库语句,实际上只增加了一个字段 APIHttpClient 访问https的客户端工具 RobotData 封装了腾讯机器人接口的数据对象 RobotJobAlarm 实现任务失败时机器人报警功能 RobotTypeEnum 多个机器人id、名字、url的枚举三.具体代码 3.0 pom.xml增加以下包
3.1 新增的(这些实现发送的主要代码) 3.1.1 robot.sqlcom.alibaba fastjson1.2.54 org.apache.httpcomponents httpclient4.5.7 commons-httpclient commons-httpclient3.1 org.projectlombok lombok
xxl_job_info表增加一个字段机器人类型。
ALTER TABLE `xxl_job_info` ADD COLUMN `robot_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'NONE' AFTER `trigger_next_time`;3.1.2 APIHttpClient
这里封装了一个访问api的客户端对象,只要你new APIHttpClient(),初始化或set了apiURL,就可以通过post()或postH()访问接口,main方法中有例子,需要用自己的机器人连接来测试。
package com.xxl.job.admin.yxdiy.robot; import com.alibaba.fastjson.JSON; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.io.IOException; import java.nio.charset.StandardCharsets; @Component @ConfigurationProperties(prefix = "msg.url") public class APIHttpClient { // 接口地址 private String apiURL; private Log logger = LogFactory.getLog(this.getClass()); private static final String pattern = "yyyy-MM-dd HH:mm:ss:SSS"; private HttpClient httpClient = new DefaultHttpClient(); private HttpPost method = null; private long startTime = 0L; private long endTime = 0L; private int status = 0; public APIHttpClient() { } public APIHttpClient(String url) { setApiURL(url); } public String getApiURL() { return apiURL; } public void setApiURL(String apiURL) { this.apiURL = apiURL; method = null; if (apiURL != null) { method = new HttpPost(apiURL); } } public HttpClient getHttpClient() { return httpClient; } public void setHttpClient(HttpClient httpClient) { this.httpClient = httpClient; } public HttpPost getMethod() { if (method == null && apiURL != null) { method = new HttpPost(apiURL); } return method; } public void setMethod(HttpPost method) { this.method = method; } public String post(String parameters) { String body = null; logger.debug("parameters:" + parameters); logger.debug("apiURL:"+ apiURL); HttpPost med = getMethod(); if (med != null & parameters != null && !"".equals(parameters.trim())) { try { // 建立一个NamevaluePair数组,用于存储欲传送的参数 med.addHeader("Content-type", "application/json; charset=utf-8"); med.setHeader("Accept", "application/json"); med.setEntity(new StringEntity(parameters, StandardCharsets.UTF_8)); startTime = System.currentTimeMillis(); HttpResponse response = getHttpClient().execute(med); endTime = System.currentTimeMillis(); int statusCode = response.getStatusLine().getStatusCode(); logger.debug("statusCode:" + statusCode); logger.debug("调用API 花费时间(单位:毫秒):" + (endTime - startTime)); if (statusCode != HttpStatus.SC_OK) { logger.error("Method failed:" + response.getStatusLine()); logger.error("返回值:" + response.toString()); status = 1; } // Read the response body body = EntityUtils.toString(response.getEntity()); } catch (IOException e) { // 网络错误 status = 3; logger.error("网络错误,请检查!"); } finally { logger.debug("调用接口状态:" + status); } } return body; } public Integer postH(String parameters) { String body = null; logger.debug("parameters:" + parameters); logger.debug("apiURL:"+ apiURL); HttpPost med = getMethod(); int statusCode=-1; if (med != null & parameters != null && !"".equals(parameters.trim())) { try { // 建立一个NamevaluePair数组,用于存储欲传送的参数 med.addHeader("Content-type", "application/json; charset=utf-8"); med.setHeader("Accept", "application/json"); med.setEntity(new StringEntity(parameters, StandardCharsets.UTF_8)); startTime = System.currentTimeMillis(); HttpResponse response = getHttpClient().execute(med); endTime = System.currentTimeMillis(); statusCode = response.getStatusLine().getStatusCode(); logger.debug("statusCode:" + statusCode); logger.debug("调用API 花费时间(单位:毫秒):" + (endTime - startTime)); if (statusCode != HttpStatus.SC_OK) { logger.error("Method failed:" + response.getStatusLine()); logger.error("返回值:" + response.toString()); status = 1; } // Read the response body body = EntityUtils.toString(response.getEntity()); } catch (IOException e) { // 网络错误 status = 3; logger.error("网络错误,请检查!"); } finally { logger.debug("调用接口状态:" + status); } } return statusCode; } public static void main(String[] args) { APIHttpClient ac = new APIHttpClient("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=这里是马赛克"); String jObjStr = JSON.toJSonString( new RobotData("测试返回值", 0)); System.out.println(jObjStr); System.out.println(ac.postH(jObjStr)); } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public long getStartTime() { return startTime; } public long getEndTime() { return endTime; } }3.1.3 RobotData
封装了腾讯机器人接口的数据对象,很简单,看代码吧。
package com.xxl.job.admin.yxdiy.robot; import com.alibaba.fastjson.JSON; import lombok.Data; import java.util.Collections; import java.util.HashMap; import java.util.Map; @Data public class RobotData { String msgtype = "text"; //消息类型 Map3.1.4 RobotTypeEnumtext; //消息内容 public RobotData(String content, Integer isAtAll) { String atAll = ""; if (isAtAll == 1) { atAll = "@all"; } this.text = new HashMap<>(); text.put("content", content); text.put("mentioned_list", Collections.singletonList(atAll)); } public static String toJsonStr(RobotData rd) { return JSON.toJSonString(rd); } }
这个枚举主要有2个作用,一个是用来配置机器人的信息,一个是为了方便做I18n多语言映射。
package com.xxl.job.admin.yxdiy.robot; import com.xxl.job.admin.core.util.I18nUtil; import java.util.HashMap; import java.util.Map; public enum RobotTypeEnum { DWXF1(I18nUtil.getString("robot_type_dwxf1")), DWJH2(I18nUtil.getString("robot_type_dwjh2")), DWZB3(I18nUtil.getString("robot_type_dwzb3")), DWCS7(I18nUtil.getString("robot_type_dwcs7")), TCYJ8(I18nUtil.getString("robot_type_tcyj8")), TCJH5(I18nUtil.getString("robot_type_tcjh5")), //DIY4(I18nUtil.getString("robot_type_diy4")), NONE(I18nUtil.getString("robot_type_none")); private static final Map3.1.5 RobotJobAlarmm = new HashMap (); static { // 下面的key打码了,用之前,请将自己的机器人key写进来。 m.put("DWXF1", "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=这里是马赛克"); m.put("DWJH2", "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=这里是马赛克"); m.put("DWZB3", "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=这里是马赛克"); m.put("TCYJ8", "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=这里是马赛克"); m.put("TCJH5", "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=这里是马赛克"); m.put("DWCS7", "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=这里是马赛克"); m.put("NONE", ""); } private final String title; RobotTypeEnum(String title) { this.title = title; } public String getTitle() { return title; } public static RobotTypeEnum match(String name, RobotTypeEnum defaultItem) { for (RobotTypeEnum item : RobotTypeEnum.values()) { if (item.name().equals(name)) { return item; } } return defaultItem; } public static String getUrl(String name) { return m.get(name); } }
这个是最主要的报警类,只要你实现了JobAlarm,任务报错时就会执行子类的doAlarm方法。
package com.xxl.job.admin.yxdiy.robot; 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.stereotype.Component; import java.text.MessageFormat; import java.util.Arrays; import java.util.HashSet; import java.util.Objects; import java.util.Set; @Component public class RobotJobAlarm implements JobAlarm { private static Logger logger = LoggerFactory.getLogger(RobotJobAlarm.class); public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog) { boolean alarmResult = true; APIHttpClient ac = new APIHttpClient(); // send monitor Robot if (info != null && !Objects.equals(info.getRobotType(), "NONE")) { // alarmContent String alarmContent = "任务日志Id:" + jobLog.getId(); if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) { alarmContent += ",触发信息:" + jobLog.getTriggerMsg(); } if (jobLog.getHandleCode() > 0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) { alarmContent += ",错误信息:" + jobLog.getHandleMsg(); } if (alarmContent.length() > 300) { alarmContent=alarmContent.substring(0, 300); } // Robot info XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(info.getJobGroup()); String personal = I18nUtil.getString("admin_name_full"); String title = I18nUtil.getString("jobconf_monitor"); String content = MessageFormat.format(loadRobotJobAlarmTemplate(), group != null ? group.getTitle() : "null", info.getId(), info.getJobDesc(), alarmContent); Set3.2 需要修改的类和文件(这些主要是页面交互用的) 3.2.1 message_zh_CN.propertiesrobotSet = new HashSet (Arrays.asList(info.getRobotType().split(","))); for (String robot : robotSet) { int isAtAll = 0; ac.setApiURL(RobotTypeEnum.getUrl(robot)); if (Objects.equals(robot, "DWXF1")) { isAtAll = 1; } String jObjStr = RobotData.toJsonStr( new RobotData(content, isAtAll)); // make robot try { Integer statusCode = ac.postH(jObjStr); if (statusCode != 200) { alarmResult = false; logger.error(">>>>>>>>>>> xxl-job, job 机器人报警 send error, JobLogId:{}" , jobLog.getId(), "statusCode:" + statusCode); } } catch (Exception e) { logger.error(">>>>>>>>>>> xxl-job, job 机器人报警 send error, JobLogId:{}", jobLog.getId(), e); alarmResult = false; } } } return alarmResult; } private static final String loadRobotJobAlarmTemplate() { String mailBodyTemplate = I18nUtil.getString("jobconf_monitor_detail") + ":n" + I18nUtil.getString("jobinfo_field_jobgroup") + " | {0} n" + I18nUtil.getString("jobinfo_field_id") + " | {1}n" + I18nUtil.getString("jobinfo_field_jobdesc") + " | {2}n" + I18nUtil.getString("jobconf_monitor_alarm_title") + " | " + I18nUtil.getString("jobconf_monitor_alarm_type") + "n" + I18nUtil.getString("jobconf_monitor_alarm_content") + " | {3}"; return mailBodyTemplate; } }
message_zh_CN.properties、message_zh_TC.properties、message_en.propertiesp 这个多国语言文件,可根据实际项目来改,我放个CN的例子:
robot_type_dwxf1=数仓消防机器人 robot_type_dwjh2=数仓稽核机器人 robot_type_dwzb3=数仓值班机器人 robot_type_dwcs7=数仓测试机器人 robot_type_tcyj8=马赛克预警机器人 robot_type_tcjh5=马赛克稽核机器人 robot_type_diy4=自定义机器人 robot_type_none=无 robot_type=报警机器人 jobinfo_field_alarmrobot=报警机器人3.2.2 jobinfo.index.1.js
下面的是稍稍繁琐的写页面了,因为源码太长,我不贴全了,只放要改的代码,再截个位置图。
3.2.2.1 修改一:
//在第一个"columns": [ 中, // {"data": 'alarmEmail', "visible": false}下边, 增加: {"data": 'robotType', "visible": false},
3.2.2.2 修改二、三:
这两个位置加同样的代码:
// $("#updateModal .form input[name='alarmEmail']").val(row.alarmEmail);下边 // 增加一行代码 $('#updateModal .form select[name=robotType] option[value=' + row.robotType + ']').prop('selected', true);3.2.3 jobinfo.index.ftl
3.2.3.1 修改一:
// 在 id="job_list" 中,
// 新增一行
${I18n.jobinfo_field_alarmemail}
3.2.3.2 修改二、三:
// 两处改动是一样的,在144行左右 中 ,
// 和 389行左右 中
// 在 name="alarmEmail"下边
// 新增以下代码,机器人单选框
3.2.4 JobInfoController
增加机器人Enum
model.addAttribute("RobotTypeEnum", RobotTypeEnum.values()); // 机器人类型-字典3.2.5 XxlJobInfo
任务信息实体类,增加robotType和get、set方法
private String robotType; // 机器人类型 public String getRobotType() { return robotType; } public void setRobotType(String robotType) { this.robotType = robotType; }3.2.7 XxlJobServiceImpl.java
改了3处,这个贴全代码吧
package com.xxl.job.admin.service.impl; import com.xxl.job.admin.core.cron.Cronexpression; import com.xxl.job.admin.core.model.XxlJobGroup; import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobLogReport; import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum; import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum; import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum; import com.xxl.job.admin.core.thread.JobScheduleHelper; import com.xxl.job.admin.core.util.I18nUtil; import com.xxl.job.admin.dao.*; import com.xxl.job.admin.service.XxlJobService; import com.xxl.job.admin.yxdiy.robot.RobotTypeEnum; import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.enums.ExecutorBlockStrategyEnum; import com.xxl.job.core.glue.GlueTypeEnum; import com.xxl.job.core.util.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.text.MessageFormat; import java.util.*; @Service public class XxlJobServiceImpl implements XxlJobService { private static Logger logger = LoggerFactory.getLogger(XxlJobServiceImpl.class); @Resource private XxlJobGroupDao xxlJobGroupDao; @Resource private XxlJobInfoDao xxlJobInfoDao; @Resource public XxlJobLogDao xxlJobLogDao; @Resource private XxlJobLogGlueDao xxlJobLogGlueDao; @Resource private XxlJobLogReportDao xxlJobLogReportDao; @Override public Map3.2.7 XxlJobInfoMapper.xmlpageList(int start, int length, int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author) { // page list List list = xxlJobInfoDao.pageList(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author); int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author); // package result Map maps = new HashMap (); maps.put("recordsTotal", list_count); // 总记录数 maps.put("recordsFiltered", list_count); // 过滤后的总记录数 maps.put("data", list); // 分页列表 return maps; } @Override public ReturnT add(XxlJobInfo jobInfo) { // valid base XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup()); if (group == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_choose")+I18nUtil.getString("jobinfo_field_jobgroup")) ); } if (jobInfo.getJobDesc()==null || jobInfo.getJobDesc().trim().length()==0) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) ); } if (jobInfo.getAuthor()==null || jobInfo.getAuthor().trim().length()==0) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) ); } // valid trigger ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null); if (scheduleTypeEnum == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } if (scheduleTypeEnum == ScheduleTypeEnum.CRON) { if (jobInfo.getScheduleConf()==null || !Cronexpression.isValidexpression(jobInfo.getScheduleConf())) { return new ReturnT (ReturnT.FAIL_CODE, "Cron"+I18nUtil.getString("system_unvalid")); } } else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE) { if (jobInfo.getScheduleConf() == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")) ); } try { int fixSecond = Integer.valueOf(jobInfo.getScheduleConf()); if (fixSecond < 1) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } } catch (Exception e) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } } // valid robot RobotTypeEnum robotTypeEnum = RobotTypeEnum.match(jobInfo.getRobotType(), null); if (robotTypeEnum == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("robot_type")+I18nUtil.getString("system_unvalid")) ); } // valid job if (GlueTypeEnum.match(jobInfo.getGlueType()) == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_gluetype")+I18nUtil.getString("system_unvalid")) ); } if (GlueTypeEnum.BEAN==GlueTypeEnum.match(jobInfo.getGlueType()) && (jobInfo.getExecutorHandler()==null || jobInfo.getExecutorHandler().trim().length()==0) ) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+"JobHandler") ); } // 》fix "r" in shell if (GlueTypeEnum.GLUE_SHELL==GlueTypeEnum.match(jobInfo.getGlueType()) && jobInfo.getGlueSource()!=null) { jobInfo.setGlueSource(jobInfo.getGlueSource().replaceAll("r", "")); } // valid advanced if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) ); } if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("misfire_strategy")+I18nUtil.getString("system_unvalid")) ); } if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) ); } // 》ChildJobId valid if (jobInfo.getChildJobId()!=null && jobInfo.getChildJobId().trim().length()>0) { String[] childJobIds = jobInfo.getChildJobId().split(","); for (String childJobIdItem: childJobIds) { if (childJobIdItem!=null && childJobIdItem.trim().length()>0 && isNumeric(childJobIdItem)) { XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem)); if (childJobInfo==null) { return new ReturnT (ReturnT.FAIL_CODE, MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem)); } } else { return new ReturnT (ReturnT.FAIL_CODE, MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem)); } } // join , avoid "xxx,," String temp = ""; for (String item:childJobIds) { temp += item + ","; } temp = temp.substring(0, temp.length()-1); jobInfo.setChildJobId(temp); } // add in db jobInfo.setAddTime(new Date()); jobInfo.setUpdateTime(new Date()); jobInfo.setGlueUpdatetime(new Date()); xxlJobInfoDao.save(jobInfo); if (jobInfo.getId() < 1) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_add")+I18nUtil.getString("system_fail")) ); } return new ReturnT (String.valueOf(jobInfo.getId())); } private boolean isNumeric(String str){ try { int result = Integer.valueOf(str); return true; } catch (NumberFormatException e) { return false; } } @Override public ReturnT update(XxlJobInfo jobInfo) { // valid base if (jobInfo.getJobDesc()==null || jobInfo.getJobDesc().trim().length()==0) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_jobdesc")) ); } if (jobInfo.getAuthor()==null || jobInfo.getAuthor().trim().length()==0) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("system_please_input")+I18nUtil.getString("jobinfo_field_author")) ); } // valid trigger ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(jobInfo.getScheduleType(), null); if (scheduleTypeEnum == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } if (scheduleTypeEnum == ScheduleTypeEnum.CRON) { if (jobInfo.getScheduleConf()==null || !Cronexpression.isValidexpression(jobInfo.getScheduleConf())) { return new ReturnT (ReturnT.FAIL_CODE, "Cron"+I18nUtil.getString("system_unvalid") ); } } else if (scheduleTypeEnum == ScheduleTypeEnum.FIX_RATE ) { if (jobInfo.getScheduleConf() == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } try { int fixSecond = Integer.valueOf(jobInfo.getScheduleConf()); if (fixSecond < 1) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } } catch (Exception e) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } } // valid advanced if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorRouteStrategy")+I18nUtil.getString("system_unvalid")) ); } if (MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), null) == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("misfire_strategy")+I18nUtil.getString("system_unvalid")) ); } if (ExecutorBlockStrategyEnum.match(jobInfo.getExecutorBlockStrategy(), null) == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_executorBlockStrategy")+I18nUtil.getString("system_unvalid")) ); } // 》ChildJobId valid if (jobInfo.getChildJobId()!=null && jobInfo.getChildJobId().trim().length()>0) { String[] childJobIds = jobInfo.getChildJobId().split(","); for (String childJobIdItem: childJobIds) { if (childJobIdItem!=null && childJobIdItem.trim().length()>0 && isNumeric(childJobIdItem)) { XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem)); if (childJobInfo==null) { return new ReturnT (ReturnT.FAIL_CODE, MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem)); } } else { return new ReturnT (ReturnT.FAIL_CODE, MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem)); } } // join , avoid "xxx,," String temp = ""; for (String item:childJobIds) { temp += item + ","; } temp = temp.substring(0, temp.length()-1); jobInfo.setChildJobId(temp); } // group valid XxlJobGroup jobGroup = xxlJobGroupDao.load(jobInfo.getJobGroup()); if (jobGroup == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_jobgroup")+I18nUtil.getString("system_unvalid")) ); } // stage job info XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(jobInfo.getId()); if (exists_jobInfo == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_id")+I18nUtil.getString("system_not_found")) ); } // next trigger time (5s后生效,避开预读周期) long nextTriggerTime = exists_jobInfo.getTriggerNextTime(); boolean scheduleDataNotChanged = jobInfo.getScheduleType().equals(exists_jobInfo.getScheduleType()) && jobInfo.getScheduleConf().equals(exists_jobInfo.getScheduleConf()); if (exists_jobInfo.getTriggerStatus() == 1 && !scheduleDataNotChanged) { try { Date nextValidTime = JobScheduleHelper.generateNextValidTime(jobInfo, new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS)); if (nextValidTime == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } nextTriggerTime = nextValidTime.getTime(); } catch (Exception e) { logger.error(e.getMessage(), e); return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } } exists_jobInfo.setJobGroup(jobInfo.getJobGroup()); exists_jobInfo.setJobDesc(jobInfo.getJobDesc()); exists_jobInfo.setAuthor(jobInfo.getAuthor()); exists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail()); exists_jobInfo.setScheduleType(jobInfo.getScheduleType()); exists_jobInfo.setScheduleConf(jobInfo.getScheduleConf()); exists_jobInfo.setMisfireStrategy(jobInfo.getMisfireStrategy()); exists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy()); exists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler()); exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam()); exists_jobInfo.setExecutorBlockStrategy(jobInfo.getExecutorBlockStrategy()); exists_jobInfo.setExecutorTimeout(jobInfo.getExecutorTimeout()); exists_jobInfo.setExecutorFailRetryCount(jobInfo.getExecutorFailRetryCount()); exists_jobInfo.setChildJobId(jobInfo.getChildJobId()); exists_jobInfo.setTriggerNextTime(nextTriggerTime); exists_jobInfo.setRobotType(jobInfo.getRobotType()); exists_jobInfo.setUpdateTime(new Date()); xxlJobInfoDao.update(exists_jobInfo); return ReturnT.SUCCESS; } @Override public ReturnT remove(int id) { XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id); if (xxlJobInfo == null) { return ReturnT.SUCCESS; } xxlJobInfoDao.delete(id); xxlJobLogDao.delete(id); xxlJobLogGlueDao.deleteByJobId(id); return ReturnT.SUCCESS; } @Override public ReturnT start(int id) { XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id); // valid ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(xxlJobInfo.getScheduleType(), ScheduleTypeEnum.NONE); if (ScheduleTypeEnum.NONE == scheduleTypeEnum) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type_none_limit_start")) ); } // next trigger time (5s后生效,避开预读周期) long nextTriggerTime = 0; try { Date nextValidTime = JobScheduleHelper.generateNextValidTime(xxlJobInfo, new Date(System.currentTimeMillis() + JobScheduleHelper.PRE_READ_MS)); if (nextValidTime == null) { return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } nextTriggerTime = nextValidTime.getTime(); } catch (Exception e) { logger.error(e.getMessage(), e); return new ReturnT (ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) ); } xxlJobInfo.setTriggerStatus(1); xxlJobInfo.setTriggerLastTime(0); xxlJobInfo.setTriggerNextTime(nextTriggerTime); xxlJobInfo.setUpdateTime(new Date()); xxlJobInfoDao.update(xxlJobInfo); return ReturnT.SUCCESS; } @Override public ReturnT stop(int id) { XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id); xxlJobInfo.setTriggerStatus(0); xxlJobInfo.setTriggerLastTime(0); xxlJobInfo.setTriggerNextTime(0); xxlJobInfo.setUpdateTime(new Date()); xxlJobInfoDao.update(xxlJobInfo); return ReturnT.SUCCESS; } @Override public Map dashboardInfo() { int jobInfoCount = xxlJobInfoDao.findAllCount(); int jobLogCount = 0; int jobLogSuccessCount = 0; XxlJobLogReport xxlJobLogReport = xxlJobLogReportDao.queryLogReportTotal(); if (xxlJobLogReport != null) { jobLogCount = xxlJobLogReport.getRunningCount() + xxlJobLogReport.getSucCount() + xxlJobLogReport.getFailCount(); jobLogSuccessCount = xxlJobLogReport.getSucCount(); } // executor count Set executorAddressSet = new HashSet (); List groupList = xxlJobGroupDao.findAll(); if (groupList!=null && !groupList.isEmpty()) { for (XxlJobGroup group: groupList) { if (group.getRegistryList()!=null && !group.getRegistryList().isEmpty()) { executorAddressSet.addAll(group.getRegistryList()); } } } int executorCount = executorAddressSet.size(); Map dashboardMap = new HashMap (); dashboardMap.put("jobInfoCount", jobInfoCount); dashboardMap.put("jobLogCount", jobLogCount); dashboardMap.put("jobLogSuccessCount", jobLogSuccessCount); dashboardMap.put("executorCount", executorCount); return dashboardMap; } @Override public ReturnT
在sql中增加 robot_type 字段,改了好几个地方,我放全代码吧
3.3 到这里就全都完成。t . id , t.job_group, t.job_desc, t.add_time, t.update_time, t.author, t.alarm_email, t.schedule_type, t.schedule_conf, t.misfire_strategy, t.executor_route_strategy, t.executor_handler, t.executor_param, t.executor_block_strategy, t.executor_timeout, t.executor_fail_retry_count, t.glue_type, t.glue_source, t.glue_remark, t.glue_updatetime, t.child_jobid, t.trigger_status, t.trigger_last_time, t.trigger_next_time, t.robot_type
启动项目,建个测试任务,让他报错测试一下效果!
欢迎分享,转载请注明来源:内存溢出
赞
(0)
打赏
微信扫一扫
支付宝扫一扫
AOP实现
上一篇
2022-12-14
国内十大不可错过的免费学习资源网站(火速收藏中),java架构师课程推荐
下一篇
2022-12-14
评论列表(0条)