diff --git a/xxl-job-admin/src/main/java/com/xxl/job/controller/JobInfoController.java b/xxl-job-admin/src/main/java/com/xxl/job/controller/JobInfoController.java index 128916a9..66cf56c0 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/controller/JobInfoController.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/controller/JobInfoController.java @@ -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 remoteJobBean = HttpJobBean.class; + // loacal job bean + public static List> localJobBeanList = new ArrayList>(); + 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 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 list = xxlJobInfoDao.pageList(start, length, jobName, null, null); - int list_count = xxlJobInfoDao.pageListCount(start, length, jobName, null, null); + List 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 add(HttpServletRequest request) { - String triggerKeyName = null; - String cronExpression = null; - Map jobData = new HashMap(); + public ReturnT 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(500, "请选择“任务组”"); } - @SuppressWarnings("unchecked") - Set> paramSet = request.getParameterMap().entrySet(); - for (Entry 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(500, "请输入“任务名”"); } - - // triggerKeyName - if (StringUtils.isBlank(triggerKeyName)) { - return new ReturnT(500, "请输入“任务key”"); + if (!CronExpression.isValidExpression(jobCron)) { + return new ReturnT(500, "“corn”不合法"); } - - // cronExpression - if (StringUtils.isBlank(cronExpression)) { - return new ReturnT(500, "请输入“任务corn”"); - } - if (!CronExpression.isValidExpression(cronExpression)) { - return new ReturnT(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(500, "请输入“任务描述”"); } - if (jobData.get(HandlerRepository.job_url)==null || jobData.get(HandlerRepository.job_url).toString().trim().length()==0) { - return new ReturnT(500, "请输入“任务URL”"); + Class jobClass_ = null; + try { + Class clazz = Class.forName(jobClass); + if (clazz!=null) { + jobClass_ = (Class) clazz; + } + } catch (ClassNotFoundException e1) { + e1.printStackTrace(); } - if (jobData.get(HandlerRepository.handleName)==null || jobData.get(HandlerRepository.handleName).toString().trim().length()==0) { - return new ReturnT(500, "请输入“任务handler”"); + if (jobClass_ == null) { + return new ReturnT(500, "请选择“JobBean”"); + } + if (jobClass_.getClass().getName().equals(remoteJobBean.getName())) { + if (StringUtils.isBlank(handler_address)) { + return new ReturnT(500, "请输入“远程-机器地址”"); + } + if (StringUtils.isBlank(handler_name)) { + return new ReturnT(500, "请输入“远程-执行器”"); + } + } + if (StringUtils.isBlank(author)) { + return new ReturnT(500, "请输入“负责人”"); + } + if (StringUtils.isBlank(alarm_email)) { + return new ReturnT(500, "请输入“报警邮件”"); } - // jobClass - Class jobClass = HttpJobBean.class; + try { + if (DynamicSchedulerUtil.checkExists(jobName, jobGroup)) { + return new ReturnT(500, "此任务已存在,请更换任务组或任务名"); + } + } catch (SchedulerException e1) { + e1.printStackTrace(); + return new ReturnT(500, "此任务已存在,请更换任务组或任务名"); + } + + HashMap jobDataMap = new HashMap(); + 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(500, "任务ID重复,请更换确认"); + boolean result = DynamicSchedulerUtil.addJob(jobInfo); + if (result) { + return ReturnT.SUCCESS; + } else { + xxlJobInfoDao.delete(jobGroup, jobName); + return new ReturnT(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 reschedule(String triggerKeyName, String cronExpression) { - // triggerKeyName - if (StringUtils.isBlank(triggerKeyName)) { - return new ReturnT(500, "请输入“任务key”"); + public ReturnT 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) { + + // valid + if (JobGroupEnum.match(jobGroup) == null) { + return new ReturnT(500, "请选择“任务组”"); } - // cronExpression - if (StringUtils.isBlank(cronExpression)) { - return new ReturnT(500, "请输入“任务corn”"); + if (StringUtils.isBlank(jobName)) { + return new ReturnT(500, "请输入“任务名”"); } - if (!CronExpression.isValidExpression(cronExpression)) { - return new ReturnT(500, "“任务corn”不合法"); + if (!CronExpression.isValidExpression(jobCron)) { + return new ReturnT(500, "“corn”不合法"); } + + XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName); + jobInfo.setJobCron(jobCron); + try { - DynamicSchedulerUtil.rescheduleJob(triggerKeyName, cronExpression); + // fresh quartz + DynamicSchedulerUtil.rescheduleJob(jobInfo); - // update - XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName); - if (jobInfo!=null) { - jobInfo.setJobCron(cronExpression); - xxlJobInfoDao.update(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 remove(String triggerKeyName) { + public ReturnT 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 pause(String triggerKeyName) { + public ReturnT 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 resume(String triggerKeyName) { + public ReturnT 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 triggerJob(String triggerKeyName) { + public ReturnT triggerJob(String jobGroup, String jobName) { try { - DynamicSchedulerUtil.triggerJob(triggerKeyName); + DynamicSchedulerUtil.triggerJob(jobName, jobGroup); return ReturnT.SUCCESS; } catch (SchedulerException e) { e.printStackTrace(); diff --git a/xxl-job-admin/src/main/java/com/xxl/job/controller/JobLogController.java b/xxl-job-admin/src/main/java/com/xxl/job/controller/JobLogController.java index a0c79f2e..6958f8c8 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/controller/JobLogController.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/controller/JobLogController.java @@ -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 triggerLog(int triggerLogId, String status, String msg) { - XxlJobLog log = xxlJobLogDao.load(triggerLogId); + public ReturnT 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); diff --git a/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobInfo.java b/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobInfo.java index 749b1047..aafcaba6 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobInfo.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobInfo.java @@ -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 + "]"; } - + } diff --git a/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobLog.java b/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobLog.java index c4b8a2ed..4ebd9f7f 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobLog.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobLog.java @@ -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 + "]"; } } diff --git a/xxl-job-admin/src/main/java/com/xxl/job/core/util/DynamicSchedulerUtil.java b/xxl-job-admin/src/main/java/com/xxl/job/core/util/DynamicSchedulerUtil.java index 79526ff7..b582f0f6 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/core/util/DynamicSchedulerUtil.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/core/util/DynamicSchedulerUtil.java @@ -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; @@ -124,29 +126,42 @@ public final class DynamicSchedulerUtil implements InitializingBean { e.printStackTrace(); } } + + // 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 jobClass, Map 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 jobClass_ = null; + try { + jobClass_ = (Class)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 { - // TriggerKey : name + group - String group = Scheduler.DEFAULT_GROUP; - TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group); - - 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(); - - 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); + // 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; } - return result; + + // TriggerKey : name + group + TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup()); + JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup()); + + // CronTrigger : TriggerKey + cronExpression + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron()).withMisfireHandlingInstructionDoNothing(); + CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build(); + + //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 triggerSet = new HashSet(); + 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); diff --git a/xxl-job-admin/src/main/java/com/xxl/job/dao/IXxlJobInfoDao.java b/xxl-job-admin/src/main/java/com/xxl/job/dao/IXxlJobInfoDao.java index 2d718dea..dc6e7430 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/dao/IXxlJobInfoDao.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/dao/IXxlJobInfoDao.java @@ -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 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 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); } diff --git a/xxl-job-admin/src/main/java/com/xxl/job/dao/impl/XxlJobInfoDaoImpl.java b/xxl-job-admin/src/main/java/com/xxl/job/dao/impl/XxlJobInfoDaoImpl.java index 77c287b5..3879cd57 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/dao/impl/XxlJobInfoDaoImpl.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/dao/impl/XxlJobInfoDaoImpl.java @@ -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 pageList(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd) { + public List pageList(int offset, int pagesize, String jobGroup, String jobName) { HashMap params = new HashMap(); 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 params = new HashMap(); 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 params = new HashMap(); + 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 params = new HashMap(); + params.put("jobGroup", jobGroup); + params.put("jobName", jobName); + + return sqlSessionTemplate.update("XxlJobInfoMapper.delete", params); } } diff --git a/xxl-job-admin/src/main/java/com/xxl/job/service/job/HttpJobBean.java b/xxl-job-admin/src/main/java/com/xxl/job/service/job/HttpJobBean.java index 51210d39..ab35dd13 100644 --- a/xxl-job-admin/src/main/java/com/xxl/job/service/job/HttpJobBean.java +++ b/xxl-job-admin/src/main/java/com/xxl/job/service/job/HttpJobBean.java @@ -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,44 +23,43 @@ 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); - + @SuppressWarnings("unchecked") @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { - String triggerKey = context.getTrigger().getJobKey().getName(); - - // jobDataMap 2 params - Map params = new HashMap(); - 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 jobDataMap = (HashMap) 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 params = new HashMap(); + 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 diff --git a/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml b/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml index 669afef9..bd158ad7 100644 --- a/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml +++ b/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml @@ -6,37 +6,45 @@ + + + + + + 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 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} ); SELECT LAST_INSERT_ID() - SELECT FROM xxl_job_qrtz_trigger_info AS t - WHERE t.job_name = #{jobName} + WHERE t.job_group = #{jobGroup} + AND t.job_name = #{jobName} - + 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} - 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} \ No newline at end of file diff --git a/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml b/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml index 0fa5af79..5b0c6afa 100644 --- a/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml +++ b/xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml @@ -9,6 +9,7 @@ + @@ -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} ); diff --git a/xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl b/xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl index 0f0b3853..d1cde5f3 100644 --- a/xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl +++ b/xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl @@ -42,9 +42,7 @@
- - jobName - + 任务名
@@ -66,63 +64,23 @@ - - - - - - - - + + + + + + + + + + + + + - - <#-- - <#if jobList?exists && jobList?size gt 0> - <#list jobList as item> - - - - - - - - - - - - --> - +
id任务Key任务Cron任务Class状态Status参数addTimeupdateTimeid任务组任务名Cron描述JobBean任务数据新增时间更新时间负责人报警邮件报警阀值状态 操作
${item['TriggerKey'].name}${item['Trigger'].cronExpression}${item['JobDetail'].jobClass} - <#assign jobDataMap = item['JobDetail'].jobDataMap /> - <#if jobDataMap?exists && jobDataMap?keys?size gt 0> - <#list jobDataMap?keys as key> - ${key} = ${jobDataMap[key]}
- - -
- <#if item['TriggerState'] == 'NORMAL'> - - <#elseif item['TriggerState'] == 'PAUSED'> - - <#else> - - - -

- <#if item['TriggerState'] == 'NORMAL'> - - <#elseif item['TriggerState'] == 'PAUSED'> - - - - - - -

-
@@ -155,29 +113,51 @@ -
+
- -
+ +
+ +
- -
+ +
+ +
+ +
+
+
+ +
+ +
- -
+ +
+ +
- -
+ +
-
diff --git a/xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl b/xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl index b5ba01df..ce55effa 100644 --- a/xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl +++ b/xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl @@ -35,7 +35,7 @@ 任务组 @@ -74,6 +74,7 @@ 任务组 任务名 Cron + 描述 JobBean 任务数据 调度时间 diff --git a/xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js b/xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js index 58f13ae6..58d228f2 100644 --- a/xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js +++ b/xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js @@ -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?'查看'+ data +'':"无"; + } + }, { "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 ''+ data +''; + } else if ('PAUSED' == data){ + return ''+ data +''; + } + return data; + } + }, + { "data": '操作' , "render": function ( data, type, row ) { return function(){ // status @@ -43,23 +79,31 @@ $(function() { pause_resume = ' '; } // 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 = '

'+ pause_resume + ' '+ - ' '+ - ' '+ + '
'+ ''+ + 'onclick="javascript:window.open(\'' + logUrl + '\')" >查看日志 '+ + ' '+ '

'; @@ -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 = '
'+ - ''+ - '
'+ - '
'+ - '
'; - $(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 = '
'+ + ''+ + '
'+ + '
'+ + '
'; + $(this).parents('.form-group').parent().append(html); + + $("#addModal .removeParam").on('click', function () { + $(this).parents('.form-group').remove(); + }); + }); + */ }); diff --git a/xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js b/xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js index 82c4a004..91fdf328 100644 --- a/xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js +++ b/xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js @@ -33,6 +33,7 @@ $(function() { }, { "data": 'jobName'}, { "data": 'jobCron', "visible" : false}, + { "data": 'jobDesc', "visible" : false}, { "data": 'jobClass', "visible" : false}, { "data": 'jobData', diff --git a/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobInfoTest.java b/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobInfoTest.java index 61aaed63..4dd20d61 100644 --- a/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobInfoTest.java +++ b/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobInfoTest.java @@ -21,8 +21,8 @@ public class XxlJobInfoTest { @Test public void pageList(){ - List list = xxlJobInfoDao.pageList(0, 20, null, null, null); - int list_count = xxlJobInfoDao.pageListCount(0, 20, null, null, null); + List 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"); diff --git a/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobLogTest.java b/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobLogTest.java index 28b63972..22cf7917 100644 --- a/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobLogTest.java +++ b/xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobLogTest.java @@ -57,8 +57,8 @@ public class XxlJobLogTest { @Test public void pageList(){ - List list = xxlJobLogDao.pageList(0, 20, null, null, null); - int list_count = xxlJobLogDao.pageListCount(0, 20, null, null, null); + List 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); diff --git a/xxl-job-client-demo/src/main/java/com/xxl/job/service/handler/DemoJobHandler.java b/xxl-job-client-demo/src/main/java/com/xxl/job/service/handler/DemoJobHandler.java index 4d5c66eb..135280c5 100644 --- a/xxl-job-client-demo/src/main/java/com/xxl/job/service/handler/DemoJobHandler.java +++ b/xxl-job-client-demo/src/main/java/com/xxl/job/service/handler/DemoJobHandler.java @@ -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 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; } diff --git a/xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerRepository.java b/xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerRepository.java index db63543b..a3205ef8 100644 --- a/xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerRepository.java +++ b/xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerRepository.java @@ -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"; - - // handler class map - private static ConcurrentHashMap handlerClassMap = new ConcurrentHashMap(); - // handler thread map - private static ConcurrentHashMap handlerTreadMap = new ConcurrentHashMap(); - // handler date queue map - private static ConcurrentHashMap>> handlerDataQueueMap = new ConcurrentHashMap>>(); + public static final String HANDLER_ADDRESS = "handler_address"; + public static final String HANDLER_NAME = "handler_name"; + public static final String HANDLER_PARAMS = "handler_params"; + + public static final String TRIGGER_LOG_ID = "trigger_log_id"; + public static final String TRIGGER_LOG_URL = "trigger_log_url"; + + public static ConcurrentHashMap handlerTreadMap = new ConcurrentHashMap(); // regist handler public static void regist(String handleName, IJobHandler handler){ - handlerClassMap.put(handleName, handler); - LinkedBlockingQueue> handlerDateQueue = new LinkedBlockingQueue>(); - 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> handlerDateQueue = handlerDataQueueMap.get(_handleName); - Map 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 params = new HashMap(); - 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 _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> handlerDateQueue = handlerDataQueueMap.get(_handleName); - if (handlerDateQueue == null) { - handlerDateQueue = new LinkedBlockingQueue>(); - 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 triggerData = new HashMap(); + 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); } } diff --git a/xxl-job-client/src/main/java/com/xxl/job/client/handler/IJobHandler.java b/xxl-job-client/src/main/java/com/xxl/job/client/handler/IJobHandler.java index b7339882..6371bf04 100644 --- a/xxl-job-client/src/main/java/com/xxl/job/client/handler/IJobHandler.java +++ b/xxl-job-client/src/main/java/com/xxl/job/client/handler/IJobHandler.java @@ -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 param) throws Exception; + public abstract JobHandleStatus handle(String... params) throws Exception; public enum JobHandleStatus{ /**