1、任务属性新增"路由策略"并设计交互;

2、GLUE源码底层结构调整;
This commit is contained in:
xueli.xue 2017-03-12 15:51:13 +08:00
parent 7102517093
commit f3573c8643
17 changed files with 202 additions and 186 deletions

View File

@ -88,10 +88,10 @@ XXL-JOB是一个轻量级分布式任务调度框架其核心设计目标是
![输入图片说明](https://static.oschina.net/uploads/img/201703/07162326_L3VB.png "在这里输入图片标题") ![输入图片说明](https://static.oschina.net/uploads/img/201703/07162326_L3VB.png "在这里输入图片标题")
#### 1.5 环境 #### 1.5 环境
- JDK1.7+
- Tomcat7+
- Mysql5.6+
- Servlet/JSP Spec3.0/2.2 - Servlet/JSP Spec3.0/2.2
- JDK1.7+
- Tomcat7+/Jetty8+
- Mysql5.6+
- Maven3+ - Maven3+

View File

@ -5,7 +5,6 @@ import com.xxl.job.admin.core.model.XxlJobLogGlue;
import com.xxl.job.admin.dao.IXxlJobInfoDao; import com.xxl.job.admin.dao.IXxlJobInfoDao;
import com.xxl.job.admin.dao.IXxlJobLogGlueDao; import com.xxl.job.admin.dao.IXxlJobLogGlueDao;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -28,9 +27,9 @@ public class JobCodeController {
private IXxlJobLogGlueDao xxlJobLogGlueDao; private IXxlJobLogGlueDao xxlJobLogGlueDao;
@RequestMapping @RequestMapping
public String index(Model model, int jobGroup, String jobName) { public String index(Model model, int jobId) {
XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName); XxlJobInfo jobInfo = xxlJobInfoDao.loadById(jobId);
List<XxlJobLogGlue> jobLogGlues = xxlJobLogGlueDao.selectList(jobGroup, jobName); List<XxlJobLogGlue> jobLogGlues = xxlJobLogGlueDao.findByJobId(jobId);
model.addAttribute("jobInfo", jobInfo); model.addAttribute("jobInfo", jobInfo);
model.addAttribute("jobLogGlues", jobLogGlues); model.addAttribute("jobLogGlues", jobLogGlues);
return "jobcode/jobcode.index"; return "jobcode/jobcode.index";
@ -38,7 +37,7 @@ public class JobCodeController {
@RequestMapping("/save") @RequestMapping("/save")
@ResponseBody @ResponseBody
public ReturnT<String> save(Model model, int jobGroup, String jobName, String glueSource, String glueRemark) { public ReturnT<String> save(Model model, int id, String glueSource, String glueRemark) {
// valid // valid
if (glueRemark==null) { if (glueRemark==null) {
return new ReturnT<String>(500, "请输入备注"); return new ReturnT<String>(500, "请输入备注");
@ -46,31 +45,26 @@ public class JobCodeController {
if (glueRemark.length()<6 || glueRemark.length()>100) { if (glueRemark.length()<6 || glueRemark.length()>100) {
return new ReturnT<String>(500, "备注长度应该在6至100之间"); return new ReturnT<String>(500, "备注长度应该在6至100之间");
} }
XxlJobInfo jobInfoOld = xxlJobInfoDao.load(jobGroup, jobName); XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(id);
if (jobInfoOld == null) { if (exists_jobInfo == null) {
return new ReturnT<String>(500, "任务不存在"); return new ReturnT<String>(500, "参数异常");
} }
// log old code // log old code
XxlJobLogGlue xxlJobLogGlue = new XxlJobLogGlue(); XxlJobLogGlue xxlJobLogGlue = new XxlJobLogGlue();
xxlJobLogGlue.setJobGroup(jobInfoOld.getJobGroup()); xxlJobLogGlue.setJobId(exists_jobInfo.getId());
xxlJobLogGlue.setJobName(jobInfoOld.getJobName()); xxlJobLogGlue.setGlueSource(exists_jobInfo.getGlueSource());
xxlJobLogGlue.setGlueSource(jobInfoOld.getGlueSource()); xxlJobLogGlue.setGlueRemark(exists_jobInfo.getGlueRemark());
xxlJobLogGlue.setGlueRemark(jobInfoOld.getGlueRemark()); xxlJobLogGlueDao.save(xxlJobLogGlue);
// init new code
jobInfoOld.setGlueSource(glueSource);
jobInfoOld.setGlueRemark(glueRemark);
// update new code ,and log old code
xxlJobInfoDao.update(jobInfoOld);
if (StringUtils.isNotBlank(xxlJobLogGlue.getGlueSource()) && StringUtils.isNotBlank(xxlJobLogGlue.getGlueRemark())) {
xxlJobLogGlueDao.save(xxlJobLogGlue);
// remove code backup more than 30
xxlJobLogGlueDao.removeOld(xxlJobLogGlue.getJobGroup(), xxlJobLogGlue.getJobName(), 30);
}
// update new code
exists_jobInfo.setGlueSource(glueSource);
exists_jobInfo.setGlueRemark(glueRemark);
xxlJobInfoDao.update(exists_jobInfo);
// remove code backup more than 30
xxlJobLogGlueDao.removeOld(exists_jobInfo.getId(), 3);
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
} }

View File

@ -1,6 +1,8 @@
package com.xxl.job.admin.controller; package com.xxl.job.admin.controller;
import com.xxl.job.admin.core.model.XxlJobGroup; import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.dao.IXxlJobGroupDao; import com.xxl.job.admin.dao.IXxlJobGroupDao;
import com.xxl.job.admin.service.IXxlJobService; import com.xxl.job.admin.service.IXxlJobService;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
@ -30,9 +32,11 @@ public class JobInfoController {
@RequestMapping @RequestMapping
public String index(Model model) { public String index(Model model) {
// 路由策略-列表
model.addAttribute("ExecutorRouteStrategyEnum", ExecutorRouteStrategyEnum.values());
// 任务组 // 任务组
List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll(); List<XxlJobGroup> jobGroupList = xxlJobGroupDao.findAll();
model.addAttribute("JobGroupList", jobGroupList); model.addAttribute("JobGroupList", jobGroupList);
return "jobinfo/jobinfo.index"; return "jobinfo/jobinfo.index";
} }
@ -48,21 +52,14 @@ public class JobInfoController {
@RequestMapping("/add") @RequestMapping("/add")
@ResponseBody @ResponseBody
public ReturnT<String> add(int jobGroup, String jobCron, String jobDesc, String author, String alarmEmail, public ReturnT<String> add(XxlJobInfo jobInfo) {
String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark, String childJobKey) { return xxlJobService.add(jobInfo);
return xxlJobService.add(jobGroup, jobCron, jobDesc, author, alarmEmail,
executorHandler, executorParam,
glueSwitch, glueSource, glueRemark, childJobKey);
} }
@RequestMapping("/reschedule") @RequestMapping("/reschedule")
@ResponseBody @ResponseBody
public ReturnT<String> reschedule(int jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail, public ReturnT<String> reschedule(XxlJobInfo jobInfo) {
String executorHandler, String executorParam, int glueSwitch, String childJobKey) { return xxlJobService.reschedule(jobInfo);
return xxlJobService.reschedule(jobGroup, jobName, jobCron, jobDesc, author, alarmEmail,
executorHandler, executorParam, glueSwitch, childJobKey);
} }
@RequestMapping("/remove") @RequestMapping("/remove")

View File

@ -7,63 +7,69 @@ package com.xxl.job.admin.core.model;
public class XxlJobLogGlue { public class XxlJobLogGlue {
private int id; private int id;
private int jobId;
private int jobGroup;
private String jobName;
private String glueSource; private String glueSource;
private String glueRemark; private String glueRemark;
private String addTime; private String addTime;
private String updateTime; private String updateTime;
public int getId() { public int getId() {
return id; return id;
} }
public void setId(int id) { public void setId(int id) {
this.id = id; this.id = id;
} }
public int getJobGroup() {
return jobGroup; public int getJobId() {
return jobId;
} }
public void setJobGroup(int jobGroup) {
this.jobGroup = jobGroup; public void setJobId(int jobId) {
} this.jobId = jobId;
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
} }
public String getGlueSource() { public String getGlueSource() {
return glueSource; return glueSource;
} }
public void setGlueSource(String glueSource) { public void setGlueSource(String glueSource) {
this.glueSource = glueSource; this.glueSource = glueSource;
} }
public String getGlueRemark() { public String getGlueRemark() {
return glueRemark; return glueRemark;
} }
public void setGlueRemark(String glueRemark) { public void setGlueRemark(String glueRemark) {
this.glueRemark = glueRemark; this.glueRemark = glueRemark;
} }
public String getAddTime() { public String getAddTime() {
return addTime; return addTime;
} }
public void setAddTime(String addTime) { public void setAddTime(String addTime) {
this.addTime = addTime; this.addTime = addTime;
} }
public String getUpdateTime() { public String getUpdateTime() {
return updateTime; return updateTime;
} }
public void setUpdateTime(String updateTime) { public void setUpdateTime(String updateTime) {
this.updateTime = updateTime; this.updateTime = updateTime;
} }
@Override @Override
public String toString() { public String toString() {
return "XxlJobLogGlue [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", glueSource=" return "XxlJobLogGlue{" +
+ glueSource + ", glueRemark=" + glueRemark + ", addTime=" + addTime + ", updateTime=" + updateTime "id=" + id +
+ "]"; ", jobId=" + jobId +
", glueSource='" + glueSource + '\'' +
", glueRemark='" + glueRemark + '\'' +
", addTime='" + addTime + '\'' +
", updateTime='" + updateTime + '\'' +
'}';
} }
} }

View File

@ -32,9 +32,11 @@ public enum ExecutorRouteStrategyEnum {
} }
public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem){ public static ExecutorRouteStrategyEnum match(String name, ExecutorRouteStrategyEnum defaultItem){
for (ExecutorRouteStrategyEnum item: ExecutorRouteStrategyEnum.values()) { if (name != null) {
if (item.name().equals(name)) { for (ExecutorRouteStrategyEnum item: ExecutorRouteStrategyEnum.values()) {
return item; if (item.name().equals(name)) {
return item;
}
} }
} }
return defaultItem; return defaultItem;

View File

@ -16,7 +16,8 @@ public interface IXxlJobInfoDao {
public int pageListCount(int offset, int pagesize, int jobGroup, String executorHandler); public int pageListCount(int offset, int pagesize, int jobGroup, String executorHandler);
public int save(XxlJobInfo info); public int save(XxlJobInfo info);
public XxlJobInfo loadById(int id);
public XxlJobInfo load(int jobGroup, String jobName); public XxlJobInfo load(int jobGroup, String jobName);
public int update(XxlJobInfo item); public int update(XxlJobInfo item);

View File

@ -12,10 +12,10 @@ public interface IXxlJobLogGlueDao {
public int save(XxlJobLogGlue xxlJobLogGlue); public int save(XxlJobLogGlue xxlJobLogGlue);
public List<XxlJobLogGlue> selectList(int jobGroup, String jobName); public List<XxlJobLogGlue> findByJobId(int jobId);
public int removeOld(int jobGroup, String jobName, int limit); public int removeOld(int jobId, int limit);
public int delete(int jobGroup, String jobName); public int deleteByJobId(int jobId);
} }

View File

@ -47,6 +47,11 @@ public class XxlJobInfoDaoImpl implements IXxlJobInfoDao {
return sqlSessionTemplate.insert("XxlJobInfoMapper.save", info); return sqlSessionTemplate.insert("XxlJobInfoMapper.save", info);
} }
@Override
public XxlJobInfo loadById(int id) {
return sqlSessionTemplate.selectOne("XxlJobInfoMapper.loadById", id);
}
@Override @Override
public XxlJobInfo load(int jobGroup, String jobName) { public XxlJobInfo load(int jobGroup, String jobName) {
HashMap<String, Object> params = new HashMap<String, Object>(); HashMap<String, Object> params = new HashMap<String, Object>();

View File

@ -25,28 +25,21 @@ public class XxlJobLogGlueDaoImpl implements IXxlJobLogGlueDao {
} }
@Override @Override
public List<XxlJobLogGlue> selectList(int jobGroup, String jobName) { public List<XxlJobLogGlue> findByJobId(int jobId) {
HashMap<String, Object> params = new HashMap<String, Object>(); return sqlSessionTemplate.selectList("XxlJobLogGlueMapper.findByJobId", jobId);
params.put("jobGroup", jobGroup);
params.put("jobName", jobName);
return sqlSessionTemplate.selectList("XxlJobLogGlueMapper.selectList", params);
} }
@Override @Override
public int removeOld(int jobGroup, String jobName, int limit) { public int removeOld(int jobId, int limit) {
HashMap<String, Object> params = new HashMap<String, Object>(); HashMap<String, Object> params = new HashMap<String, Object>();
params.put("jobGroup", jobGroup); params.put("jobId", jobId);
params.put("jobName", jobName);
params.put("limit", limit); params.put("limit", limit);
return sqlSessionTemplate.delete("XxlJobLogGlueMapper.removeOld", params); return sqlSessionTemplate.delete("XxlJobLogGlueMapper.removeOld", params);
} }
@Override @Override
public int delete(int jobGroup, String jobName) { public int deleteByJobId(int jobId) {
HashMap<String, Object> params = new HashMap<String, Object>(); return sqlSessionTemplate.delete("XxlJobLogGlueMapper.deleteByJobId", jobId);
params.put("jobGroup", jobGroup);
params.put("jobName", jobName);
return sqlSessionTemplate.delete("XxlJobLogGlueMapper.delete", params);
} }
} }

View File

@ -1,6 +1,7 @@
package com.xxl.job.admin.service; package com.xxl.job.admin.service;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.biz.model.ReturnT;
import java.util.Map; import java.util.Map;
@ -14,11 +15,9 @@ public interface IXxlJobService {
public Map<String, Object> pageList(int start, int length, int jobGroup, String executorHandler, String filterTime); public Map<String, Object> pageList(int start, int length, int jobGroup, String executorHandler, String filterTime);
public ReturnT<String> add(int jobGroup, String jobCron, String jobDesc, String author, String alarmEmail, public ReturnT<String> add(XxlJobInfo jobInfo);
String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark, String childJobKey);
public ReturnT<String> reschedule(int jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail, public ReturnT<String> reschedule(XxlJobInfo jobInfo);
String executorHandler, String executorParam, int glueSwitch, String childJobKey);
public ReturnT<String> remove(int jobGroup, String jobName); public ReturnT<String> remove(int jobGroup, String jobName);

View File

@ -2,6 +2,7 @@ package com.xxl.job.admin.service.impl;
import com.xxl.job.admin.core.model.XxlJobGroup; import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo; import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler; import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
import com.xxl.job.admin.dao.IXxlJobGroupDao; import com.xxl.job.admin.dao.IXxlJobGroupDao;
import com.xxl.job.admin.dao.IXxlJobInfoDao; import com.xxl.job.admin.dao.IXxlJobInfoDao;
@ -64,33 +65,34 @@ public class XxlJobServiceImpl implements IXxlJobService {
} }
@Override @Override
public ReturnT<String> add(int jobGroup, String jobCron, String jobDesc, String author, String alarmEmail, public ReturnT<String> add(XxlJobInfo jobInfo) {
String executorHandler, String executorParam,
int glueSwitch, String glueSource, String glueRemark, String childJobKey) {
// valid // valid
XxlJobGroup group = xxlJobGroupDao.load(jobGroup); XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup());
if (group == null) { if (group == null) {
return new ReturnT<String>(500, "请选择“执行器”"); return new ReturnT<String>(500, "请选择“执行器”");
} }
if (!CronExpression.isValidExpression(jobCron)) { if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
return new ReturnT<String>(500, "请输入格式正确的“Cron”"); return new ReturnT<String>(500, "请输入格式正确的“Cron”");
} }
if (StringUtils.isBlank(jobDesc)) { if (StringUtils.isBlank(jobInfo.getJobDesc())) {
return new ReturnT<String>(500, "请输入“任务描述”"); return new ReturnT<String>(500, "请输入“任务描述”");
} }
if (StringUtils.isBlank(author)) { if (StringUtils.isBlank(jobInfo.getAuthor())) {
return new ReturnT<String>(500, "请输入“负责人”"); return new ReturnT<String>(500, "请输入“负责人”");
} }
if (StringUtils.isBlank(alarmEmail)) { if (StringUtils.isBlank(jobInfo.getAlarmEmail())) {
return new ReturnT<String>(500, "请输入“报警邮件”"); return new ReturnT<String>(500, "请输入“报警邮件”");
} }
if (glueSwitch==0 && StringUtils.isBlank(executorHandler)) { if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
return new ReturnT<String>(500, "路由策略非法");
}
if (jobInfo.getGlueSwitch()==0 && StringUtils.isBlank(jobInfo.getExecutorHandler())) {
return new ReturnT<String>(500, "请输入“JobHandler”"); return new ReturnT<String>(500, "请输入“JobHandler”");
} }
// childJobKey valid // childJobKey valid
if (StringUtils.isNotBlank(childJobKey)) { if (StringUtils.isNotBlank(jobInfo.getChildJobKey())) {
String[] childJobKeys = childJobKey.split(","); String[] childJobKeys = jobInfo.getChildJobKey().split(",");
for (String childJobKeyItem: childJobKeys) { for (String childJobKeyItem: childJobKeys) {
String[] childJobKeyArr = childJobKeyItem.split("_"); String[] childJobKeyArr = childJobKeyItem.split("_");
if (childJobKeyArr.length!=2) { if (childJobKeyArr.length!=2) {
@ -105,8 +107,9 @@ public class XxlJobServiceImpl implements IXxlJobService {
// generate jobName // generate jobName
String jobName = FastDateFormat.getInstance("yyyyMMddHHmmssSSSS").format(new Date()); String jobName = FastDateFormat.getInstance("yyyyMMddHHmmssSSSS").format(new Date());
jobInfo.setJobName(jobName);
try { try {
if (XxlJobDynamicScheduler.checkExists(jobName, String.valueOf(jobGroup))) { if (XxlJobDynamicScheduler.checkExists(jobName, String.valueOf(jobInfo.getJobGroup()))) {
return new ReturnT<String>(500, "系统繁忙,请稍后重试"); return new ReturnT<String>(500, "系统繁忙,请稍后重试");
} }
} catch (SchedulerException e1) { } catch (SchedulerException e1) {
@ -115,7 +118,7 @@ public class XxlJobServiceImpl implements IXxlJobService {
} }
// Backup to the database // Backup to the database
XxlJobInfo jobInfo = new XxlJobInfo(); /*XxlJobInfo jobInfo = new XxlJobInfo();
jobInfo.setJobGroup(jobGroup); jobInfo.setJobGroup(jobGroup);
jobInfo.setJobName(jobName); jobInfo.setJobName(jobName);
jobInfo.setJobCron(jobCron); jobInfo.setJobCron(jobCron);
@ -127,11 +130,11 @@ public class XxlJobServiceImpl implements IXxlJobService {
jobInfo.setGlueSwitch(glueSwitch); jobInfo.setGlueSwitch(glueSwitch);
jobInfo.setGlueSource(glueSource); jobInfo.setGlueSource(glueSource);
jobInfo.setGlueRemark(glueRemark); jobInfo.setGlueRemark(glueRemark);
jobInfo.setChildJobKey(childJobKey); jobInfo.setChildJobKey(childJobKey);*/
try { try {
// add job 2 quartz // add job 2 quartz
boolean result = XxlJobDynamicScheduler.addJob(String.valueOf(jobGroup), jobName, jobCron); boolean result = XxlJobDynamicScheduler.addJob(String.valueOf(jobInfo.getJobGroup()), jobName, jobInfo.getJobCron());
if (result) { if (result) {
xxlJobInfoDao.save(jobInfo); xxlJobInfoDao.save(jobInfo);
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
@ -145,36 +148,31 @@ public class XxlJobServiceImpl implements IXxlJobService {
} }
@Override @Override
public ReturnT<String> reschedule(int jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail, public ReturnT<String> reschedule(XxlJobInfo jobInfo) {
String executorHandler, String executorParam, int glueSwitch, String childJobKey) {
// valid // valid
XxlJobGroup group = xxlJobGroupDao.load(jobGroup); if (!CronExpression.isValidExpression(jobInfo.getJobCron())) {
if (group == null) {
return new ReturnT<String>(500, "请选择“执行器”");
}
if (StringUtils.isBlank(jobName)) {
return new ReturnT<String>(500, "请输入“任务名”");
}
if (!CronExpression.isValidExpression(jobCron)) {
return new ReturnT<String>(500, "请输入格式正确的“Cron”"); return new ReturnT<String>(500, "请输入格式正确的“Cron”");
} }
if (StringUtils.isBlank(jobDesc)) { if (StringUtils.isBlank(jobInfo.getJobDesc())) {
return new ReturnT<String>(500, "请输入“任务描述”"); return new ReturnT<String>(500, "请输入“任务描述”");
} }
if (StringUtils.isBlank(author)) { if (StringUtils.isBlank(jobInfo.getAuthor())) {
return new ReturnT<String>(500, "请输入“负责人”"); return new ReturnT<String>(500, "请输入“负责人”");
} }
if (StringUtils.isBlank(alarmEmail)) { if (StringUtils.isBlank(jobInfo.getAlarmEmail())) {
return new ReturnT<String>(500, "请输入“报警邮件”"); return new ReturnT<String>(500, "请输入“报警邮件”");
} }
if (glueSwitch==0 && StringUtils.isBlank(executorHandler)) { if (ExecutorRouteStrategyEnum.match(jobInfo.getExecutorRouteStrategy(), null) == null) {
return new ReturnT<String>(500, "路由策略非法");
}
if (jobInfo.getGlueSwitch()==0 && StringUtils.isBlank(jobInfo.getExecutorHandler())) {
return new ReturnT<String>(500, "请输入“JobHandler”"); return new ReturnT<String>(500, "请输入“JobHandler”");
} }
// childJobKey valid // childJobKey valid
if (StringUtils.isNotBlank(childJobKey)) { if (StringUtils.isNotBlank(jobInfo.getChildJobKey())) {
String[] childJobKeys = childJobKey.split(","); String[] childJobKeys = jobInfo.getChildJobKey().split(",");
for (String childJobKeyItem: childJobKeys) { for (String childJobKeyItem: childJobKeys) {
String[] childJobKeyArr = childJobKeyItem.split("_"); String[] childJobKeyArr = childJobKeyItem.split("_");
if (childJobKeyArr.length!=2) { if (childJobKeyArr.length!=2) {
@ -188,21 +186,26 @@ public class XxlJobServiceImpl implements IXxlJobService {
} }
// stage job info // stage job info
XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName); XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(jobInfo.getId());
jobInfo.setJobCron(jobCron); if (exists_jobInfo == null) {
jobInfo.setJobDesc(jobDesc); return new ReturnT<String>(500, "参数异常");
jobInfo.setAuthor(author); }
jobInfo.setAlarmEmail(alarmEmail);
jobInfo.setExecutorHandler(executorHandler); exists_jobInfo.setJobCron(jobInfo.getJobCron());
jobInfo.setExecutorParam(executorParam); exists_jobInfo.setJobDesc(jobInfo.getJobDesc());
jobInfo.setGlueSwitch(glueSwitch); exists_jobInfo.setAuthor(jobInfo.getAuthor());
jobInfo.setChildJobKey(childJobKey); exists_jobInfo.setAlarmEmail(jobInfo.getAlarmEmail());
exists_jobInfo.setExecutorRouteStrategy(jobInfo.getExecutorRouteStrategy());
exists_jobInfo.setExecutorHandler(jobInfo.getExecutorHandler());
exists_jobInfo.setExecutorParam(jobInfo.getExecutorParam());
exists_jobInfo.setGlueSwitch(jobInfo.getGlueSwitch());
exists_jobInfo.setChildJobKey(jobInfo.getChildJobKey());
try { try {
// fresh quartz // fresh quartz
boolean ret = XxlJobDynamicScheduler.rescheduleJob(String.valueOf(jobGroup), jobName, jobCron); boolean ret = XxlJobDynamicScheduler.rescheduleJob(String.valueOf(exists_jobInfo.getJobGroup()), exists_jobInfo.getJobName(), exists_jobInfo.getJobCron());
if (ret) { if (ret) {
xxlJobInfoDao.update(jobInfo); xxlJobInfoDao.update(exists_jobInfo);
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
} else { } else {
return new ReturnT<String>(500, "更新任务失败"); return new ReturnT<String>(500, "更新任务失败");
@ -215,11 +218,13 @@ public class XxlJobServiceImpl implements IXxlJobService {
@Override @Override
public ReturnT<String> remove(int jobGroup, String jobName) { public ReturnT<String> remove(int jobGroup, String jobName) {
XxlJobInfo xxlJobInfo = xxlJobInfoDao.load(jobGroup, jobName);
try { try {
XxlJobDynamicScheduler.removeJob(jobName, String.valueOf(jobGroup)); XxlJobDynamicScheduler.removeJob(jobName, String.valueOf(jobGroup));
xxlJobInfoDao.delete(jobGroup, jobName); xxlJobInfoDao.delete(jobGroup, jobName);
xxlJobLogDao.delete(jobGroup, jobName); xxlJobLogDao.delete(jobGroup, jobName);
xxlJobLogGlueDao.delete(jobGroup, jobName); xxlJobLogGlueDao.deleteByJobId(xxlJobInfo.getId());
return ReturnT.SUCCESS; return ReturnT.SUCCESS;
} catch (SchedulerException e) { } catch (SchedulerException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -113,7 +113,13 @@
SELECT LAST_INSERT_ID() SELECT LAST_INSERT_ID()
</selectKey> </selectKey>
</insert> </insert>
<select id="loadById" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
SELECT <include refid="Base_Column_List" />
FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t
WHERE t.id = #{id}
</select>
<select id="load" parameterType="java.util.HashMap" resultMap="XxlJobInfo"> <select id="load" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
SELECT <include refid="Base_Column_List" /> SELECT <include refid="Base_Column_List" />
FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t FROM XXL_JOB_QRTZ_TRIGGER_INFO AS t

View File

@ -5,8 +5,7 @@
<resultMap id="XxlJobLogGlue" type="com.xxl.job.admin.core.model.XxlJobLogGlue" > <resultMap id="XxlJobLogGlue" type="com.xxl.job.admin.core.model.XxlJobLogGlue" >
<result column="id" property="id" /> <result column="id" property="id" />
<result column="job_group" property="jobGroup" /> <result column="job_id" property="jobId" />
<result column="job_name" property="jobName" />
<result column="glue_source" property="glueSource" /> <result column="glue_source" property="glueSource" />
<result column="glue_remark" property="glueRemark" /> <result column="glue_remark" property="glueRemark" />
<result column="add_time" property="addTime" /> <result column="add_time" property="addTime" />
@ -15,8 +14,7 @@
<sql id="Base_Column_List"> <sql id="Base_Column_List">
t.id, t.id,
t.job_group, t.job_id,
t.job_name,
t.glue_source, t.glue_source,
t.glue_remark, t.glue_remark,
t.add_time, t.add_time,
@ -25,15 +23,13 @@
<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobLogGlue" useGeneratedKeys="true" keyProperty="id" > <insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobLogGlue" useGeneratedKeys="true" keyProperty="id" >
INSERT INTO XXL_JOB_QRTZ_TRIGGER_LOGGLUE ( INSERT INTO XXL_JOB_QRTZ_TRIGGER_LOGGLUE (
`job_group`, `job_id`,
`job_name`, `glue_source`,
`glue_source`,
`glue_remark`, `glue_remark`,
`add_time`, `add_time`,
`update_time` `update_time`
) VALUES ( ) VALUES (
#{jobGroup}, #{jobId},
#{jobName},
#{glueSource}, #{glueSource},
#{glueRemark}, #{glueRemark},
now(), now(),
@ -44,17 +40,10 @@
</selectKey> </selectKey>
</insert> </insert>
<select id="selectList" parameterType="java.util.HashMap" resultMap="XxlJobLogGlue"> <select id="findByJobId" parameterType="java.lang.Integer" resultMap="XxlJobLogGlue">
SELECT <include refid="Base_Column_List" /> SELECT <include refid="Base_Column_List" />
FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE AS t FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE AS t
<trim prefix="WHERE" prefixOverrides="AND | OR" > WHERE t.job_id = #{jobId}
<if test="jobGroup gt 0">
AND t.job_group = #{jobGroup}
</if>
<if test="jobName != null and jobName != ''">
AND t.job_name = #{jobName}
</if>
</trim>
ORDER BY id DESC ORDER BY id DESC
</select> </select>
@ -63,16 +52,16 @@
WHERE id NOT in( WHERE id NOT in(
SELECT id FROM( SELECT id FROM(
SELECT id FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE SELECT id FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE
WHERE `job_group` = #{jobGroup} and `job_name` = #{jobName} WHERE `job_id` = #{jobId}
ORDER BY update_time desc ORDER BY update_time desc
LIMIT 0, #{limit} LIMIT 0, #{limit}
) t1 ) t1
) AND `job_group` = #{jobGroup} and `job_name` = #{jobName} ) AND `job_id` = #{jobId}
</delete> </delete>
<delete id="delete" parameterType="java.util.HashMap" > <delete id="deleteByJobId" parameterType="java.lang.Integer" >
DELETE FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE DELETE FROM XXL_JOB_QRTZ_TRIGGER_LOGGLUE
WHERE job_group = #{jobGroup} and job_name = #{jobName} WHERE `job_id` = #{jobId}
</delete> </delete>
</mapper> </mapper>

View File

@ -94,8 +94,7 @@
<script src="${request.contextPath}/static/plugins/codemirror/addon/hint/show-hint.js"></script> <script src="${request.contextPath}/static/plugins/codemirror/addon/hint/show-hint.js"></script>
<script src="${request.contextPath}/static/plugins/codemirror/addon/hint/anyword-hint.js"></script> <script src="${request.contextPath}/static/plugins/codemirror/addon/hint/anyword-hint.js"></script>
<script> <script>
var jobGroup = '${jobInfo.jobGroup}'; var id = '${jobInfo.id}';
var jobName = '${jobInfo.jobName}';
</script> </script>
<script src="${request.contextPath}/static/js/jobcode.index.1.js"></script> <script src="${request.contextPath}/static/js/jobcode.index.1.js"></script>

View File

@ -124,23 +124,29 @@
<label for="lastname" class="col-sm-2 control-label">任务描述<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">任务描述<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="50" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="50" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">路由策略<font color="red">*</font></label>
<div class="col-sm-4">
<select class="form-control" name="executorRouteStrategy" >
<#list ExecutorRouteStrategyEnum as item>
<option value="${item}" >${item.title}</option>
</#list>
</select>
</div>
<label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div>
</div>
<div class="form-group">
<label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label> <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" name="executorHandler" placeholder="请输入“JobHandler”" maxlength="100" > <input type="text" class="form-control" name="executorHandler" placeholder="请输入“JobHandler”" maxlength="100" >
<span class="input-group-addon"><b>GLUE</b>&nbsp;<input type="checkbox" class="ifGLUE" ></span> <span class="input-group-addon"><b>GLUE</b>&nbsp;<input type="checkbox" class="ifGLUE" ></span>
<input type="hidden" name="glueSwitch" value="0" > <input type="hidden" name="glueSwitch" value="0" >
</div> </div>
</div> </div>
<label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label> <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div>
<label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
@ -148,6 +154,10 @@
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div>
</div> </div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div>
</div>
<hr> <hr>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-3 col-sm-6"> <div class="col-sm-offset-3 col-sm-6">
@ -191,14 +201,30 @@ public class DemoGlueJobHandler extends IJobHandler {
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal form" role="form" > <form class="form-horizontal form" role="form" >
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">执行器<font color="red">*</font></label> <label for="firstname" class="col-sm-2 control-label">执行器<font color="red">*</font></label>
<div class="col-sm-4"> <div class="col-sm-4">
<input type="text" class="form-control jobGroupTitle" maxlength="50" readonly > <select class="form-control" name="jobGroup" disabled >
</div> <#list JobGroupList as group>
<option value="${group.id}" >${group.title}</option>
</#list>
</select>
</div>
<label for="lastname" class="col-sm-2 control-label">任务描述<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">任务描述<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="50" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="50" ></div>
</div> </div>
<div class="form-group">
<label for="firstname" class="col-sm-2 control-label">路由策略<font color="red">*</font></label>
<div class="col-sm-4">
<select class="form-control" name="executorRouteStrategy" >
<#list ExecutorRouteStrategyEnum as item>
<option value="${item}" >${item.title}</option>
</#list>
</select>
</div>
<label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div>
</div>
<div class="form-group"> <div class="form-group">
<label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label> <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
<div class="col-sm-4"> <div class="col-sm-4">
@ -212,24 +238,21 @@ public class DemoGlueJobHandler extends IJobHandler {
<div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label> <label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label> <label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div> <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div>
</div> </div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="50" ></div>
</div>
<hr> <hr>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-3 col-sm-6"> <div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-primary" >保存</button> <button type="submit" class="btn btn-primary" >保存</button>
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<input type="hidden" name="jobGroup" > <input type="hidden" name="id" >
<input type="hidden" name="jobName" >
</div> </div>
</div> </div>
</form> </form>

View File

@ -37,8 +37,7 @@ $(function() {
type : 'POST', type : 'POST',
url : base_url + '/jobcode/save', url : base_url + '/jobcode/save',
data : { data : {
'jobGroup' : jobGroup, 'id' : id,
'jobName' : jobName,
'glueSource' : glueSource, 'glueSource' : glueSource,
'glueRemark' : glueRemark 'glueRemark' : glueRemark
}, },

View File

@ -100,7 +100,7 @@ $(function() {
// log url // log url
var codeBtn = ""; var codeBtn = "";
if(row.glueSwitch > 0){ if(row.glueSwitch > 0){
var codeUrl = base_url +'/jobcode?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName; var codeUrl = base_url +'/jobcode?jobId='+ row.id;
codeBtn = '<button class="btn btn-warning btn-xs" type="button" onclick="javascript:window.open(\'' + codeUrl + '\')" >GLUE</button> ' codeBtn = '<button class="btn btn-warning btn-xs" type="button" onclick="javascript:window.open(\'' + codeUrl + '\')" >GLUE</button> '
} }
@ -112,6 +112,7 @@ $(function() {
' jobDesc="'+ row.jobDesc +'" '+ ' jobDesc="'+ row.jobDesc +'" '+
' author="'+ row.author +'" '+ ' author="'+ row.author +'" '+
' alarmEmail="'+ row.alarmEmail +'" '+ ' alarmEmail="'+ row.alarmEmail +'" '+
' executorRouteStrategy="'+row.executorRouteStrategy +'" '+
' executorHandler="'+row.executorHandler +'" '+ ' executorHandler="'+row.executorHandler +'" '+
' executorParam="'+ row.executorParam +'" '+ ' executorParam="'+ row.executorParam +'" '+
' glueSwitch="'+ row.glueSwitch +'" '+ ' glueSwitch="'+ row.glueSwitch +'" '+
@ -323,20 +324,17 @@ $(function() {
$("#job_list").on('click', '.update',function() { $("#job_list").on('click', '.update',function() {
// base data // base data
$("#updateModal .form input[name='jobGroup']").val($(this).parent('p').attr("jobGroup")); $("#updateModal .form input[name='id']").val($(this).parent('p').attr("id"));
$("#updateModal .form input[name='jobName']").val($(this).parent('p').attr("jobName")); $('#updateModal .form select[name=jobGroup] option[value='+ $(this).parent('p').attr("jobGroup") +']').prop('selected', true);
$("#updateModal .form input[name='jobDesc']").val($(this).parent('p').attr("jobDesc")); $("#updateModal .form input[name='jobDesc']").val($(this).parent('p').attr("jobDesc"));
$("#updateModal .form input[name='jobCron']").val($(this).parent('p').attr("jobCron")); $("#updateModal .form input[name='jobCron']").val($(this).parent('p').attr("jobCron"));
$("#updateModal .form input[name='author']").val($(this).parent('p').attr("author")); $("#updateModal .form input[name='author']").val($(this).parent('p').attr("author"));
$("#updateModal .form input[name='alarmEmail']").val($(this).parent('p').attr("alarmEmail")); $("#updateModal .form input[name='alarmEmail']").val($(this).parent('p').attr("alarmEmail"));
$('#updateModal .form select[name=executorRouteStrategy] option[value='+ $(this).parent('p').attr("executorRouteStrategy") +']').prop('selected', true);
$("#updateModal .form input[name='executorHandler']").val($(this).parent('p').attr("executorHandler")); $("#updateModal .form input[name='executorHandler']").val($(this).parent('p').attr("executorHandler"));
$("#updateModal .form input[name='executorParam']").val($(this).parent('p').attr("executorParam")); $("#updateModal .form input[name='executorParam']").val($(this).parent('p').attr("executorParam"));
$("#updateModal .form input[name='childJobKey']").val($(this).parent('p').attr("childJobKey")); $("#updateModal .form input[name='childJobKey']").val($(this).parent('p').attr("childJobKey"));
// jobGroupTitle
var jobGroupTitle = $("#addModal .form select[name='jobGroup']").find("option[value='" + $(this).parent('p').attr("jobGroup") + "']").text();
$("#updateModal .form .jobGroupTitle").val(jobGroupTitle);
// glueSwitch // glueSwitch
var glueSwitch = $(this).parent('p').attr("glueSwitch"); var glueSwitch = $(this).parent('p').attr("glueSwitch");
$("#updateModal .form input[name='glueSwitch']").val(glueSwitch); $("#updateModal .form input[name='glueSwitch']").val(glueSwitch);