commit
554429ea59
|
@ -1,14 +1,11 @@
|
|||
package com.xxl.job.controller;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.quartz.CronExpression;
|
||||
|
@ -28,6 +25,8 @@ import com.xxl.job.core.model.XxlJobInfo;
|
|||
import com.xxl.job.core.util.DynamicSchedulerUtil;
|
||||
import com.xxl.job.dao.IXxlJobInfoDao;
|
||||
import com.xxl.job.service.job.HttpJobBean;
|
||||
import com.xxl.job.service.job.LocalJobBean;
|
||||
import com.xxl.job.service.job.LocalJobBeanB;
|
||||
|
||||
/**
|
||||
* index controller
|
||||
|
@ -40,9 +39,20 @@ public class JobInfoController {
|
|||
@Resource
|
||||
private IXxlJobInfoDao xxlJobInfoDao;
|
||||
|
||||
// remote job bean
|
||||
public static Class <? extends Job> remoteJobBean = HttpJobBean.class;
|
||||
// loacal job bean
|
||||
public static List<Class <? extends Job>> localJobBeanList = new ArrayList<Class<? extends Job>>();
|
||||
static{
|
||||
localJobBeanList.add(LocalJobBean.class);
|
||||
localJobBeanList.add(LocalJobBeanB.class);
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public String index(Model model) {
|
||||
model.addAttribute("JobGroupList", JobGroupEnum.values());
|
||||
model.addAttribute("localJobBeanList", localJobBeanList); // 本地任务-列表
|
||||
model.addAttribute("remoteJobBean", remoteJobBean); // 远程任务-jobBean
|
||||
model.addAttribute("JobGroupList", JobGroupEnum.values()); // 任务组列表
|
||||
return "jobinfo/index";
|
||||
}
|
||||
|
||||
|
@ -50,11 +60,11 @@ public class JobInfoController {
|
|||
@ResponseBody
|
||||
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
|
||||
@RequestParam(required = false, defaultValue = "10") int length,
|
||||
String jobName, String filterTime) {
|
||||
String jobGroup, String jobName, String filterTime) {
|
||||
|
||||
// page list
|
||||
List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobName, null, null);
|
||||
int list_count = xxlJobInfoDao.pageListCount(start, length, jobName, null, null);
|
||||
List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, jobName);
|
||||
int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, jobName);
|
||||
|
||||
// fill job info
|
||||
if (list!=null && list.size()>0) {
|
||||
|
@ -71,72 +81,89 @@ public class JobInfoController {
|
|||
return maps;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@RequestMapping("/add")
|
||||
@ResponseBody
|
||||
public ReturnT<String> add(HttpServletRequest request) {
|
||||
String triggerKeyName = null;
|
||||
String cronExpression = null;
|
||||
Map<String, String> jobData = new HashMap<String, String>();
|
||||
public ReturnT<String> add(String jobGroup, String jobName, String jobCron, String jobDesc, String jobClass,
|
||||
String handler_params, String handler_address, String handler_name,
|
||||
String author, String alarm_email, int alarm_threshold) {
|
||||
|
||||
try {
|
||||
request.setCharacterEncoding("utf-8");
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
e1.printStackTrace();
|
||||
// valid
|
||||
if (JobGroupEnum.match(jobGroup) == null) {
|
||||
return new ReturnT<String>(500, "请选择“任务组”");
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<Map.Entry<String, String[]>> paramSet = request.getParameterMap().entrySet();
|
||||
for (Entry<String, String[]> param : paramSet) {
|
||||
if (param.getKey().equals("triggerKeyName")) {
|
||||
triggerKeyName = param.getValue()[0];
|
||||
} else if (param.getKey().equals("cronExpression")) {
|
||||
cronExpression = param.getValue()[0];
|
||||
} else {
|
||||
jobData.put(param.getKey(), (String) (param.getValue().length>0?param.getValue()[0]:param.getValue()));
|
||||
}
|
||||
if (StringUtils.isBlank(jobName)) {
|
||||
return new ReturnT<String>(500, "请输入“任务名”");
|
||||
}
|
||||
|
||||
// triggerKeyName
|
||||
if (StringUtils.isBlank(triggerKeyName)) {
|
||||
return new ReturnT<String>(500, "请输入“任务key”");
|
||||
if (!CronExpression.isValidExpression(jobCron)) {
|
||||
return new ReturnT<String>(500, "“corn”不合法");
|
||||
}
|
||||
|
||||
// cronExpression
|
||||
if (StringUtils.isBlank(cronExpression)) {
|
||||
return new ReturnT<String>(500, "请输入“任务corn”");
|
||||
}
|
||||
if (!CronExpression.isValidExpression(cronExpression)) {
|
||||
return new ReturnT<String>(500, "“任务corn”不合法");
|
||||
}
|
||||
|
||||
// jobData
|
||||
if (jobData.get(HandlerRepository.job_desc)==null || jobData.get(HandlerRepository.job_desc).toString().trim().length()==0) {
|
||||
if (StringUtils.isBlank(jobDesc)) {
|
||||
return new ReturnT<String>(500, "请输入“任务描述”");
|
||||
}
|
||||
if (jobData.get(HandlerRepository.job_url)==null || jobData.get(HandlerRepository.job_url).toString().trim().length()==0) {
|
||||
return new ReturnT<String>(500, "请输入“任务URL”");
|
||||
Class<? extends Job> jobClass_ = null;
|
||||
try {
|
||||
Class<?> clazz = Class.forName(jobClass);
|
||||
if (clazz!=null) {
|
||||
jobClass_ = (Class<? extends Job>) clazz;
|
||||
}
|
||||
} catch (ClassNotFoundException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
if (jobData.get(HandlerRepository.handleName)==null || jobData.get(HandlerRepository.handleName).toString().trim().length()==0) {
|
||||
return new ReturnT<String>(500, "请输入“任务handler”");
|
||||
if (jobClass_ == null) {
|
||||
return new ReturnT<String>(500, "请选择“JobBean”");
|
||||
}
|
||||
if (jobClass_.getClass().getName().equals(remoteJobBean.getName())) {
|
||||
if (StringUtils.isBlank(handler_address)) {
|
||||
return new ReturnT<String>(500, "请输入“远程-机器地址”");
|
||||
}
|
||||
if (StringUtils.isBlank(handler_name)) {
|
||||
return new ReturnT<String>(500, "请输入“远程-执行器”");
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(author)) {
|
||||
return new ReturnT<String>(500, "请输入“负责人”");
|
||||
}
|
||||
if (StringUtils.isBlank(alarm_email)) {
|
||||
return new ReturnT<String>(500, "请输入“报警邮件”");
|
||||
}
|
||||
|
||||
// jobClass
|
||||
Class<? extends Job> jobClass = HttpJobBean.class;
|
||||
try {
|
||||
if (DynamicSchedulerUtil.checkExists(jobName, jobGroup)) {
|
||||
return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
|
||||
}
|
||||
} catch (SchedulerException e1) {
|
||||
e1.printStackTrace();
|
||||
return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
|
||||
}
|
||||
|
||||
HashMap<String, String> jobDataMap = new HashMap<String, String>();
|
||||
jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
|
||||
jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address);
|
||||
jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name);
|
||||
|
||||
// Backup to the database
|
||||
XxlJobInfo jobInfo = new XxlJobInfo();
|
||||
jobInfo.setJobGroup(jobGroup);
|
||||
jobInfo.setJobName(jobName);
|
||||
jobInfo.setJobCron(jobCron);
|
||||
jobInfo.setJobDesc(jobDesc);
|
||||
jobInfo.setJobClass(jobClass);
|
||||
jobInfo.setJobData(JacksonUtil.writeValueAsString(jobDataMap));
|
||||
jobInfo.setAuthor(author);
|
||||
jobInfo.setAlarmEmail(alarm_email);
|
||||
jobInfo.setAlarmThreshold(alarm_threshold);
|
||||
xxlJobInfoDao.save(jobInfo);
|
||||
|
||||
try {
|
||||
// add job 2 quartz
|
||||
boolean result = DynamicSchedulerUtil.addJob(triggerKeyName, cronExpression, jobClass, null);
|
||||
if (!result) {
|
||||
return new ReturnT<String>(500, "任务ID重复,请更换确认");
|
||||
boolean result = DynamicSchedulerUtil.addJob(jobInfo);
|
||||
if (result) {
|
||||
return ReturnT.SUCCESS;
|
||||
} else {
|
||||
xxlJobInfoDao.delete(jobGroup, jobName);
|
||||
return new ReturnT<String>(500, "新增任务失败");
|
||||
}
|
||||
// Backup to the database
|
||||
XxlJobInfo jobInfo = new XxlJobInfo();
|
||||
jobInfo.setJobName(triggerKeyName);
|
||||
jobInfo.setJobCron(cronExpression);
|
||||
jobInfo.setJobClass(jobClass.getName());
|
||||
jobInfo.setJobData(JacksonUtil.writeValueAsString(jobData));
|
||||
xxlJobInfoDao.save(jobInfo);
|
||||
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -145,27 +172,30 @@ public class JobInfoController {
|
|||
|
||||
@RequestMapping("/reschedule")
|
||||
@ResponseBody
|
||||
public ReturnT<String> reschedule(String triggerKeyName, String cronExpression) {
|
||||
// triggerKeyName
|
||||
if (StringUtils.isBlank(triggerKeyName)) {
|
||||
return new ReturnT<String>(500, "请输入“任务key”");
|
||||
}
|
||||
// cronExpression
|
||||
if (StringUtils.isBlank(cronExpression)) {
|
||||
return new ReturnT<String>(500, "请输入“任务corn”");
|
||||
}
|
||||
if (!CronExpression.isValidExpression(cronExpression)) {
|
||||
return new ReturnT<String>(500, "“任务corn”不合法");
|
||||
}
|
||||
try {
|
||||
DynamicSchedulerUtil.rescheduleJob(triggerKeyName, cronExpression);
|
||||
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String jobClass,
|
||||
String handler_params, String handler_address, String handler_name,
|
||||
String author, String alarm_email, int alarm_threshold) {
|
||||
|
||||
// update
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName);
|
||||
if (jobInfo!=null) {
|
||||
jobInfo.setJobCron(cronExpression);
|
||||
xxlJobInfoDao.update(jobInfo);
|
||||
}
|
||||
// valid
|
||||
if (JobGroupEnum.match(jobGroup) == null) {
|
||||
return new ReturnT<String>(500, "请选择“任务组”");
|
||||
}
|
||||
if (StringUtils.isBlank(jobName)) {
|
||||
return new ReturnT<String>(500, "请输入“任务名”");
|
||||
}
|
||||
if (!CronExpression.isValidExpression(jobCron)) {
|
||||
return new ReturnT<String>(500, "“corn”不合法");
|
||||
}
|
||||
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName);
|
||||
jobInfo.setJobCron(jobCron);
|
||||
|
||||
try {
|
||||
// fresh quartz
|
||||
DynamicSchedulerUtil.rescheduleJob(jobInfo);
|
||||
|
||||
// fresh db
|
||||
xxlJobInfoDao.update(jobInfo);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -175,13 +205,11 @@ public class JobInfoController {
|
|||
|
||||
@RequestMapping("/remove")
|
||||
@ResponseBody
|
||||
public ReturnT<String> remove(String triggerKeyName) {
|
||||
public ReturnT<String> remove(String jobGroup, String jobName) {
|
||||
try {
|
||||
if (triggerKeyName!=null) {
|
||||
DynamicSchedulerUtil.removeJob(triggerKeyName);
|
||||
xxlJobInfoDao.delete(triggerKeyName);
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
DynamicSchedulerUtil.removeJob(jobName, jobGroup);
|
||||
xxlJobInfoDao.delete(jobGroup, jobName);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -190,15 +218,9 @@ public class JobInfoController {
|
|||
|
||||
@RequestMapping("/pause")
|
||||
@ResponseBody
|
||||
public ReturnT<String> pause(String triggerKeyName) {
|
||||
public ReturnT<String> pause(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.pauseJob(triggerKeyName);
|
||||
// update
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName);
|
||||
if (jobInfo!=null) {
|
||||
jobInfo.setJobStatus("PAUSED");
|
||||
xxlJobInfoDao.update(jobInfo);
|
||||
}
|
||||
DynamicSchedulerUtil.pauseJob(jobName, jobGroup); // jobStatus do not store
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -208,15 +230,9 @@ public class JobInfoController {
|
|||
|
||||
@RequestMapping("/resume")
|
||||
@ResponseBody
|
||||
public ReturnT<String> resume(String triggerKeyName) {
|
||||
public ReturnT<String> resume(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.resumeJob(triggerKeyName);
|
||||
// update
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName);
|
||||
if (jobInfo!=null) {
|
||||
jobInfo.setJobStatus("NORMAL");
|
||||
xxlJobInfoDao.update(jobInfo);
|
||||
}
|
||||
DynamicSchedulerUtil.resumeJob(jobName, jobGroup);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -226,9 +242,9 @@ public class JobInfoController {
|
|||
|
||||
@RequestMapping("/trigger")
|
||||
@ResponseBody
|
||||
public ReturnT<String> triggerJob(String triggerKeyName) {
|
||||
public ReturnT<String> triggerJob(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.triggerJob(triggerKeyName);
|
||||
DynamicSchedulerUtil.triggerJob(jobName, jobGroup);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -33,7 +33,9 @@ public class JobLogController {
|
|||
public IXxlJobLogDao xxlJobLogDao;
|
||||
|
||||
@RequestMapping
|
||||
public String index(Model model) {
|
||||
public String index(Model model, String jobGroup, String jobName) {
|
||||
model.addAttribute("jobGroup", jobGroup);
|
||||
model.addAttribute("jobName", jobName);
|
||||
model.addAttribute("JobGroupList", JobGroupEnum.values());
|
||||
return "joblog/index";
|
||||
}
|
||||
|
@ -71,8 +73,8 @@ public class JobLogController {
|
|||
|
||||
@RequestMapping("/save")
|
||||
@ResponseBody
|
||||
public ReturnT<String> triggerLog(int triggerLogId, String status, String msg) {
|
||||
XxlJobLog log = xxlJobLogDao.load(triggerLogId);
|
||||
public ReturnT<String> triggerLog(int trigger_log_id, String status, String msg) {
|
||||
XxlJobLog log = xxlJobLogDao.load(trigger_log_id);
|
||||
if (log!=null) {
|
||||
log.setHandleTime(new Date());
|
||||
log.setHandleStatus(status);
|
||||
|
|
|
@ -10,21 +10,22 @@ public class XxlJobInfo {
|
|||
|
||||
private int id;
|
||||
|
||||
private String jobGroup; // base on quartz 任务组
|
||||
private String jobName; // base on quartz 任务名
|
||||
private String jobCron; // base on quartz 任务执行CRON表达式
|
||||
private String jobClass; // base on quartz 任务执行JobBean
|
||||
private String jobData; // base on db, Map-JSON-String 任务执行数据
|
||||
private String jobGroup; // 任务组
|
||||
private String jobName; // 任务名
|
||||
private String jobCron; // 任务执行CRON表达式 【base on quartz】
|
||||
private String jobDesc;
|
||||
private String jobClass; // 任务执行JobBean 【base on quartz】
|
||||
private String jobData; // 任务执行数据 Map-JSON-String
|
||||
|
||||
private Date addTime;
|
||||
private Date updateTime;
|
||||
|
||||
private String author; // 作者
|
||||
private String author; // 负责人
|
||||
private String alarmEmail; // 报警邮件
|
||||
private int alarmThreshold; // 报警阀值
|
||||
|
||||
// copy from quartz
|
||||
private String jobStatus; // 任务状态
|
||||
private String jobStatus; // 任务状态 【base on quartz】
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
|
@ -58,6 +59,14 @@ public class XxlJobInfo {
|
|||
this.jobCron = jobCron;
|
||||
}
|
||||
|
||||
public String getJobDesc() {
|
||||
return jobDesc;
|
||||
}
|
||||
|
||||
public void setJobDesc(String jobDesc) {
|
||||
this.jobDesc = jobDesc;
|
||||
}
|
||||
|
||||
public String getJobClass() {
|
||||
return jobClass;
|
||||
}
|
||||
|
@ -125,9 +134,9 @@ public class XxlJobInfo {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "XxlJobInfo [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
|
||||
+ ", jobClass=" + jobClass + ", jobData=" + jobData + ", addTime=" + addTime + ", updateTime="
|
||||
+ updateTime + ", author=" + author + ", alarmEmail=" + alarmEmail + ", alarmThreshold="
|
||||
+ alarmThreshold + ", jobStatus=" + jobStatus + "]";
|
||||
+ ", jobDesc=" + jobDesc + ", jobClass=" + jobClass + ", jobData=" + jobData + ", addTime=" + addTime
|
||||
+ ", updateTime=" + updateTime + ", author=" + author + ", alarmEmail=" + alarmEmail
|
||||
+ ", alarmThreshold=" + alarmThreshold + ", jobStatus=" + jobStatus + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public class XxlJobLog {
|
|||
private String jobGroup;
|
||||
private String jobName;
|
||||
private String jobCron;
|
||||
private String jobDesc;
|
||||
private String jobClass;
|
||||
private String jobData;
|
||||
|
||||
|
@ -26,7 +27,6 @@ public class XxlJobLog {
|
|||
private Date handleTime;
|
||||
private String handleStatus;
|
||||
private String handleMsg;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -51,6 +51,12 @@ public class XxlJobLog {
|
|||
public void setJobCron(String jobCron) {
|
||||
this.jobCron = jobCron;
|
||||
}
|
||||
public String getJobDesc() {
|
||||
return jobDesc;
|
||||
}
|
||||
public void setJobDesc(String jobDesc) {
|
||||
this.jobDesc = jobDesc;
|
||||
}
|
||||
public String getJobClass() {
|
||||
return jobClass;
|
||||
}
|
||||
|
@ -103,9 +109,9 @@ public class XxlJobLog {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "XxlJobLog [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
|
||||
+ ", jobClass=" + jobClass + ", jobData=" + jobData + ", triggerTime=" + triggerTime
|
||||
+ ", triggerStatus=" + triggerStatus + ", triggerMsg=" + triggerMsg + ", handleTime=" + handleTime
|
||||
+ ", handleStatus=" + handleStatus + ", handleMsg=" + handleMsg + "]";
|
||||
+ ", jobDesc=" + jobDesc + ", jobClass=" + jobClass + ", jobData=" + jobData + ", triggerTime="
|
||||
+ triggerTime + ", triggerStatus=" + triggerStatus + ", triggerMsg=" + triggerMsg + ", handleTime="
|
||||
+ handleTime + ", handleStatus=" + handleStatus + ", handleMsg=" + handleMsg + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.xxl.job.core.util;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -29,6 +30,7 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.xxl.job.client.util.JacksonUtil;
|
||||
import com.xxl.job.core.model.XxlJobInfo;
|
||||
import com.xxl.job.dao.IXxlJobInfoDao;
|
||||
import com.xxl.job.dao.IXxlJobLogDao;
|
||||
|
@ -125,28 +127,41 @@ public final class DynamicSchedulerUtil implements InitializingBean {
|
|||
}
|
||||
}
|
||||
|
||||
// check if exists
|
||||
public static boolean checkExists(String jobName, String jobGroup) throws SchedulerException{
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
|
||||
return scheduler.checkExists(triggerKey);
|
||||
}
|
||||
|
||||
// addJob 新增
|
||||
public static boolean addJob(String triggerKeyName, String cronExpression, Class<? extends Job> jobClass, Map<String, Object> jobData) throws SchedulerException {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean addJob(XxlJobInfo jobInfo) throws SchedulerException {
|
||||
// TriggerKey : name + group
|
||||
String group = Scheduler.DEFAULT_GROUP;
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup());
|
||||
JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
|
||||
|
||||
// TriggerKey valid if_exists
|
||||
if (scheduler.checkExists(triggerKey)) {
|
||||
Trigger trigger = scheduler.getTrigger(triggerKey);
|
||||
logger.info(">>>>>>>>> Already exist trigger [" + trigger + "] by key [" + triggerKey + "] in Scheduler");
|
||||
if (checkExists(jobInfo.getJobName(), jobInfo.getJobGroup())) {
|
||||
logger.info(">>>>>>>>> addJob fail, job already exist, jobInfo:{}", jobInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
// CronTrigger : TriggerKey + cronExpression // withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度
|
||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
|
||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron()).withMisfireHandlingInstructionDoNothing();
|
||||
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
||||
|
||||
// JobDetail : jobClass
|
||||
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(triggerKeyName, group).build();
|
||||
if (jobData!=null && jobData.size() > 0) {
|
||||
Class<? extends Job> jobClass_ = null;
|
||||
try {
|
||||
jobClass_ = (Class<? extends Job>)Class.forName(jobInfo.getJobClass());
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
JobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey).build();
|
||||
if (jobInfo.getJobData()!=null) {
|
||||
JobDataMap jobDataMap = jobDetail.getJobDataMap();
|
||||
jobDataMap.putAll(jobData); // JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
|
||||
jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class)); // JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
|
||||
}
|
||||
|
||||
// schedule : jobDetail + cronTrigger
|
||||
|
@ -156,49 +171,60 @@ public final class DynamicSchedulerUtil implements InitializingBean {
|
|||
return true;
|
||||
}
|
||||
|
||||
// reschedule 重置cron
|
||||
public static boolean rescheduleJob(String triggerKeyName, String cronExpression) throws SchedulerException {
|
||||
// reschedule
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean rescheduleJob(XxlJobInfo jobInfo) throws SchedulerException {
|
||||
|
||||
// TriggerKey valid if_exists
|
||||
if (!checkExists(jobInfo.getJobName(), jobInfo.getJobGroup())) {
|
||||
logger.info(">>>>>>>>>>> rescheduleJob fail, job not exists, jobInfo:{}", jobInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TriggerKey : name + group
|
||||
String group = Scheduler.DEFAULT_GROUP;
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup());
|
||||
JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
|
||||
|
||||
boolean result = false;
|
||||
if (scheduler.checkExists(triggerKey)) {
|
||||
// CronTrigger : TriggerKey + cronExpression
|
||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
|
||||
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
||||
// CronTrigger : TriggerKey + cronExpression
|
||||
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron()).withMisfireHandlingInstructionDoNothing();
|
||||
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
|
||||
|
||||
Date date = scheduler.rescheduleJob(triggerKey, cronTrigger);
|
||||
result = true;
|
||||
logger.info(">>>>>>>>>>> resumeJob success, triggerKey:{}, cronExpression:{}, date:{}", triggerKey, cronExpression, date);
|
||||
} else {
|
||||
logger.info(">>>>>>>>>>> resumeJob fail, triggerKey:{}, cronExpression:{}", triggerKey, cronExpression);
|
||||
}
|
||||
return result;
|
||||
//scheduler.rescheduleJob(triggerKey, cronTrigger);
|
||||
|
||||
// JobDetail-JobDataMap fresh
|
||||
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
||||
JobDataMap jobDataMap = jobDetail.getJobDataMap();
|
||||
jobDataMap.clear();
|
||||
jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));
|
||||
|
||||
// Trigger fresh
|
||||
HashSet<Trigger> triggerSet = new HashSet<Trigger>();
|
||||
triggerSet.add(cronTrigger);
|
||||
|
||||
scheduler.scheduleJob(jobDetail, triggerSet, true);
|
||||
logger.info(">>>>>>>>>>> resumeJob success, jobInfo:{}", jobInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
// unscheduleJob 删除
|
||||
public static boolean removeJob(String triggerKeyName) throws SchedulerException {
|
||||
// unscheduleJob
|
||||
public static boolean removeJob(String jobName, String jobGroup) throws SchedulerException {
|
||||
// TriggerKey : name + group
|
||||
String group = Scheduler.DEFAULT_GROUP;
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
|
||||
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
|
||||
boolean result = false;
|
||||
if (scheduler.checkExists(triggerKey)) {
|
||||
if (checkExists(jobName, jobGroup)) {
|
||||
result = scheduler.unscheduleJob(triggerKey);
|
||||
logger.info(">>>>>>>>>>> removeJob, triggerKey:{}, result [{}]", triggerKey, result);
|
||||
}
|
||||
logger.info(">>>>>>>>>>> removeJob, triggerKey:{}, result [{}]", triggerKey, result);
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pause 暂停
|
||||
public static boolean pauseJob(String triggerKeyName) throws SchedulerException {
|
||||
// Pause
|
||||
public static boolean pauseJob(String jobName, String jobGroup) throws SchedulerException {
|
||||
// TriggerKey : name + group
|
||||
String group = Scheduler.DEFAULT_GROUP;
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
|
||||
|
||||
boolean result = false;
|
||||
if (scheduler.checkExists(triggerKey)) {
|
||||
if (checkExists(jobName, jobGroup)) {
|
||||
scheduler.pauseTrigger(triggerKey);
|
||||
result = true;
|
||||
logger.info(">>>>>>>>>>> pauseJob success, triggerKey:{}", triggerKey);
|
||||
|
@ -208,14 +234,13 @@ public final class DynamicSchedulerUtil implements InitializingBean {
|
|||
return result;
|
||||
}
|
||||
|
||||
// resume 重启
|
||||
public static boolean resumeJob(String triggerKeyName) throws SchedulerException {
|
||||
// TriggerKey : name + group
|
||||
String group = Scheduler.DEFAULT_GROUP;
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
|
||||
// resume
|
||||
public static boolean resumeJob(String jobName, String jobGroup) throws SchedulerException {
|
||||
// TriggerKey : name + group
|
||||
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
|
||||
|
||||
boolean result = false;
|
||||
if (scheduler.checkExists(triggerKey)) {
|
||||
if (checkExists(jobName, jobGroup)) {
|
||||
scheduler.resumeTrigger(triggerKey);
|
||||
result = true;
|
||||
logger.info(">>>>>>>>>>> resumeJob success, triggerKey:{}", triggerKey);
|
||||
|
@ -225,14 +250,13 @@ public final class DynamicSchedulerUtil implements InitializingBean {
|
|||
return result;
|
||||
}
|
||||
|
||||
// run 执行一次
|
||||
public static boolean triggerJob(String triggerKeyName) throws SchedulerException {
|
||||
// TriggerKey : name + group
|
||||
String group = Scheduler.DEFAULT_GROUP;
|
||||
JobKey jobKey = JobKey.jobKey(triggerKeyName, group);
|
||||
// run
|
||||
public static boolean triggerJob(String jobName, String jobGroup) throws SchedulerException {
|
||||
// TriggerKey : name + group
|
||||
JobKey jobKey = new JobKey(jobName, jobGroup);
|
||||
|
||||
boolean result = false;
|
||||
if (scheduler.checkExists(jobKey)) {
|
||||
if (checkExists(jobName, jobGroup)) {
|
||||
scheduler.triggerJob(jobKey);
|
||||
result = true;
|
||||
logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.xxl.job.dao;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.xxl.job.core.model.XxlJobInfo;
|
||||
|
@ -11,15 +10,15 @@ import com.xxl.job.core.model.XxlJobInfo;
|
|||
*/
|
||||
public interface IXxlJobInfoDao {
|
||||
|
||||
public List<XxlJobInfo> pageList(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd);
|
||||
public int pageListCount(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd);
|
||||
public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String jobName);
|
||||
public int pageListCount(int offset, int pagesize, String jobGroup, String jobName);
|
||||
|
||||
public int save(XxlJobInfo info);
|
||||
|
||||
public XxlJobInfo load(String jobName);
|
||||
public XxlJobInfo load(String jobGroup, String jobName);
|
||||
|
||||
public int update(XxlJobInfo item);
|
||||
|
||||
public int delete(String jobName);
|
||||
public int delete(String jobGroup, String jobName);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.xxl.job.dao.impl;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -23,25 +22,23 @@ public class XxlJobInfoDaoImpl implements IXxlJobInfoDao {
|
|||
public SqlSessionTemplate sqlSessionTemplate;
|
||||
|
||||
@Override
|
||||
public List<XxlJobInfo> pageList(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd) {
|
||||
public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String jobName) {
|
||||
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("offset", offset);
|
||||
params.put("pagesize", pagesize);
|
||||
params.put("jobGroup", jobGroup);
|
||||
params.put("jobName", jobName);
|
||||
params.put("addTimeStart", addTimeStart);
|
||||
params.put("addTimeEnd", addTimeEnd);
|
||||
|
||||
return sqlSessionTemplate.selectList("XxlJobInfoMapper.pageList", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int pageListCount(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd) {
|
||||
public int pageListCount(int offset, int pagesize, String jobGroup, String jobName) {
|
||||
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("offset", offset);
|
||||
params.put("pagesize", pagesize);
|
||||
params.put("jobGroup", jobGroup);
|
||||
params.put("jobName", jobName);
|
||||
params.put("addTimeStart", addTimeStart);
|
||||
params.put("addTimeEnd", addTimeEnd);
|
||||
|
||||
return sqlSessionTemplate.selectOne("XxlJobInfoMapper.pageListCount", params);
|
||||
}
|
||||
|
@ -52,8 +49,12 @@ public class XxlJobInfoDaoImpl implements IXxlJobInfoDao {
|
|||
}
|
||||
|
||||
@Override
|
||||
public XxlJobInfo load(String jobName) {
|
||||
return sqlSessionTemplate.selectOne("XxlJobInfoMapper.load", jobName);
|
||||
public XxlJobInfo load(String jobGroup, String jobName) {
|
||||
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("jobGroup", jobGroup);
|
||||
params.put("jobName", jobName);
|
||||
|
||||
return sqlSessionTemplate.selectOne("XxlJobInfoMapper.load", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,8 +63,12 @@ public class XxlJobInfoDaoImpl implements IXxlJobInfoDao {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int delete(String jobName) {
|
||||
return sqlSessionTemplate.update("XxlJobInfoMapper.delete", jobName);
|
||||
public int delete(String jobGroup, String jobName) {
|
||||
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("jobGroup", jobGroup);
|
||||
params.put("jobName", jobName);
|
||||
|
||||
return sqlSessionTemplate.update("XxlJobInfoMapper.delete", params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.impl.triggers.CronTriggerImpl;
|
||||
import org.quartz.JobKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
|
@ -22,8 +23,10 @@ import com.xxl.job.core.util.PropertiesUtil;
|
|||
|
||||
/**
|
||||
* http job bean
|
||||
* “@DisallowConcurrentExecution” diable concurrent, thread size can not be only one, better given more
|
||||
* @author xuxueli 2015-12-17 18:20:34
|
||||
*/
|
||||
@DisallowConcurrentExecution
|
||||
public class HttpJobBean extends QuartzJobBean {
|
||||
private static Logger logger = LoggerFactory.getLogger(HttpJobBean.class);
|
||||
|
||||
|
@ -31,35 +34,32 @@ public class HttpJobBean extends QuartzJobBean {
|
|||
@Override
|
||||
protected void executeInternal(JobExecutionContext context)
|
||||
throws JobExecutionException {
|
||||
String triggerKey = context.getTrigger().getJobKey().getName();
|
||||
|
||||
// jobDataMap 2 params
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(triggerKey);
|
||||
if (jobInfo!=null && jobInfo.getJobData()!=null) {
|
||||
params = JacksonUtil.readValue(jobInfo.getJobData(), Map.class);
|
||||
}
|
||||
|
||||
// corn
|
||||
String cornExp = null;
|
||||
if (context.getTrigger() instanceof CronTriggerImpl) {
|
||||
CronTriggerImpl trigger = (CronTriggerImpl) context.getTrigger();
|
||||
cornExp = trigger.getCronExpression();
|
||||
}
|
||||
JobKey jobKey = context.getTrigger().getJobKey();
|
||||
|
||||
XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKey.getGroup(), jobKey.getName());
|
||||
HashMap<String, String> jobDataMap = (HashMap<String, String>) JacksonUtil.readValueRefer(jobInfo.getJobData(), Map.class);
|
||||
// save log
|
||||
XxlJobLog jobLog = new XxlJobLog();
|
||||
jobLog.setJobName(triggerKey);
|
||||
jobLog.setJobCron(cornExp);
|
||||
jobLog.setJobGroup(jobInfo.getJobGroup());
|
||||
jobLog.setJobName(jobInfo.getJobName());
|
||||
jobLog.setJobCron(jobInfo.getJobCron());
|
||||
jobLog.setJobDesc(jobInfo.getJobDesc());
|
||||
jobLog.setJobClass(jobInfo.getJobClass());
|
||||
jobLog.setJobData(jobInfo.getJobData());
|
||||
|
||||
jobLog.setJobClass(HttpJobBean.class.getName());
|
||||
jobLog.setJobData(jobInfo.getJobData());
|
||||
DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
|
||||
logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog);
|
||||
|
||||
// trigger request
|
||||
params.put(HandlerRepository.triggerLogId, String.valueOf(jobLog.getId()));
|
||||
params.put(HandlerRepository.triggerLogUrl, PropertiesUtil.getString(HandlerRepository.triggerLogUrl));
|
||||
String[] postResp = HttpUtil.post(params.get(HandlerRepository.job_url), params);
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
params.put(HandlerRepository.TRIGGER_LOG_URL, PropertiesUtil.getString(HandlerRepository.TRIGGER_LOG_URL));
|
||||
params.put(HandlerRepository.TRIGGER_LOG_ID, String.valueOf(jobLog.getId()));
|
||||
params.put(HandlerRepository.HANDLER_NAME, jobDataMap.get(HandlerRepository.HANDLER_NAME));
|
||||
params.put(HandlerRepository.HANDLER_PARAMS, jobDataMap.get(HandlerRepository.HANDLER_PARAMS));
|
||||
|
||||
String[] postResp = HttpUtil.post(jobDataMap.get(HandlerRepository.HANDLER_ADDRESS), params);
|
||||
logger.info(">>>>>>>>>>> xxl-job trigger http response, jobLog.id:{}, jobLog:{}", jobLog.getId(), jobLog);
|
||||
|
||||
// parse trigger response
|
||||
|
|
|
@ -6,37 +6,45 @@
|
|||
<resultMap id="XxlJobInfo" type="com.xxl.job.core.model.XxlJobInfo" >
|
||||
<result column="id" property="id" />
|
||||
|
||||
<result column="job_group" property="jobGroup" />
|
||||
<result column="job_name" property="jobName" />
|
||||
<result column="job_cron" property="jobCron" />
|
||||
<result column="job_desc" property="jobDesc" />
|
||||
<result column="job_class" property="jobClass" />
|
||||
<result column="job_data" property="jobData" />
|
||||
|
||||
<result column="add_time" property="addTime" />
|
||||
<result column="update_time" property="updateTime" />
|
||||
|
||||
<result column="author" property="author" />
|
||||
<result column="alarm_email" property="alarmEmail" />
|
||||
<result column="alarm_threshold" property="alarmThreshold" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
t.id,
|
||||
t.job_group,
|
||||
t.job_name,
|
||||
t.job_cron,
|
||||
t.job_desc,
|
||||
t.job_class,
|
||||
t.job_data,
|
||||
t.add_time,
|
||||
t.update_time
|
||||
t.update_time,
|
||||
t.author,
|
||||
t.alarm_email,
|
||||
t.alarm_threshold
|
||||
</sql>
|
||||
|
||||
<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
|
||||
SELECT <include refid="Base_Column_List" />
|
||||
FROM xxl_job_qrtz_trigger_info AS t
|
||||
<trim prefix="WHERE" prefixOverrides="AND | OR" >
|
||||
<if test="jobName != null and jobName!=''">
|
||||
AND t.job_name = #{jobName}
|
||||
<if test="jobGroup != null and jobGroup != ''">
|
||||
AND t.job_group = #{jobGroup}
|
||||
</if>
|
||||
<if test="addTimeStart != null">
|
||||
AND t.add_time <![CDATA[ > ]]> #{addTimeStart}
|
||||
</if>
|
||||
<if test="addTimeEnd != null">
|
||||
AND t.add_time <![CDATA[ < ]]> #{addTimeEnd}
|
||||
<if test="jobName != null and jobName != ''">
|
||||
AND t.job_name like CONCAT(CONCAT('%', #{jobName}), '%')
|
||||
</if>
|
||||
</trim>
|
||||
ORDER BY id DESC
|
||||
|
@ -47,56 +55,74 @@
|
|||
SELECT count(1)
|
||||
FROM xxl_job_qrtz_trigger_info AS t
|
||||
<trim prefix="WHERE" prefixOverrides="AND | OR" >
|
||||
<if test="jobName != null and jobName!=''">
|
||||
AND t.job_name = #{jobName}
|
||||
<if test="jobGroup != null and jobGroup != ''">
|
||||
AND t.job_group = #{jobGroup}
|
||||
</if>
|
||||
<if test="addTimeStart != null">
|
||||
AND t.add_time <![CDATA[ > ]]> #{addTimeStart}
|
||||
</if>
|
||||
<if test="addTimeEnd != null">
|
||||
AND t.add_time <![CDATA[ < ]]> #{addTimeEnd}
|
||||
<if test="jobName != null and jobName != ''">
|
||||
AND t.job_name like CONCAT(CONCAT('%', #{jobName}), '%')
|
||||
</if>
|
||||
</trim>
|
||||
</select>
|
||||
|
||||
<insert id="save" parameterType="com.xxl.job.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" >
|
||||
INSERT INTO `xxl_job_qrtz_trigger_info` (
|
||||
`job_name`,
|
||||
`job_cron`,
|
||||
`job_class`,
|
||||
`job_data`,
|
||||
`add_time`,
|
||||
`update_time`
|
||||
job_group,
|
||||
job_name,
|
||||
job_cron,
|
||||
job_desc,
|
||||
job_class,
|
||||
job_data,
|
||||
add_time,
|
||||
update_time,
|
||||
author,
|
||||
alarm_email,
|
||||
alarm_threshold
|
||||
) VALUES (
|
||||
#{jobGroup},
|
||||
#{jobName},
|
||||
#{jobCron},
|
||||
#{jobDesc},
|
||||
#{jobClass},
|
||||
#{jobData},
|
||||
NOW(),
|
||||
NOW()
|
||||
NOW(),
|
||||
#{author},
|
||||
#{alarmEmail},
|
||||
#{alarmThreshold}
|
||||
);
|
||||
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
|
||||
SELECT LAST_INSERT_ID()
|
||||
</selectKey>
|
||||
</insert>
|
||||
|
||||
<select id="load" parameterType="java.lang.String" resultMap="XxlJobInfo">
|
||||
<select id="load" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
|
||||
SELECT <include refid="Base_Column_List" />
|
||||
FROM xxl_job_qrtz_trigger_info AS t
|
||||
WHERE t.job_name = #{jobName}
|
||||
WHERE t.job_group = #{jobGroup}
|
||||
AND t.job_name = #{jobName}
|
||||
</select>
|
||||
|
||||
<update id="update">
|
||||
<update id="update" parameterType="com.xxl.job.core.model.XxlJobInfo" >
|
||||
UPDATE `xxl_job_qrtz_trigger_info`
|
||||
SET `job_cron`= #{jobCron},
|
||||
`job_data`= #{jobData},
|
||||
`update_time`= NOW()
|
||||
WHERE `id`= #{id}
|
||||
SET
|
||||
job_cron = #{jobCron},
|
||||
job_desc = #{jobDesc},
|
||||
job_data = #{jobData},
|
||||
update_time = NOW(),
|
||||
author = #{author},
|
||||
alarm_email = #{alarmEmail},
|
||||
alarm_threshold = #{alarmThreshold}
|
||||
WHERE job_group = #{jobGroup}
|
||||
AND job_name = #{jobName}
|
||||
</update>
|
||||
|
||||
<delete id="delete" parameterType="java.lang.String">
|
||||
delete from xxl_job_qrtz_trigger_info
|
||||
where job_name = #{jobName}
|
||||
DELETE
|
||||
FROM
|
||||
xxl_job_qrtz_trigger_info
|
||||
WHERE
|
||||
job_group = #{jobGroup}
|
||||
AND job_name = #{jobName}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
|
@ -9,6 +9,7 @@
|
|||
<result column="job_group" property="jobGroup" />
|
||||
<result column="job_name" property="jobName" />
|
||||
<result column="job_cron" property="jobCron" />
|
||||
<result column="job_desc" property="jobDesc" />
|
||||
<result column="job_class" property="jobClass" />
|
||||
<result column="job_data" property="jobData" />
|
||||
|
||||
|
@ -26,8 +27,9 @@
|
|||
t.job_group,
|
||||
t.job_name,
|
||||
t.job_cron,
|
||||
t.job_desc,
|
||||
t.job_class,
|
||||
t.job_data,
|
||||
t.job_desc,
|
||||
t.trigger_time,
|
||||
t.trigger_status,
|
||||
t.trigger_msg,
|
||||
|
@ -94,12 +96,14 @@
|
|||
`job_group`,
|
||||
`job_name`,
|
||||
`job_cron`,
|
||||
`job_desc`,
|
||||
`job_class`,
|
||||
`job_data`
|
||||
) VALUES (
|
||||
#{jobGroup},
|
||||
#{jobName},
|
||||
#{jobCron},
|
||||
#{jobDesc},
|
||||
#{jobClass},
|
||||
#{jobData}
|
||||
);
|
||||
|
|
|
@ -42,9 +42,7 @@
|
|||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">
|
||||
jobName
|
||||
</span>
|
||||
<span class="input-group-addon">任务名</span>
|
||||
<input type="text" class="form-control" id="jobName" value="${jobName}" autocomplete="on" >
|
||||
</div>
|
||||
</div>
|
||||
|
@ -66,63 +64,23 @@
|
|||
<table id="job_list" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>id</th>
|
||||
<th>任务Key</th>
|
||||
<th>任务Cron</th>
|
||||
<th>任务Class</th>
|
||||
<th>状态Status</th>
|
||||
<th>参数</th>
|
||||
<th>addTime</th>
|
||||
<th>updateTime</th>
|
||||
<th name="id" >id</th>
|
||||
<th name="jobGroup" >任务组</th>
|
||||
<th name="jobName" >任务名</th>
|
||||
<th name="jobCron" >Cron</th>
|
||||
<th name="jobDesc" >描述</th>
|
||||
<th name="jobClass" >JobBean</th>
|
||||
<th name="jobData" >任务数据</th>
|
||||
<th name="addTime" >新增时间</th>
|
||||
<th name="updateTime" >更新时间</th>
|
||||
<th name="author" >负责人</th>
|
||||
<th name="alarmEmail" >报警邮件</th>
|
||||
<th name="alarmThreshold" >报警阀值</th>
|
||||
<th name="jobStatus" >状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<#--
|
||||
<#if jobList?exists && jobList?size gt 0>
|
||||
<#list jobList as item>
|
||||
<tr>
|
||||
<td>${item['TriggerKey'].name}</td>
|
||||
<td>${item['Trigger'].cronExpression}</td>
|
||||
<td>${item['JobDetail'].jobClass}</td>
|
||||
<td>
|
||||
<#assign jobDataMap = item['JobDetail'].jobDataMap />
|
||||
<#if jobDataMap?exists && jobDataMap?keys?size gt 0>
|
||||
<#list jobDataMap?keys as key>
|
||||
${key} = ${jobDataMap[key]} <br>
|
||||
</#list>
|
||||
</#if>
|
||||
</td>
|
||||
<td state="${item['TriggerState']}" >
|
||||
<#if item['TriggerState'] == 'NORMAL'>
|
||||
<button class="btn btn-block btn-success" type="button">运行ing</button>
|
||||
<#elseif item['TriggerState'] == 'PAUSED'>
|
||||
<button class="btn btn-block btn-warning" type="button">暂停ing</button>
|
||||
<#else>
|
||||
<button class="btn btn-block" type="button">${item['TriggerState']}</button>
|
||||
</#if>
|
||||
</td>
|
||||
<td>
|
||||
<p name="${item['TriggerKey'].name}" group="${item['TriggerKey'].group}"
|
||||
cronExpression="${item['Trigger'].cronExpression}" jobClassName="${item['JobDetail'].jobClass}" jobDesc="${job_desc?if_exists}" >
|
||||
<#if item['TriggerState'] == 'NORMAL'>
|
||||
<button class="btn btn-info btn-xs job_operate" type="job_pause" type="button">暂停</button>
|
||||
<#elseif item['TriggerState'] == 'PAUSED'>
|
||||
<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button>
|
||||
</#if>
|
||||
<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行一次</button>
|
||||
<button class="btn btn-info btn-xs update" type="button">更新corn</button>
|
||||
<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>
|
||||
<button class="btn btn-warning btn-xs" type="job_del" type="button"
|
||||
onclick="javascript:window.open('${request.contextPath}/joblog?jobName=${item['TriggerKey'].name}')" >查看日志</button>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</#list>
|
||||
</#if>
|
||||
|
||||
-->
|
||||
</tbody>
|
||||
<tbody></tbody>
|
||||
<tfoot></tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -155,29 +113,51 @@
|
|||
</select>
|
||||
</div>
|
||||
<label for="firstname" class="col-sm-2 control-label">任务名</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="triggerKeyName" placeholder="请输入任务Key" minlength="4" maxlength="100" ></div>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="jobName" placeholder="请输入“任务名”" minlength="4" maxlength="100" ></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastname" class="col-sm-3 control-label">任务Corn</label>
|
||||
<div class="col-sm-9"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn" maxlength="100" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">Corn</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Corn”" maxlength="100" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">描述</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="200" ></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastname" class="col-sm-3 control-label">任务描述</label>
|
||||
<div class="col-sm-9"><input type="text" class="form-control" name="job_desc" placeholder="请输入任务描述" maxlength="200" ></div>
|
||||
<label for="firstname" class="col-sm-2 control-label">JobBean</label>
|
||||
<div class="col-sm-4">
|
||||
<select class="form-control" name="jobClass" >
|
||||
<#if remoteJobBean?exists >
|
||||
<option value="${remoteJobBean.name}" jobClassType="remote" >【远程任务】</option>
|
||||
</#if>
|
||||
<#if localJobBeanList?exists && localJobBeanList?size gt 0 >
|
||||
<#list localJobBeanList as localJobBean>
|
||||
<option value="${localJobBean.name}" jobClassType="local" >${localJobBean.name}</option>
|
||||
</#list>
|
||||
</#if>
|
||||
</select>
|
||||
</div>
|
||||
<label for="firstname" class="col-sm-2 control-label">执行参数</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
|
||||
</div>
|
||||
<div class="form-group remote_panel">
|
||||
<label for="lastname" class="col-sm-2 control-label">远程-机器地址</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“远程-机器地址”" maxlength="200" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">远程-执行器</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“远程-执行器”" maxlength="200" ></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastname" class="col-sm-3 control-label">任务URL</label>
|
||||
<div class="col-sm-9"><input type="text" class="form-control" name="job_url" placeholder="请输入任务URL" maxlength="200" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">负责人</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">报警邮件</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="alarm_email" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="200" ></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastname" class="col-sm-3 control-label">任务handler</label>
|
||||
<div class="col-sm-9"><input type="text" class="form-control" name="handleName" placeholder="请输入任务handler" maxlength="200" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">报警阈值</label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="alarm_threshold" placeholder="请输入“报警阈值”" maxlength="200" ></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<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-info pull-right addParam">+ arg</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<span class="input-group-addon">任务组</span>
|
||||
<select class="form-control" id="jobGroup" >
|
||||
<#list JobGroupList as group>
|
||||
<option value="${group}" <#if jobInfo?exists && group == jobInfo.jobGroup>selected</#if> >${group.desc}</option>
|
||||
<option value="${group}" <#if jobGroup == group>selected</#if> >${group.desc}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -74,6 +74,7 @@
|
|||
<th name="jobGroup" >任务组</th>
|
||||
<th name="jobName" >任务名</th>
|
||||
<th name="jobCron" >Cron</th>
|
||||
<th name="jobDesc" >描述</th>
|
||||
<th name="jobClass" >JobBean</th>
|
||||
<th name="jobData" >任务数据</th>
|
||||
<th name="triggerTime" >调度时间</th>
|
||||
|
|
|
@ -7,32 +7,68 @@ $(function() {
|
|||
"ajax": {
|
||||
url: base_url + "/jobinfo/pageList",
|
||||
data : function ( d ) {
|
||||
d.jobName = $('#jobName').val()
|
||||
d.jobGroup = $('#jobGroup').val();
|
||||
d.jobName = $('#jobName').val();
|
||||
}
|
||||
},
|
||||
"searching": false,
|
||||
"ordering": false,
|
||||
//"scrollX": true, // X轴滚动条,取消自适应
|
||||
"columns": [
|
||||
{ "data": 'id', "bSortable": false, "visible" : false},
|
||||
{ "data": 'jobName', "bSortable": false},
|
||||
{ "data": 'jobCron', "bSortable": false, "visible" : true},
|
||||
{ "data": 'jobClass', "bSortable": false, "visible" : false},
|
||||
{ "data": 'jobStatus', "bSortable": false, "visible" : true},
|
||||
{ "data": 'jobData', "bSortable": false, "visible" : true},
|
||||
{
|
||||
"data": 'jobGroup',
|
||||
"render": function ( data, type, row ) {
|
||||
var groupMenu = $("#jobGroup").find("option");
|
||||
for ( var index in $("#jobGroup").find("option")) {
|
||||
if ($(groupMenu[index]).attr('value') == data) {
|
||||
return $(groupMenu[index]).html();
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
},
|
||||
{ "data": 'jobName'},
|
||||
{ "data": 'jobCron', "visible" : true},
|
||||
{ "data": 'jobDesc', "visible" : false},
|
||||
{ "data": 'jobClass', "visible" : true},
|
||||
{
|
||||
"data": 'jobData',
|
||||
"visible" : true,
|
||||
"render": function ( data, type, row ) {
|
||||
return data?'<a class="logTips" href="javascript:;" >查看<span style="display:none;">'+ data +'</span></a>':"无";
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": 'addTime',
|
||||
"bSortable": false,
|
||||
"visible" : false,
|
||||
"render": function ( data, type, row ) {
|
||||
return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": 'updateTime',
|
||||
"bSortable": false,
|
||||
"visible" : false,
|
||||
"render": function ( data, type, row ) {
|
||||
return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
|
||||
}
|
||||
},
|
||||
{ "data": '操作' , "bSortable": false,
|
||||
{ "data": 'author', "visible" : true},
|
||||
{ "data": 'alarmEmail', "visible" : false},
|
||||
{ "data": 'alarmThreshold', "visible" : false},
|
||||
{
|
||||
"data": 'jobStatus',
|
||||
"visible" : true,
|
||||
"render": function ( data, type, row ) {
|
||||
if ('NORMAL' == data) {
|
||||
return '<small class="label label-success" ><i class="fa fa-clock-o"></i>'+ data +'</small>';
|
||||
} else if ('PAUSED' == data){
|
||||
return '<small class="label label-default"><i class="fa fa-clock-o"></i>'+ data +'</small>';
|
||||
}
|
||||
return data;
|
||||
}
|
||||
},
|
||||
{ "data": '操作' ,
|
||||
"render": function ( data, type, row ) {
|
||||
return function(){
|
||||
// status
|
||||
|
@ -43,23 +79,31 @@ $(function() {
|
|||
pause_resume = '<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button> ';
|
||||
}
|
||||
// log url
|
||||
var logUrl = base_url +'/joblog?jobName='+ row.jobName;
|
||||
var logUrl = base_url +'/joblog?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName;
|
||||
|
||||
// job data
|
||||
var jobDataMap = eval('(' + row.jobData + ')');
|
||||
|
||||
var html = '<p jobName="'+ row.jobName +'" '+
|
||||
' cronExpression="'+ row.jobCron +'" '+
|
||||
' job_desc="'+jobDataMap.job_desc +'" '+
|
||||
' job_url="'+ jobDataMap.job_url +'" '+
|
||||
' handleName="'+ jobDataMap.handleName +'" '+
|
||||
var html = '<p id="'+ row.id +'" '+
|
||||
' jobGroup="'+ row.jobGroup +'" '+
|
||||
' jobName="'+ row.jobName +'" '+
|
||||
' jobCron="'+ row.jobCron +'" '+
|
||||
' jobDesc="'+ row.jobDesc +'" '+
|
||||
' jobClass="'+ row.jobClass +'" '+
|
||||
' jobData="'+ row.jobData +'" '+
|
||||
' author="'+ row.author +'" '+
|
||||
' alarmEmail="'+ row.alarmEmail +'" '+
|
||||
' alarmThreshold="'+ row.alarmThreshold +'" '+
|
||||
' handler_params="'+jobDataMap.handler_params +'" '+
|
||||
' handler_address="'+ jobDataMap.handler_address +'" '+
|
||||
' handler_name="'+ jobDataMap.handler_name +'" '+
|
||||
'>'+
|
||||
pause_resume +
|
||||
'<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行</button> '+
|
||||
'<button class="btn btn-info btn-xs update" type="button">更新corn</button> '+
|
||||
'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button> '+
|
||||
'<button class="btn btn-warning btn-xs update" type="button">编辑</button><br> '+
|
||||
'<button class="btn btn-warning btn-xs" type="job_del" type="button" '+
|
||||
'onclick="javascript:window.open(\'' + logUrl + '\')" >查看日志</button>'+
|
||||
'onclick="javascript:window.open(\'' + logUrl + '\')" >查看日志</button> '+
|
||||
'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button> '+
|
||||
'</p>';
|
||||
|
||||
|
||||
|
@ -68,8 +112,6 @@ $(function() {
|
|||
}
|
||||
}
|
||||
],
|
||||
"searching": false,
|
||||
"ordering": true,
|
||||
"language" : {
|
||||
"sProcessing" : "处理中...",
|
||||
"sLengthMenu" : "每页 _MENU_ 条记录",
|
||||
|
@ -96,6 +138,12 @@ $(function() {
|
|||
}
|
||||
});
|
||||
|
||||
// 日志弹框提示
|
||||
$('#job_list').on('click', '.logTips', function(){
|
||||
var msg = $(this).find('span').html();
|
||||
ComAlertTec.show(msg);
|
||||
});
|
||||
|
||||
// 搜索按钮
|
||||
$('#searchBtn').on('click', function(){
|
||||
jobTable.fnDraw();
|
||||
|
@ -108,28 +156,30 @@ $(function() {
|
|||
var type = $(this).attr("type");
|
||||
if ("job_pause" == type) {
|
||||
typeName = "暂停";
|
||||
url = base_url + "/job/pause";
|
||||
url = base_url + "/jobinfo/pause";
|
||||
} else if ("job_resume" == type) {
|
||||
typeName = "恢复";
|
||||
url = base_url + "/job/resume";
|
||||
url = base_url + "/jobinfo/resume";
|
||||
} else if ("job_del" == type) {
|
||||
typeName = "删除";
|
||||
url = base_url + "/job/remove";
|
||||
url = base_url + "/jobinfo/remove";
|
||||
} else if ("job_trigger" == type) {
|
||||
typeName = "执行一次";
|
||||
url = base_url + "/job/trigger";
|
||||
typeName = "执行";
|
||||
url = base_url + "/jobinfo/trigger";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
var name = $(this).parent('p').attr("jobName");
|
||||
var jobGroup = $(this).parent('p').attr("jobGroup");
|
||||
var jobName = $(this).parent('p').attr("jobName");
|
||||
|
||||
ComConfirm.show("确认" + typeName + "?", function(){
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : url,
|
||||
data : {
|
||||
"triggerKeyName" : name
|
||||
"jobGroup" : jobGroup,
|
||||
"jobName" : jobName
|
||||
},
|
||||
dataType : "json",
|
||||
success : function(data){
|
||||
|
@ -162,50 +212,74 @@ $(function() {
|
|||
errorClass : 'help-block',
|
||||
focusInvalid : true,
|
||||
rules : {
|
||||
triggerKeyName : {
|
||||
jobName : {
|
||||
required : true ,
|
||||
minlength: 4,
|
||||
maxlength: 100,
|
||||
myValid01:true
|
||||
},
|
||||
cronExpression : {
|
||||
jobCron : {
|
||||
required : true ,
|
||||
maxlength: 100
|
||||
},
|
||||
job_desc : {
|
||||
jobDesc : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
job_url : {
|
||||
handler_address : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
handleName : {
|
||||
handler_name : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
author : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
alarm_email : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
alarm_threshold : {
|
||||
required : true ,
|
||||
digits:true
|
||||
}
|
||||
},
|
||||
messages : {
|
||||
triggerKeyName : {
|
||||
required :"请输入“任务Key”." ,
|
||||
minlength:"“任务Key”长度不应低于4位",
|
||||
maxlength:"“任务Key”长度不应超过100位"
|
||||
jobName : {
|
||||
required :"请输入“任务名”" ,
|
||||
minlength:"“任务名”长度不应低于4位",
|
||||
maxlength:"“任务名”长度不应超过100位"
|
||||
},
|
||||
cronExpression : {
|
||||
required :"请输入“任务Corn”." ,
|
||||
maxlength:"“任务Corn”长度不应超过100位"
|
||||
jobCron : {
|
||||
required :"请输入“Corn”." ,
|
||||
maxlength:"“Corn”长度不应超过100位"
|
||||
},
|
||||
job_desc : {
|
||||
jobDesc : {
|
||||
required :"请输入“任务描述”." ,
|
||||
maxlength:"“任务描述”长度不应超过200位"
|
||||
},
|
||||
job_url : {
|
||||
required :"请输入“任务URL”." ,
|
||||
maxlength:"“任务URL”长度不应超过200位"
|
||||
handler_address : {
|
||||
required :"请输入“远程-机器地址”." ,
|
||||
maxlength:"“远程-机器地址”长度不应超过200位"
|
||||
},
|
||||
handleName : {
|
||||
required : "请输入“任务handler”." ,
|
||||
maxlength: "“任务handler”长度不应超过200位"
|
||||
handler_name : {
|
||||
required : "请输入“远程-执行器”." ,
|
||||
maxlength: "“远程-执行器”长度不应超过200位"
|
||||
},
|
||||
author : {
|
||||
required : "请输入“负责人”." ,
|
||||
maxlength: "“负责人”长度不应超过50位"
|
||||
},
|
||||
alarm_email : {
|
||||
required : "请输入“报警邮件”." ,
|
||||
maxlength: "“报警邮件”长度不应超过200位"
|
||||
},
|
||||
alarm_threshold : {
|
||||
required : "请输入“报警阈值”." ,
|
||||
digits:"阀值应该为整数."
|
||||
}
|
||||
},
|
||||
highlight : function(element) {
|
||||
|
@ -219,52 +293,20 @@ $(function() {
|
|||
element.parent('div').append(error);
|
||||
},
|
||||
submitHandler : function(form) {
|
||||
|
||||
var triggerKeyName = $('#addModal input[name="triggerKeyName"]').val();
|
||||
var cronExpression = $('#addModal input[name="cronExpression"]').val();
|
||||
var job_desc = $('#addModal input[name="job_desc"]').val();
|
||||
var job_url = $('#addModal input[name="job_url"]').val();
|
||||
var handleName = $('#addModal input[name="handleName"]').val();
|
||||
|
||||
var paramStr = 'triggerKeyName=' + triggerKeyName +
|
||||
'&cronExpression=' + cronExpression +
|
||||
'&job_desc=' + job_desc +
|
||||
'&job_url=' + job_url +
|
||||
'&handleName=' + handleName;
|
||||
|
||||
var ifFin = true;
|
||||
$('#addModal .newParam').each(function(){
|
||||
ifFin = false;
|
||||
var key = $(this).find('input[name="key"]').val();
|
||||
var value = $(this).find('input[name="value"]').val();
|
||||
if (!key) {
|
||||
ComAlert.show(2, "新增参数key不可为空");
|
||||
return;
|
||||
} else {
|
||||
if(!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(key)){
|
||||
ComAlert.show(2, "新增参数key不合法, 只支持英文字母开头,只含有英文字母、数字和下划线");
|
||||
return;
|
||||
}
|
||||
}
|
||||
paramStr += "&" + key + "=" + value;
|
||||
ifFin = true;
|
||||
});
|
||||
|
||||
if(ifFin){
|
||||
$.post(base_url + "/job/add", paramStr, function(data, status) {
|
||||
if (data.code == "200") {
|
||||
ComAlert.show(1, "新增调度任务成功", function(){
|
||||
window.location.reload();
|
||||
});
|
||||
} else {
|
||||
if (data.msg) {
|
||||
ComAlert.show(2, data.msg);
|
||||
} else {
|
||||
ComAlert.show(2, "新增失败");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$.post(base_url + "/jobinfo/add", $("#addModal .form").serialize(), function(data, status) {
|
||||
if (data.code == "200") {
|
||||
ComAlert.show(1, "新增调度任务成功", function(){
|
||||
ComAlert.show(1, "新增任务成功");
|
||||
jobTable.fnDraw();
|
||||
});
|
||||
} else {
|
||||
if (data.msg) {
|
||||
ComAlert.show(2, data.msg);
|
||||
} else {
|
||||
ComAlert.show(2, "新增失败");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$("#addModal").on('hide.bs.modal', function () {
|
||||
|
@ -273,19 +315,16 @@ $(function() {
|
|||
$("#addModal .form .form-group").removeClass("has-error");
|
||||
});
|
||||
|
||||
// 新增-添加参数
|
||||
$("#addModal .addParam").on('click', function () {
|
||||
var html = '<div class="form-group newParam">'+
|
||||
'<label for="lastname" class="col-sm-2 control-label">参数 <button class="btn btn-danger btn-xs removeParam" type="button">移除</button></label>'+
|
||||
'<div class="col-sm-4"><input type="text" class="form-control" name="key" placeholder="请输入参数key[将会强转为String]" maxlength="200" /></div>'+
|
||||
'<div class="col-sm-6"><input type="text" class="form-control" name="value" placeholder="请输入参数value[将会强转为String]" maxlength="200" /></div>'+
|
||||
'</div>';
|
||||
$(this).parents('.form-group').parent().append(html);
|
||||
|
||||
$("#addModal .removeParam").on('click', function () {
|
||||
$(this).parents('.form-group').remove();
|
||||
});
|
||||
});
|
||||
// 远程任务/本地任务,切换
|
||||
$("#addModal select[name='jobClass']").change(function() {
|
||||
//console.log($(this).val());
|
||||
console.log( $(this).val().indexOf('HttpJobBean') );
|
||||
if($(this).val().indexOf('HttpJobBean') > -1){
|
||||
$(".remote_panel").show(); // remote
|
||||
} else if($(this).val().indexOf('HttpJobBean') == -1){
|
||||
$(".remote_panel").hide(); // local
|
||||
}
|
||||
});
|
||||
|
||||
// 更新
|
||||
$("#job_list").on('click', '.update',function() {
|
||||
|
@ -376,4 +415,20 @@ $(function() {
|
|||
$("#updateModal .form")[0].reset()
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
// 新增-添加参数
|
||||
$("#addModal .addParam").on('click', function () {
|
||||
var html = '<div class="form-group newParam">'+
|
||||
'<label for="lastname" class="col-sm-2 control-label">参数 <button class="btn btn-danger btn-xs removeParam" type="button">移除</button></label>'+
|
||||
'<div class="col-sm-4"><input type="text" class="form-control" name="key" placeholder="请输入参数key[将会强转为String]" maxlength="200" /></div>'+
|
||||
'<div class="col-sm-6"><input type="text" class="form-control" name="value" placeholder="请输入参数value[将会强转为String]" maxlength="200" /></div>'+
|
||||
'</div>';
|
||||
$(this).parents('.form-group').parent().append(html);
|
||||
|
||||
$("#addModal .removeParam").on('click', function () {
|
||||
$(this).parents('.form-group').remove();
|
||||
});
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
|
|
@ -33,6 +33,7 @@ $(function() {
|
|||
},
|
||||
{ "data": 'jobName'},
|
||||
{ "data": 'jobCron', "visible" : false},
|
||||
{ "data": 'jobDesc', "visible" : false},
|
||||
{ "data": 'jobClass', "visible" : false},
|
||||
{
|
||||
"data": 'jobData',
|
||||
|
|
|
@ -21,8 +21,8 @@ public class XxlJobInfoTest {
|
|||
|
||||
@Test
|
||||
public void pageList(){
|
||||
List<XxlJobInfo> list = xxlJobInfoDao.pageList(0, 20, null, null, null);
|
||||
int list_count = xxlJobInfoDao.pageListCount(0, 20, null, null, null);
|
||||
List<XxlJobInfo> list = xxlJobInfoDao.pageList(0, 20, null, null);
|
||||
int list_count = xxlJobInfoDao.pageListCount(0, 20, null, null);
|
||||
|
||||
System.out.println(list);
|
||||
System.out.println(list_count);
|
||||
|
@ -39,13 +39,13 @@ public class XxlJobInfoTest {
|
|||
System.out.println(count);
|
||||
System.out.println(info.getId());
|
||||
|
||||
XxlJobInfo item = xxlJobInfoDao.load("job_name");
|
||||
XxlJobInfo item = xxlJobInfoDao.load(null ,"job_name");
|
||||
System.out.println(item);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update(){
|
||||
XxlJobInfo item = xxlJobInfoDao.load("job_name");
|
||||
XxlJobInfo item = xxlJobInfoDao.load(null ,"job_name");
|
||||
|
||||
item.setJobCron("jobCron2");
|
||||
item.setJobData("jobData2");
|
||||
|
|
|
@ -57,8 +57,8 @@ public class XxlJobLogTest {
|
|||
|
||||
@Test
|
||||
public void pageList(){
|
||||
List<XxlJobLog> list = xxlJobLogDao.pageList(0, 20, null, null, null);
|
||||
int list_count = xxlJobLogDao.pageListCount(0, 20, null, null, null);
|
||||
List<XxlJobLog> list = xxlJobLogDao.pageList(0, 20, null, null, null, null);
|
||||
int list_count = xxlJobLogDao.pageListCount(0, 20, null, null, null, null);
|
||||
|
||||
System.out.println(list);
|
||||
System.out.println(list_count);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.xxl.job.service.handler;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -20,12 +19,12 @@ public class DemoJobHandler extends IJobHandler {
|
|||
private static transient Logger logger = LoggerFactory.getLogger(DemoJobHandler.class);
|
||||
|
||||
public DemoJobHandler() {
|
||||
HandlerRepository.regist(DemoJobHandler.class.getName(), this);
|
||||
HandlerRepository.regist("demoJobHandler", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobHandleStatus handle(Map<String, String> param) throws Exception {
|
||||
logger.info(" ... param:{}", param);
|
||||
public JobHandleStatus handle(String... params) throws Exception {
|
||||
logger.info(" ... params:" + params);
|
||||
TimeUnit.SECONDS.sleep(new Random().nextInt(5));
|
||||
return JobHandleStatus.SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,15 @@
|
|||
package com.xxl.job.client.handler;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.xxl.job.client.handler.IJobHandler.JobHandleStatus;
|
||||
import com.xxl.job.client.util.HttpUtil;
|
||||
import com.xxl.job.client.util.JacksonUtil;
|
||||
|
||||
|
||||
/**
|
||||
* handler repository
|
||||
* @author xuxueli 2015-12-19 19:28:44
|
||||
|
@ -23,142 +17,47 @@ import com.xxl.job.client.util.JacksonUtil;
|
|||
public class HandlerRepository {
|
||||
private static Logger logger = LoggerFactory.getLogger(HandlerRepository.class);
|
||||
|
||||
public static final String job_desc = "job_desc";
|
||||
public static final String job_url = "job_url";
|
||||
public static final String handleName = "handleName";
|
||||
public static final String triggerLogId = "triggerLogId";
|
||||
public static final String triggerLogUrl = "triggerLogUrl";
|
||||
public static final String HANDLER_ADDRESS = "handler_address";
|
||||
public static final String HANDLER_NAME = "handler_name";
|
||||
public static final String HANDLER_PARAMS = "handler_params";
|
||||
|
||||
// handler class map
|
||||
private static ConcurrentHashMap<String, IJobHandler> handlerClassMap = new ConcurrentHashMap<String, IJobHandler>();
|
||||
// handler thread map
|
||||
private static ConcurrentHashMap<String, HandlerThread> handlerTreadMap = new ConcurrentHashMap<String, HandlerThread>();
|
||||
// handler date queue map
|
||||
private static ConcurrentHashMap<String, LinkedBlockingQueue<Map<String, String>>> handlerDataQueueMap = new ConcurrentHashMap<String, LinkedBlockingQueue<Map<String, String>>>();
|
||||
public static final String TRIGGER_LOG_ID = "trigger_log_id";
|
||||
public static final String TRIGGER_LOG_URL = "trigger_log_url";
|
||||
|
||||
public static ConcurrentHashMap<String, HandlerThread> handlerTreadMap = new ConcurrentHashMap<String, HandlerThread>();
|
||||
|
||||
// regist handler
|
||||
public static void regist(String handleName, IJobHandler handler){
|
||||
handlerClassMap.put(handleName, handler);
|
||||
LinkedBlockingQueue<Map<String, String>> handlerDateQueue = new LinkedBlockingQueue<Map<String, String>>();
|
||||
handlerDataQueueMap.put(handleName, handlerDateQueue);
|
||||
HandlerThread handlerThread = new HandlerThread(handleName);
|
||||
HandlerThread handlerThread = new HandlerThread(handler);
|
||||
handlerThread.start();
|
||||
handlerTreadMap.put(handleName, handlerThread);
|
||||
logger.info(">>>>>>>>>>> xxl-job regist handler success, handleName:{}, handler:{}, handlerDateQueue:{}, handlerThread:{}",
|
||||
new Object[]{handleName, handler, handlerDateQueue, handlerThread});
|
||||
}
|
||||
|
||||
// create handler thread
|
||||
static class HandlerThread extends Thread{
|
||||
private String _handleName;
|
||||
public HandlerThread(String _handleName) {
|
||||
this._handleName = _handleName;
|
||||
}
|
||||
public boolean isValid = true;
|
||||
public void stopThread(){
|
||||
isValid = false;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
while (isValid) {
|
||||
LinkedBlockingQueue<Map<String, String>> handlerDateQueue = handlerDataQueueMap.get(_handleName);
|
||||
Map<String, String> handlerData = handlerDateQueue.poll();
|
||||
if (handlerData!=null) {
|
||||
// handle job
|
||||
JobHandleStatus _status = JobHandleStatus.FAIL;
|
||||
String _msg = null;
|
||||
try {
|
||||
IJobHandler handler = handlerClassMap.get(_handleName);
|
||||
_status = handler.handle(handlerData);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
_status = JobHandleStatus.FAIL;
|
||||
StringWriter out = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(out));
|
||||
_msg = out.toString();
|
||||
}
|
||||
|
||||
// callback handler info
|
||||
String callback_response[] = null;
|
||||
try {
|
||||
String _triggerLogUrl = handlerData.get(HandlerRepository.triggerLogUrl);
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
params.put(HandlerRepository.triggerLogId, handlerData.get(HandlerRepository.triggerLogId));
|
||||
params.put(HttpUtil.status, _status.name());
|
||||
params.put(HttpUtil.msg, _msg);
|
||||
callback_response = HttpUtil.post(_triggerLogUrl, params);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger.info("<<<<<<<<<<< xxl-job thread handle, handlerData:{}, callback_status:{}, callback_msg:{}, callback_response:{}, thread:{}",
|
||||
new Object[]{handlerData, _status, _msg, callback_response, this});
|
||||
} else {
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(200);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handlerTreadMap.put(handleName, handlerThread); // putIfAbsent
|
||||
logger.info(">>>>>>>>>>> xxl-job regist handler success, handleName:{}, handler:{}", new Object[]{handleName, handler});
|
||||
}
|
||||
|
||||
// handler push to queue
|
||||
public static String pushHandleQueue(Map<String, String> _param) {
|
||||
logger.info(">>>>>>>>>>> xxl-job pushHandleQueue start, _param:{}", new Object[]{_param});
|
||||
|
||||
// resuolt
|
||||
// result
|
||||
String _status = HttpUtil.FAIL;
|
||||
String _msg = "";
|
||||
|
||||
// push data to queue
|
||||
String _handleName = _param.get(HandlerRepository.handleName);
|
||||
int _triggerLogId = Integer.valueOf(_param.get(HandlerRepository.triggerLogId)); // 次数应校验,停止队列功能为开发
|
||||
try {
|
||||
if (_handleName!=null && _handleName.trim().length()>0) {
|
||||
IJobHandler handler = handlerClassMap.get(_handleName);
|
||||
if (handler != null) {
|
||||
// push data to handler queue
|
||||
LinkedBlockingQueue<Map<String, String>> handlerDateQueue = handlerDataQueueMap.get(_handleName);
|
||||
if (handlerDateQueue == null) {
|
||||
handlerDateQueue = new LinkedBlockingQueue<Map<String, String>>();
|
||||
handlerDataQueueMap.put(_handleName, handlerDateQueue);
|
||||
logger.info(">>>>>>>>>>> xxl-job handler lazy fresh handlerDateQueue, _handleName:{}, handler:{}, handlerDateQueue:{}",
|
||||
new Object[]{_handleName, handler, handlerDateQueue});
|
||||
}
|
||||
// check handler thread
|
||||
HandlerThread handlerThreadOld = handlerTreadMap.get(_handleName);
|
||||
if (!handlerThreadOld.isAlive()) {
|
||||
handlerThreadOld.stopThread();
|
||||
HandlerThread handlerThread = new HandlerThread(_handleName);
|
||||
handlerThread.start();
|
||||
handlerTreadMap.put(_handleName, handlerThread);
|
||||
logger.info(">>>>>>>>>>> xxl-job handler lazy fresh thread, _handleName:{}, handler:{}, handlerThread:{}",
|
||||
new Object[]{_handleName, handler, handlerThread});
|
||||
}
|
||||
// push to queue
|
||||
handlerDateQueue.offer(_param);
|
||||
_status = HttpUtil.SUCCESS;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
StringWriter out = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(out));
|
||||
_status = HttpUtil.FAIL;
|
||||
_msg = out.toString();
|
||||
HandlerThread handlerThread = handlerTreadMap.get(_param.get(HandlerRepository.HANDLER_NAME));
|
||||
if (handlerThread != null) {
|
||||
handlerThread.pushData(_param);
|
||||
_status = HttpUtil.SUCCESS;
|
||||
} else {
|
||||
_msg = "handler not found.";
|
||||
}
|
||||
logger.info(">>>>>>>>>>> xxl-job pushHandleQueue, _handleName:{}, _triggerLogId:{}, _param:{}, _status:{}, _msg:{}",
|
||||
new Object[]{_handleName, _triggerLogId, _param, _status, _msg});
|
||||
|
||||
HashMap<String, String> triggerData = new HashMap<String, String>();
|
||||
triggerData.put(HandlerRepository.TRIGGER_LOG_ID, _param.get(HandlerRepository.TRIGGER_LOG_ID));
|
||||
triggerData.put(HttpUtil.status, _status);
|
||||
triggerData.put(HttpUtil.msg, _msg);
|
||||
return JacksonUtil.writeValueAsString(triggerData);
|
||||
|
||||
/**
|
||||
* trigger-log :
|
||||
* trigger side : store trigger-info >> trigger request >> update trigger-response-status
|
||||
* job side : handler trigger >> update trigger-result
|
||||
*/
|
||||
logger.info(">>>>>>>>>>> xxl-job pushHandleQueue end, triggerData:{}", new Object[]{triggerData});
|
||||
return JacksonUtil.writeValueAsString(triggerData);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.xxl.job.client.handler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* remote job handler
|
||||
* @author xuxueli 2015-12-19 19:06:38
|
||||
|
@ -15,7 +13,7 @@ public abstract class IJobHandler extends HandlerRepository{
|
|||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public abstract JobHandleStatus handle(Map<String, String> param) throws Exception;
|
||||
public abstract JobHandleStatus handle(String... params) throws Exception;
|
||||
|
||||
public enum JobHandleStatus{
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue