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"; //消息类型
Map text; //消息内容
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);
}
}
3.1.4 RobotTypeEnum
这个枚举主要有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 Map m =
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);
}
}
3.1.5 RobotJobAlarm
这个是最主要的报警类,只要你实现了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);
Set robotSet = 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;
}
}
3.2 需要修改的类和文件(这些主要是页面交互用的)
3.2.1 message_zh_CN.properties
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 Map pageList(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
3.2.7 XxlJobInfoMapper.xml
在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
启动项目,建个测试任务,让他报错测试一下效果!
Java相关栏目本月热门文章
- 1【Linux驱动开发】设备树详解(二)设备树语法详解
- 2别跟客户扯细节
- 3Springboot+RabbitMQ+ACK机制(生产方确认(全局、局部)、消费方确认)、知识盲区
- 4【Java】对象处理流(ObjectOutputStream和ObjectInputStream)
- 5【分页】常见两种SpringBoot项目中分页技巧
- 6一文带你搞懂OAuth2.0
- 7我要写整个中文互联网界最牛逼的JVM系列教程 | 「JVM与Java体系架构」章节:虚拟机与Java虚拟机介绍
- 8【Spring Cloud】新闻头条微服务项目:FreeMarker模板引擎实现文章静态页面生成
- 9JavaSE - 封装、static成员和内部类
- 10树莓派mjpg-streamer实现监控及拍照功能调试
- 11用c++写一个蓝屏代码
- 12从JDK8源码中看ArrayList和LinkedList的区别
- 13idea 1、报错java: 找不到符号 符号: 变量 log 2、转换成Maven项目
- 14在openwrt使用C语言增加ubus接口(包含C uci操作)
- 15Spring 解决循环依赖
- 16SpringMVC——基于MVC架构的Spring框架
- 17Andy‘s First Dictionary C++ STL set应用
- 18动态内存管理
- 19我的创作纪念日
- 20Docker自定义镜像-Dockerfile
热门相关搜索
路由器设置
木托盘
宝塔面板
儿童python教程
心情低落
朋友圈
vim
双一流学科
专升本
我的学校
日记学校
西点培训学校
汽修学校
情书
化妆学校
塔沟武校
异形模板
西南大学排名
最精辟人生短句
6步教你追回被骗的钱
南昌大学排名
清朝十二帝
北京印刷学院排名
北方工业大学排名
北京航空航天大学排名
首都经济贸易大学排名
中国传媒大学排名
首都师范大学排名
中国地质大学(北京)排名
北京信息科技大学排名
中央民族大学排名
北京舞蹈学院排名
北京电影学院排名
中国戏曲学院排名
河北政法职业学院排名
河北经贸大学排名
天津中德应用技术大学排名
天津医学高等专科学校排名
天津美术学院排名
天津音乐学院排名
天津工业大学排名
北京工业大学耿丹学院排名
北京警察学院排名
天津科技大学排名
北京邮电大学(宏福校区)排名
北京网络职业学院排名
北京大学医学部排名
河北科技大学排名
河北地质大学排名
河北体育学院排名



