任务地址支持配置多个,进行failover
This commit is contained in:
parent
e58f77ddee
commit
71e12272c3
|
@ -150,17 +150,19 @@ CREATE TABLE `xxl_job_qrtz_trigger_info` (
|
|||
`job_cron` varchar(128) NOT NULL COMMENT '任务执行CORN',
|
||||
`job_desc` varchar(255) NOT NULL,
|
||||
`job_class` varchar(255) NOT NULL COMMENT '任务执行JobBean',
|
||||
`job_data` varchar(512) DEFAULT NULL COMMENT '任务执行数据',
|
||||
`add_time` datetime DEFAULT NULL,
|
||||
`update_time` datetime DEFAULT NULL,
|
||||
`author` varchar(64) DEFAULT NULL COMMENT '作者',
|
||||
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
|
||||
`alarm_threshold` int(11) DEFAULT NULL COMMENT '报警阀值(连续失败次数)',
|
||||
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,有多个则逗号分隔',
|
||||
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
|
||||
`executor_param` varchar(255) DEFAULT NULL COMMENT '执行器任务参数',
|
||||
`glue_switch` int(11) DEFAULT '0' COMMENT 'GLUE模式开关:0-否,1-是',
|
||||
`glue_source` text COMMENT 'GLUE源代码',
|
||||
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `xxl_job_qrtz_trigger_log` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
|
@ -169,7 +171,9 @@ CREATE TABLE `xxl_job_qrtz_trigger_log` (
|
|||
`job_cron` varchar(128) NOT NULL COMMENT '任务执行CORN表达式',
|
||||
`job_desc` varchar(255) NOT NULL,
|
||||
`job_class` varchar(255) NOT NULL COMMENT '任务执行JobBean',
|
||||
`job_data` varchar(512) DEFAULT NULL COMMENT '任务执行数据',
|
||||
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
|
||||
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
|
||||
`executor_param` varchar(255) DEFAULT NULL COMMENT 'executor_param',
|
||||
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
|
||||
`trigger_status` varchar(255) DEFAULT NULL COMMENT '调度-结果',
|
||||
`trigger_msg` varchar(2048) DEFAULT NULL COMMENT '调度-日志',
|
||||
|
@ -177,7 +181,7 @@ CREATE TABLE `xxl_job_qrtz_trigger_log` (
|
|||
`handle_status` varchar(255) DEFAULT NULL COMMENT '执行-状态',
|
||||
`handle_msg` varchar(2048) DEFAULT NULL COMMENT '执行-日志',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `xxl_job_qrtz_trigger_logglue` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
|
@ -188,7 +192,8 @@ CREATE TABLE `xxl_job_qrtz_trigger_logglue` (
|
|||
`add_time` timestamp NULL DEFAULT NULL,
|
||||
`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
|
||||
commit;
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
package com.xxl.job.admin.controller;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.quartz.CronExpression;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -16,15 +11,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.xxl.job.admin.core.constant.Constants.JobGroupEnum;
|
||||
import com.xxl.job.admin.core.jobbean.RemoteHttpJobBean;
|
||||
import com.xxl.job.admin.core.model.ReturnT;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.util.DynamicSchedulerUtil;
|
||||
import com.xxl.job.admin.dao.IXxlJobInfoDao;
|
||||
import com.xxl.job.admin.dao.IXxlJobLogDao;
|
||||
import com.xxl.job.admin.dao.IXxlJobLogGlueDao;
|
||||
import com.xxl.job.core.handler.HandlerRepository;
|
||||
import com.xxl.job.core.util.JacksonUtil;
|
||||
import com.xxl.job.admin.service.IXxlJobService;
|
||||
|
||||
/**
|
||||
* index controller
|
||||
|
@ -35,11 +23,7 @@ import com.xxl.job.core.util.JacksonUtil;
|
|||
public class JobInfoController {
|
||||
|
||||
@Resource
|
||||
private IXxlJobInfoDao xxlJobInfoDao;
|
||||
@Resource
|
||||
public IXxlJobLogDao xxlJobLogDao;
|
||||
@Resource
|
||||
private IXxlJobLogGlueDao xxlJobLogGlueDao;
|
||||
private IXxlJobService xxlJobService;
|
||||
|
||||
@RequestMapping
|
||||
public String index(Model model) {
|
||||
|
@ -53,219 +37,52 @@ public class JobInfoController {
|
|||
@RequestParam(required = false, defaultValue = "10") int length,
|
||||
String jobGroup, String jobName, String filterTime) {
|
||||
|
||||
// page list
|
||||
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) {
|
||||
for (XxlJobInfo jobInfo : list) {
|
||||
DynamicSchedulerUtil.fillJobInfo(jobInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// package result
|
||||
Map<String, Object> maps = new HashMap<String, Object>();
|
||||
maps.put("recordsTotal", list_count); // 总记录数
|
||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
||||
maps.put("data", list); // 分页列表
|
||||
return maps;
|
||||
return xxlJobService.pageList(start, length, jobGroup, jobName, filterTime);
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@ResponseBody
|
||||
public ReturnT<String> add(String jobGroup, String jobName, String jobCron, String jobDesc,
|
||||
String handler_address, String handler_name, String handler_params,
|
||||
String executorAddress, String executorHandler, String executorParam,
|
||||
String author, String alarmEmail, int alarmThreshold,
|
||||
int glueSwitch, String glueSource, String glueRemark) {
|
||||
|
||||
// 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”不合法");
|
||||
}
|
||||
if (StringUtils.isBlank(jobDesc)) {
|
||||
return new ReturnT<String>(500, "请输入“任务描述”");
|
||||
}
|
||||
if (StringUtils.isBlank(handler_address)) {
|
||||
return new ReturnT<String>(500, "请输入“执行器地址”");
|
||||
}
|
||||
if (glueSwitch==0 && StringUtils.isBlank(handler_name)) {
|
||||
return new ReturnT<String>(500, "请输入“jobHandler”");
|
||||
}
|
||||
if (StringUtils.isBlank(author)) {
|
||||
return new ReturnT<String>(500, "请输入“负责人”");
|
||||
}
|
||||
if (StringUtils.isBlank(alarmEmail)) {
|
||||
return new ReturnT<String>(500, "请输入“报警邮件”");
|
||||
}
|
||||
if (alarmThreshold < 0) {
|
||||
alarmThreshold = 0;
|
||||
}
|
||||
|
||||
try {
|
||||
if (DynamicSchedulerUtil.checkExists(jobName, jobGroup)) {
|
||||
return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
|
||||
}
|
||||
} catch (SchedulerException e1) {
|
||||
e1.printStackTrace();
|
||||
return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
|
||||
}
|
||||
|
||||
// parse jobDataMap
|
||||
HashMap<String, String> jobDataMap = new HashMap<String, String>();
|
||||
jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address);
|
||||
jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name);
|
||||
jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
|
||||
|
||||
// Backup to the database
|
||||
XxlJobInfo jobInfo = new XxlJobInfo();
|
||||
jobInfo.setJobGroup(jobGroup);
|
||||
jobInfo.setJobName(jobName);
|
||||
jobInfo.setJobCron(jobCron);
|
||||
jobInfo.setJobDesc(jobDesc);
|
||||
jobInfo.setJobClass(RemoteHttpJobBean.class.getName());
|
||||
jobInfo.setJobData(JacksonUtil.writeValueAsString(jobDataMap));
|
||||
jobInfo.setAuthor(author);
|
||||
jobInfo.setAlarmEmail(alarmEmail);
|
||||
jobInfo.setAlarmThreshold(alarmThreshold);
|
||||
jobInfo.setGlueSwitch(glueSwitch);
|
||||
jobInfo.setGlueSource(glueSource);
|
||||
jobInfo.setGlueRemark(glueRemark);
|
||||
xxlJobInfoDao.save(jobInfo);
|
||||
|
||||
try {
|
||||
// add job 2 quartz
|
||||
boolean result = DynamicSchedulerUtil.addJob(jobInfo);
|
||||
if (result) {
|
||||
return ReturnT.SUCCESS;
|
||||
} else {
|
||||
xxlJobInfoDao.delete(jobGroup, jobName);
|
||||
return new ReturnT<String>(500, "新增任务失败");
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReturnT.FAIL;
|
||||
return xxlJobService.add(jobGroup, jobName, jobCron, jobDesc, executorAddress, executorHandler, executorParam,
|
||||
author, alarmEmail, alarmThreshold, glueSwitch, glueSource, glueRemark);
|
||||
}
|
||||
|
||||
@RequestMapping("/reschedule")
|
||||
@ResponseBody
|
||||
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc,
|
||||
String handler_address, String handler_name, String handler_params,
|
||||
String executorAddress, String executorHandler, String executorParam,
|
||||
String author, String alarmEmail, int alarmThreshold, int glueSwitch) {
|
||||
|
||||
// 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”不合法");
|
||||
}
|
||||
if (StringUtils.isBlank(jobDesc)) {
|
||||
return new ReturnT<String>(500, "请输入“任务描述”");
|
||||
}
|
||||
if (StringUtils.isBlank(handler_address)) {
|
||||
return new ReturnT<String>(500, "请输入“执行器地址”");
|
||||
}
|
||||
if (glueSwitch==0 && StringUtils.isBlank(handler_name)) {
|
||||
return new ReturnT<String>(500, "请输入“jobHandler”");
|
||||
}
|
||||
if (StringUtils.isBlank(author)) {
|
||||
return new ReturnT<String>(500, "请输入“负责人”");
|
||||
}
|
||||
if (StringUtils.isBlank(alarmEmail)) {
|
||||
return new ReturnT<String>(500, "请输入“报警邮件”");
|
||||
}
|
||||
if (alarmThreshold < 0) {
|
||||
alarmThreshold = 0;
|
||||
}
|
||||
|
||||
// parse jobDataMap
|
||||
HashMap<String, String> jobDataMap = new HashMap<String, String>();
|
||||
jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address);
|
||||
jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name);
|
||||
jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
|
||||
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName);
|
||||
jobInfo.setJobCron(jobCron);
|
||||
jobInfo.setJobDesc(jobDesc);
|
||||
jobInfo.setJobData(JacksonUtil.writeValueAsString(jobDataMap));
|
||||
jobInfo.setAuthor(author);
|
||||
jobInfo.setAlarmEmail(alarmEmail);
|
||||
jobInfo.setAlarmThreshold(alarmThreshold);
|
||||
jobInfo.setGlueSwitch(glueSwitch);
|
||||
|
||||
try {
|
||||
// fresh quartz
|
||||
DynamicSchedulerUtil.rescheduleJob(jobInfo);
|
||||
|
||||
// fresh db
|
||||
xxlJobInfoDao.update(jobInfo);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReturnT.FAIL;
|
||||
return xxlJobService.reschedule(jobGroup, jobName, jobCron, jobDesc, executorAddress, executorHandler, executorParam, author,
|
||||
alarmEmail, alarmThreshold, glueSwitch);
|
||||
}
|
||||
|
||||
@RequestMapping("/remove")
|
||||
@ResponseBody
|
||||
public ReturnT<String> remove(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.removeJob(jobName, jobGroup);
|
||||
xxlJobInfoDao.delete(jobGroup, jobName);
|
||||
xxlJobLogDao.delete(jobGroup, jobName);
|
||||
xxlJobLogGlueDao.delete(jobGroup, jobName);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReturnT.FAIL;
|
||||
return xxlJobService.remove(jobGroup, jobName);
|
||||
}
|
||||
|
||||
@RequestMapping("/pause")
|
||||
@ResponseBody
|
||||
public ReturnT<String> pause(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.pauseJob(jobName, jobGroup); // jobStatus do not store
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
return xxlJobService.pause(jobGroup, jobName);
|
||||
}
|
||||
|
||||
@RequestMapping("/resume")
|
||||
@ResponseBody
|
||||
public ReturnT<String> resume(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.resumeJob(jobName, jobGroup);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
return xxlJobService.resume(jobGroup, jobName);
|
||||
}
|
||||
|
||||
@RequestMapping("/trigger")
|
||||
@ResponseBody
|
||||
public ReturnT<String> triggerJob(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.triggerJob(jobName, jobGroup);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
return xxlJobService.triggerJob(jobGroup, jobName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@ import com.xxl.job.admin.core.constant.Constants.JobGroupEnum;
|
|||
import com.xxl.job.admin.core.model.ReturnT;
|
||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.dao.IXxlJobLogDao;
|
||||
import com.xxl.job.core.handler.HandlerRepository;
|
||||
import com.xxl.job.core.handler.HandlerRepository.ActionEnum;
|
||||
import com.xxl.job.core.handler.HandlerRepository.HandlerParamEnum;
|
||||
import com.xxl.job.core.util.HttpUtil;
|
||||
import com.xxl.job.core.util.HttpUtil.RemoteCallBack;
|
||||
import com.xxl.job.core.util.JacksonUtil;
|
||||
|
||||
/**
|
||||
* index controller
|
||||
|
@ -41,7 +41,7 @@ public class JobLogController {
|
|||
model.addAttribute("jobGroup", jobGroup);
|
||||
model.addAttribute("jobName", jobName);
|
||||
model.addAttribute("JobGroupList", JobGroupEnum.values());
|
||||
return "joblog/index";
|
||||
return "joblog/joblog.index";
|
||||
}
|
||||
|
||||
@RequestMapping("/pageList")
|
||||
|
@ -101,21 +101,18 @@ public class JobLogController {
|
|||
if (log == null) {
|
||||
return new ReturnT<String>(500, "参数异常");
|
||||
}
|
||||
|
||||
// server address
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> jobDataMap = JacksonUtil.readValue(log.getJobData(), Map.class);
|
||||
String handler_address = jobDataMap.get(HandlerRepository.HANDLER_ADDRESS);
|
||||
if (!handler_address.startsWith("http")){
|
||||
handler_address = "http://" + handler_address + "/";
|
||||
if (!RemoteCallBack.SUCCESS.equals(log.getTriggerStatus())) {
|
||||
return new ReturnT<String>(500, "调度失败,无法查看执行日志");
|
||||
}
|
||||
|
||||
// trigger id, trigger time
|
||||
Map<String, String> reqMap = new HashMap<String, String>();
|
||||
reqMap.put(HandlerRepository.NAMESPACE, HandlerRepository.NameSpaceEnum.LOG.name());
|
||||
reqMap.put(HandlerRepository.TRIGGER_LOG_ID, String.valueOf(id));
|
||||
reqMap.put(HandlerRepository.TRIGGER_TIMESTAMP, String.valueOf(log.getTriggerTime().getTime()));
|
||||
reqMap.put(HandlerParamEnum.TIMESTAMP.name(), String.valueOf(System.currentTimeMillis()));
|
||||
reqMap.put(HandlerParamEnum.ACTION.name(), ActionEnum.LOG.name());
|
||||
reqMap.put(HandlerParamEnum.LOG_ID.name(), String.valueOf(id));
|
||||
reqMap.put(HandlerParamEnum.LOG_DATE.name(), String.valueOf(log.getTriggerTime().getTime()));
|
||||
|
||||
RemoteCallBack callBack = HttpUtil.post(handler_address, reqMap);
|
||||
RemoteCallBack callBack = HttpUtil.post(HttpUtil.addressToUrl(log.getExecutorAddress()), reqMap);
|
||||
if (HttpUtil.RemoteCallBack.SUCCESS.equals(callBack.getStatus())) {
|
||||
return new ReturnT<String>(callBack.getMsg());
|
||||
} else {
|
||||
|
@ -138,23 +135,19 @@ public class JobLogController {
|
|||
if (log == null) {
|
||||
return new ReturnT<String>(500, "参数异常");
|
||||
}
|
||||
|
||||
// server address
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> jobDataMap = JacksonUtil.readValue(log.getJobData(), Map.class);
|
||||
String handler_address = jobDataMap.get(HandlerRepository.HANDLER_ADDRESS);
|
||||
if (!handler_address.startsWith("http")){
|
||||
handler_address = "http://" + handler_address + "/";
|
||||
if (!RemoteCallBack.SUCCESS.equals(log.getTriggerStatus())) {
|
||||
return new ReturnT<String>(500, "调度失败,无法终止日志");
|
||||
}
|
||||
String handler_name = jobDataMap.get(HandlerRepository.HANDLER_NAME);
|
||||
|
||||
// trigger id, trigger time
|
||||
// request
|
||||
Map<String, String> reqMap = new HashMap<String, String>();
|
||||
reqMap.put(HandlerRepository.NAMESPACE, HandlerRepository.NameSpaceEnum.KILL.name());
|
||||
reqMap.put(HandlerRepository.HANDLER_NAME, handler_name);
|
||||
reqMap.put(HandlerRepository.TRIGGER_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
reqMap.put(HandlerParamEnum.TIMESTAMP.name(), String.valueOf(System.currentTimeMillis()));
|
||||
reqMap.put(HandlerParamEnum.ACTION.name(), ActionEnum.KILL.name());
|
||||
reqMap.put(HandlerParamEnum.EXECUTOR_HANDLER.name(), log.getExecutorHandler());
|
||||
reqMap.put(HandlerParamEnum.JOB_GROUP.name(), log.getJobGroup());
|
||||
reqMap.put(HandlerParamEnum.JOB_NAME.name(), log.getJobName());
|
||||
|
||||
RemoteCallBack callBack = HttpUtil.post(handler_address, reqMap);
|
||||
RemoteCallBack callBack = HttpUtil.post(HttpUtil.addressToUrl(log.getExecutorAddress()), reqMap);
|
||||
if (HttpUtil.RemoteCallBack.SUCCESS.equals(callBack.getStatus())) {
|
||||
log.setHandleStatus(HttpUtil.RemoteCallBack.FAIL);
|
||||
log.setHandleMsg("人为操作主动终止");
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package com.xxl.job.admin.core.jobbean;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
|
@ -16,10 +16,10 @@ import com.xxl.job.admin.core.model.XxlJobInfo;
|
|||
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||
import com.xxl.job.admin.core.thread.JobMonitorHelper;
|
||||
import com.xxl.job.admin.core.util.DynamicSchedulerUtil;
|
||||
import com.xxl.job.core.handler.HandlerRepository;
|
||||
import com.xxl.job.core.handler.HandlerRepository.ActionEnum;
|
||||
import com.xxl.job.core.handler.HandlerRepository.HandlerParamEnum;
|
||||
import com.xxl.job.core.util.HttpUtil;
|
||||
import com.xxl.job.core.util.HttpUtil.RemoteCallBack;
|
||||
import com.xxl.job.core.util.JacksonUtil;
|
||||
|
||||
/**
|
||||
* http job bean
|
||||
|
@ -30,14 +30,12 @@ import com.xxl.job.core.util.JacksonUtil;
|
|||
public class RemoteHttpJobBean extends QuartzJobBean {
|
||||
private static Logger logger = LoggerFactory.getLogger(RemoteHttpJobBean.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context)
|
||||
throws JobExecutionException {
|
||||
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.setJobGroup(jobInfo.getJobGroup());
|
||||
|
@ -45,34 +43,29 @@ public class RemoteHttpJobBean extends QuartzJobBean {
|
|||
jobLog.setJobCron(jobInfo.getJobCron());
|
||||
jobLog.setJobDesc(jobInfo.getJobDesc());
|
||||
jobLog.setJobClass(jobInfo.getJobClass());
|
||||
jobLog.setJobData(jobInfo.getJobData());
|
||||
|
||||
jobLog.setJobClass(RemoteHttpJobBean.class.getName());
|
||||
jobLog.setJobData(jobInfo.getJobData());
|
||||
DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
|
||||
logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog);
|
||||
logger.info(">>>>>>>>>>> xxl-job trigger start, jobId:{}", jobLog.getId());
|
||||
|
||||
// trigger request
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
params.put(HandlerRepository.TRIGGER_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
|
||||
params.put(HandlerRepository.NAMESPACE, HandlerRepository.NameSpaceEnum.RUN.name());
|
||||
params.put(HandlerParamEnum.TIMESTAMP.name(), String.valueOf(System.currentTimeMillis()));
|
||||
params.put(HandlerParamEnum.ACTION.name(), ActionEnum.RUN.name());
|
||||
|
||||
params.put(HandlerRepository.TRIGGER_LOG_ID, String.valueOf(jobLog.getId()));
|
||||
params.put(HandlerRepository.TRIGGER_LOG_ADDRESS, XxlJobLogCallbackServer.getTrigger_log_address());
|
||||
params.put(HandlerParamEnum.LOG_ADDRESS.name(), XxlJobLogCallbackServer.getTrigger_log_address());
|
||||
params.put(HandlerParamEnum.LOG_ID.name(), String.valueOf(jobLog.getId()));
|
||||
|
||||
params.put(HandlerRepository.HANDLER_NAME, jobDataMap.get(HandlerRepository.HANDLER_NAME));
|
||||
params.put(HandlerRepository.HANDLER_PARAMS, jobDataMap.get(HandlerRepository.HANDLER_PARAMS));
|
||||
params.put(HandlerParamEnum.EXECUTOR_HANDLER.name(), jobInfo.getExecutorHandler());
|
||||
params.put(HandlerParamEnum.EXECUTOR_PARAMS.name(), jobInfo.getExecutorParam());
|
||||
|
||||
params.put(HandlerRepository.HANDLER_GLUE_SWITCH, String.valueOf(jobInfo.getGlueSwitch()));
|
||||
params.put(HandlerRepository.HANDLER_JOB_GROUP, jobInfo.getJobGroup());
|
||||
params.put(HandlerRepository.HANDLER_JOB_NAME, jobInfo.getJobName());
|
||||
params.put(HandlerParamEnum.GLUE_SWITCH.name(), String.valueOf(jobInfo.getGlueSwitch()));
|
||||
params.put(HandlerParamEnum.JOB_GROUP.name(), jobInfo.getJobGroup());
|
||||
params.put(HandlerParamEnum.JOB_NAME.name(), jobInfo.getJobName());
|
||||
|
||||
|
||||
// handler address, jetty (servlet dead)
|
||||
String handler_address = jobDataMap.get(HandlerRepository.HANDLER_ADDRESS);
|
||||
|
||||
RemoteCallBack callback = HttpUtil.post(HttpUtil.addressToUrl(handler_address), params);
|
||||
logger.info(">>>>>>>>>>> xxl-job trigger http response, jobLog.id:{}, jobLog:{}, callback:{}", jobLog.getId(), jobLog, callback);
|
||||
// failover trigger
|
||||
RemoteCallBack callback = failoverTrigger(jobInfo.getExecutorAddress(), params, jobLog);
|
||||
jobLog.setExecutorHandler(jobInfo.getGlueSwitch()==0?jobInfo.getExecutorHandler():"GLUE任务");
|
||||
jobLog.setExecutorParam(jobInfo.getExecutorParam());
|
||||
logger.info(">>>>>>>>>>> xxl-job failoverTrigger response, jobId:{}, callback:{}", jobLog.getId(), callback);
|
||||
|
||||
// update trigger info
|
||||
jobLog.setTriggerTime(new Date());
|
||||
|
@ -83,7 +76,45 @@ public class RemoteHttpJobBean extends QuartzJobBean {
|
|||
// monitor triger
|
||||
JobMonitorHelper.monitor(jobLog.getId());
|
||||
|
||||
logger.info(">>>>>>>>>>> xxl-job trigger end, jobLog.id:{}, jobLog:{}", jobLog.getId(), jobLog);
|
||||
logger.info(">>>>>>>>>>> xxl-job trigger end, jobId:{}", jobLog.getId());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* failover for trigger remote address
|
||||
* @param addressArr
|
||||
* @return
|
||||
*/
|
||||
public RemoteCallBack failoverTrigger(String handler_address, HashMap<String, String> handler_params, XxlJobLog jobLog){
|
||||
if (handler_address.split(",").length > 1) {
|
||||
String failoverMessage = "";
|
||||
for (String address : handler_address.split(",")) {
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
params.put(HandlerParamEnum.TIMESTAMP.name(), String.valueOf(System.currentTimeMillis()));
|
||||
params.put(HandlerParamEnum.ACTION.name(), ActionEnum.BEAT.name());
|
||||
RemoteCallBack beatResult = HttpUtil.post(HttpUtil.addressToUrl(address), params);
|
||||
failoverMessage += MessageFormat.format("BEAT running, <br>>>>[address] : {0}, <br>>>>[status] : {1}, <br>>>>[msg] : {2} <br><hr>", address, beatResult.getStatus(), beatResult.getMsg());
|
||||
if (RemoteCallBack.SUCCESS.equals(beatResult.getStatus())) {
|
||||
jobLog.setExecutorAddress(address);
|
||||
RemoteCallBack triggerCallback = HttpUtil.post(HttpUtil.addressToUrl(address), handler_params);
|
||||
triggerCallback.setStatus(RemoteCallBack.SUCCESS);
|
||||
failoverMessage += MessageFormat.format("Trigger running, <br>>>>[address] : {0}, <br>>>>[status] : {1}, <br>>>>[msg] : {2} <br><hr>", address, triggerCallback.getStatus(), triggerCallback.getMsg());
|
||||
triggerCallback.setMsg(failoverMessage);
|
||||
return triggerCallback;
|
||||
}
|
||||
}
|
||||
|
||||
RemoteCallBack result = new RemoteCallBack();
|
||||
result.setStatus(RemoteCallBack.FAIL);
|
||||
result.setMsg(failoverMessage);
|
||||
return result;
|
||||
} else {
|
||||
jobLog.setExecutorAddress(handler_address);
|
||||
RemoteCallBack triggerCallback = HttpUtil.post(HttpUtil.addressToUrl(handler_address), handler_params);
|
||||
String failoverMessage = MessageFormat.format("Trigger running, <br>>>>[address] : {0}, <br>>>>[status] : {1}, <br>>>>[msg] : {2} <br><hr>", handler_address, triggerCallback.getStatus(), triggerCallback.getMsg());
|
||||
triggerCallback.setMsg(failoverMessage);
|
||||
return triggerCallback;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,7 @@ public class XxlJobInfo {
|
|||
private String jobCron; // 任务执行CRON表达式 【base on quartz】
|
||||
private String jobDesc;
|
||||
private String jobClass; // 任务执行JobBean 【base on quartz】
|
||||
private String jobData; // 任务执行数据 Map-JSON-String
|
||||
//private String jobData; // 任务执行数据 Map-JSON-String
|
||||
|
||||
private Date addTime;
|
||||
private Date updateTime;
|
||||
|
@ -24,6 +24,10 @@ public class XxlJobInfo {
|
|||
private String alarmEmail; // 报警邮件
|
||||
private int alarmThreshold; // 报警阀值
|
||||
|
||||
private String executorAddress; // 执行器地址,有多个则逗号分隔
|
||||
private String executorHandler; // 执行器,任务Handler名称
|
||||
private String executorParam; // 执行器,任务参数
|
||||
|
||||
private int glueSwitch; // GLUE模式开关:0-否,1-是
|
||||
private String glueSource; // GLUE源代码
|
||||
private String glueRemark; // GLUE备注
|
||||
|
@ -79,14 +83,6 @@ public class XxlJobInfo {
|
|||
this.jobClass = jobClass;
|
||||
}
|
||||
|
||||
public String getJobData() {
|
||||
return jobData;
|
||||
}
|
||||
|
||||
public void setJobData(String jobData) {
|
||||
this.jobData = jobData;
|
||||
}
|
||||
|
||||
public Date getAddTime() {
|
||||
return addTime;
|
||||
}
|
||||
|
@ -127,12 +123,28 @@ public class XxlJobInfo {
|
|||
this.alarmThreshold = alarmThreshold;
|
||||
}
|
||||
|
||||
public String getJobStatus() {
|
||||
return jobStatus;
|
||||
public String getExecutorAddress() {
|
||||
return executorAddress;
|
||||
}
|
||||
|
||||
public void setJobStatus(String jobStatus) {
|
||||
this.jobStatus = jobStatus;
|
||||
public void setExecutorAddress(String executorAddress) {
|
||||
this.executorAddress = executorAddress;
|
||||
}
|
||||
|
||||
public String getExecutorHandler() {
|
||||
return executorHandler;
|
||||
}
|
||||
|
||||
public void setExecutorHandler(String executorHandler) {
|
||||
this.executorHandler = executorHandler;
|
||||
}
|
||||
|
||||
public String getExecutorParam() {
|
||||
return executorParam;
|
||||
}
|
||||
|
||||
public void setExecutorParam(String executorParam) {
|
||||
this.executorParam = executorParam;
|
||||
}
|
||||
|
||||
public int getGlueSwitch() {
|
||||
|
@ -159,13 +171,12 @@ public class XxlJobInfo {
|
|||
this.glueRemark = glueRemark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XxlJobInfo [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
|
||||
+ ", jobDesc=" + jobDesc + ", jobClass=" + jobClass + ", jobData=" + jobData + ", addTime=" + addTime
|
||||
+ ", updateTime=" + updateTime + ", author=" + author + ", alarmEmail=" + alarmEmail
|
||||
+ ", alarmThreshold=" + alarmThreshold + ", glueSwitch=" + glueSwitch + ", glueSource=" + glueSource
|
||||
+ ", glueRemark=" + glueRemark + ", jobStatus=" + jobStatus + "]";
|
||||
public String getJobStatus() {
|
||||
return jobStatus;
|
||||
}
|
||||
|
||||
public void setJobStatus(String jobStatus) {
|
||||
this.jobStatus = jobStatus;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,10 @@ public class XxlJobLog {
|
|||
private String jobCron;
|
||||
private String jobDesc;
|
||||
private String jobClass;
|
||||
private String jobData;
|
||||
|
||||
private String executorAddress; // 执行器地址,有多个则逗号分隔
|
||||
private String executorHandler; // 执行器,任务Handler名称
|
||||
private String executorParam; // 执行器,任务参数
|
||||
|
||||
// trigger info
|
||||
private Date triggerTime;
|
||||
|
@ -27,6 +30,7 @@ public class XxlJobLog {
|
|||
private Date handleTime;
|
||||
private String handleStatus;
|
||||
private String handleMsg;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
@ -63,11 +67,23 @@ public class XxlJobLog {
|
|||
public void setJobClass(String jobClass) {
|
||||
this.jobClass = jobClass;
|
||||
}
|
||||
public String getJobData() {
|
||||
return jobData;
|
||||
public String getExecutorAddress() {
|
||||
return executorAddress;
|
||||
}
|
||||
public void setJobData(String jobData) {
|
||||
this.jobData = jobData;
|
||||
public void setExecutorAddress(String executorAddress) {
|
||||
this.executorAddress = executorAddress;
|
||||
}
|
||||
public String getExecutorHandler() {
|
||||
return executorHandler;
|
||||
}
|
||||
public void setExecutorHandler(String executorHandler) {
|
||||
this.executorHandler = executorHandler;
|
||||
}
|
||||
public String getExecutorParam() {
|
||||
return executorParam;
|
||||
}
|
||||
public void setExecutorParam(String executorParam) {
|
||||
this.executorParam = executorParam;
|
||||
}
|
||||
public Date getTriggerTime() {
|
||||
return triggerTime;
|
||||
|
@ -106,12 +122,4 @@ public class XxlJobLog {
|
|||
this.handleMsg = handleMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XxlJobLog [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
|
||||
+ ", jobDesc=" + jobDesc + ", jobClass=" + jobClass + ", jobData=" + jobData + ", triggerTime="
|
||||
+ triggerTime + ", triggerStatus=" + triggerStatus + ", triggerMsg=" + triggerMsg + ", handleTime="
|
||||
+ handleTime + ", handleStatus=" + handleStatus + ", handleMsg=" + handleMsg + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.quartz.CronScheduleBuilder;
|
|||
import org.quartz.CronTrigger;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobBuilder;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.JobKey;
|
||||
import org.quartz.Scheduler;
|
||||
|
@ -35,7 +34,6 @@ import com.xxl.job.admin.core.callback.XxlJobLogCallbackServer;
|
|||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.dao.IXxlJobInfoDao;
|
||||
import com.xxl.job.admin.dao.IXxlJobLogDao;
|
||||
import com.xxl.job.core.util.JacksonUtil;
|
||||
|
||||
/**
|
||||
* base quartz scheduler util
|
||||
|
@ -176,10 +174,11 @@ public final class DynamicSchedulerUtil implements ApplicationContextAware, Init
|
|||
}
|
||||
|
||||
JobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey).build();
|
||||
if (jobInfo.getJobData()!=null) {
|
||||
/*if (jobInfo.getJobData()!=null) {
|
||||
JobDataMap jobDataMap = jobDetail.getJobDataMap();
|
||||
jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class)); // JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
|
||||
}
|
||||
jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));
|
||||
// JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
|
||||
}*/
|
||||
|
||||
// schedule : jobDetail + cronTrigger
|
||||
Date date = scheduler.scheduleJob(jobDetail, cronTrigger);
|
||||
|
@ -189,7 +188,6 @@ public final class DynamicSchedulerUtil implements ApplicationContextAware, Init
|
|||
}
|
||||
|
||||
// reschedule
|
||||
@SuppressWarnings("unchecked")
|
||||
public static boolean rescheduleJob(XxlJobInfo jobInfo) throws SchedulerException {
|
||||
|
||||
// TriggerKey valid if_exists
|
||||
|
@ -210,9 +208,9 @@ public final class DynamicSchedulerUtil implements ApplicationContextAware, Init
|
|||
|
||||
// JobDetail-JobDataMap fresh
|
||||
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
|
||||
JobDataMap jobDataMap = jobDetail.getJobDataMap();
|
||||
/*JobDataMap jobDataMap = jobDetail.getJobDataMap();
|
||||
jobDataMap.clear();
|
||||
jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));
|
||||
jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));*/
|
||||
|
||||
// Trigger fresh
|
||||
HashSet<Trigger> triggerSet = new HashSet<Trigger>();
|
||||
|
|
|
@ -63,15 +63,12 @@ public class XxlJobLogDaoImpl implements IXxlJobLogDao {
|
|||
|
||||
@Override
|
||||
public int save(XxlJobLog xxlJobLog) {
|
||||
if (xxlJobLog!=null && xxlJobLog.getJobData().length()>2000) {
|
||||
xxlJobLog.setJobData(xxlJobLog.getJobData().substring(0, 2000));
|
||||
}
|
||||
return sqlSessionTemplate.insert("XxlJobLogMapper.save", xxlJobLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTriggerInfo(XxlJobLog xxlJobLog) {
|
||||
if (xxlJobLog!=null && xxlJobLog.getTriggerMsg()!=null && xxlJobLog.getTriggerMsg().length()>2000) {
|
||||
if (xxlJobLog.getTriggerMsg()!=null && xxlJobLog.getTriggerMsg().length()>2000) {
|
||||
xxlJobLog.setTriggerMsg(xxlJobLog.getTriggerMsg().substring(0, 2000));
|
||||
}
|
||||
return sqlSessionTemplate.update("XxlJobLogMapper.updateTriggerInfo", xxlJobLog);
|
||||
|
@ -79,7 +76,7 @@ public class XxlJobLogDaoImpl implements IXxlJobLogDao {
|
|||
|
||||
@Override
|
||||
public int updateHandleInfo(XxlJobLog xxlJobLog) {
|
||||
if (xxlJobLog!=null && xxlJobLog.getHandleMsg()!=null && xxlJobLog.getHandleMsg().length()>2000) {
|
||||
if (xxlJobLog.getHandleMsg()!=null && xxlJobLog.getHandleMsg().length()>2000) {
|
||||
xxlJobLog.setHandleMsg(xxlJobLog.getHandleMsg().substring(0, 2000));
|
||||
}
|
||||
return sqlSessionTemplate.update("XxlJobLogMapper.updateHandleInfo", xxlJobLog);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package com.xxl.job.admin.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.xxl.job.admin.core.model.ReturnT;
|
||||
|
||||
/**
|
||||
* core job service for xxl-job
|
||||
*
|
||||
* @author xuxueli 2016-5-28 15:30:33
|
||||
*/
|
||||
public interface IXxlJobService {
|
||||
|
||||
public Map<String, Object> pageList(int start, int length, String jobGroup, String jobName, String filterTime);
|
||||
|
||||
public ReturnT<String> add(String jobGroup, String jobName, String jobCron, String jobDesc,
|
||||
String executorAddress, String executorHandler, String executorParam,
|
||||
String author, String alarmEmail, int alarmThreshold,
|
||||
int glueSwitch, String glueSource, String glueRemark);
|
||||
|
||||
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc,
|
||||
String handler_address, String handler_name, String handler_params,
|
||||
String author, String alarmEmail, int alarmThreshold, int glueSwitch);
|
||||
|
||||
public ReturnT<String> remove(String jobGroup, String jobName);
|
||||
|
||||
public ReturnT<String> pause(String jobGroup, String jobName);
|
||||
|
||||
public ReturnT<String> resume(String jobGroup, String jobName);
|
||||
|
||||
public ReturnT<String> triggerJob(String jobGroup, String jobName);
|
||||
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
package com.xxl.job.admin.service.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.quartz.CronExpression;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.xxl.job.admin.core.constant.Constants.JobGroupEnum;
|
||||
import com.xxl.job.admin.core.jobbean.RemoteHttpJobBean;
|
||||
import com.xxl.job.admin.core.model.ReturnT;
|
||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||
import com.xxl.job.admin.core.util.DynamicSchedulerUtil;
|
||||
import com.xxl.job.admin.dao.IXxlJobInfoDao;
|
||||
import com.xxl.job.admin.dao.IXxlJobLogDao;
|
||||
import com.xxl.job.admin.dao.IXxlJobLogGlueDao;
|
||||
import com.xxl.job.admin.service.IXxlJobService;
|
||||
|
||||
/**
|
||||
* core job service for xxl-job
|
||||
* @author xuxueli 2016-5-28 15:30:33
|
||||
*/
|
||||
@Service
|
||||
public class XxlJobServiceImpl implements IXxlJobService {
|
||||
|
||||
@Resource
|
||||
private IXxlJobInfoDao xxlJobInfoDao;
|
||||
@Resource
|
||||
public IXxlJobLogDao xxlJobLogDao;
|
||||
@Resource
|
||||
private IXxlJobLogGlueDao xxlJobLogGlueDao;
|
||||
|
||||
@Override
|
||||
public Map<String, Object> pageList(int start, int length, String jobGroup, String jobName, String filterTime) {
|
||||
|
||||
// page list
|
||||
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) {
|
||||
for (XxlJobInfo jobInfo : list) {
|
||||
DynamicSchedulerUtil.fillJobInfo(jobInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// package result
|
||||
Map<String, Object> maps = new HashMap<String, Object>();
|
||||
maps.put("recordsTotal", list_count); // 总记录数
|
||||
maps.put("recordsFiltered", list_count); // 过滤后的总记录数
|
||||
maps.put("data", list); // 分页列表
|
||||
return maps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> add(String jobGroup, String jobName, String jobCron, String jobDesc,
|
||||
String executorAddress, String executorHandler, String executorParam,
|
||||
String author, String alarmEmail, int alarmThreshold,
|
||||
int glueSwitch, String glueSource, String glueRemark) {
|
||||
// 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”");
|
||||
}
|
||||
if (StringUtils.isBlank(jobDesc)) {
|
||||
return new ReturnT<String>(500, "请输入“任务描述”");
|
||||
}
|
||||
if (StringUtils.isBlank(executorAddress)) {
|
||||
return new ReturnT<String>(500, "请输入“执行器地址”");
|
||||
}
|
||||
if (glueSwitch==0 && StringUtils.isBlank(executorHandler)) {
|
||||
return new ReturnT<String>(500, "请输入“jobHandler”");
|
||||
}
|
||||
if (StringUtils.isBlank(author)) {
|
||||
return new ReturnT<String>(500, "请输入“负责人”");
|
||||
}
|
||||
if (StringUtils.isBlank(alarmEmail)) {
|
||||
return new ReturnT<String>(500, "请输入“报警邮件”");
|
||||
}
|
||||
if (alarmThreshold < 0) {
|
||||
alarmThreshold = 0;
|
||||
}
|
||||
|
||||
try {
|
||||
if (DynamicSchedulerUtil.checkExists(jobName, jobGroup)) {
|
||||
return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
|
||||
}
|
||||
} catch (SchedulerException e1) {
|
||||
e1.printStackTrace();
|
||||
return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
|
||||
}
|
||||
|
||||
// Backup to the database
|
||||
XxlJobInfo jobInfo = new XxlJobInfo();
|
||||
jobInfo.setJobGroup(jobGroup);
|
||||
jobInfo.setJobName(jobName);
|
||||
jobInfo.setJobCron(jobCron);
|
||||
jobInfo.setJobDesc(jobDesc);
|
||||
jobInfo.setJobClass(RemoteHttpJobBean.class.getName());
|
||||
jobInfo.setAuthor(author);
|
||||
jobInfo.setAlarmEmail(alarmEmail);
|
||||
jobInfo.setAlarmThreshold(alarmThreshold);
|
||||
jobInfo.setGlueSwitch(glueSwitch);
|
||||
jobInfo.setGlueSource(glueSource);
|
||||
jobInfo.setGlueRemark(glueRemark);
|
||||
jobInfo.setExecutorAddress(executorAddress);
|
||||
jobInfo.setExecutorHandler(executorHandler);
|
||||
jobInfo.setExecutorParam(executorParam);
|
||||
xxlJobInfoDao.save(jobInfo);
|
||||
|
||||
try {
|
||||
// add job 2 quartz
|
||||
boolean result = DynamicSchedulerUtil.addJob(jobInfo);
|
||||
if (result) {
|
||||
return ReturnT.SUCCESS;
|
||||
} else {
|
||||
xxlJobInfoDao.delete(jobGroup, jobName);
|
||||
return new ReturnT<String>(500, "新增任务失败");
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc,
|
||||
String executorAddress, String executorHandler, String executorParam,
|
||||
String author, String alarmEmail, int alarmThreshold, int glueSwitch) {
|
||||
|
||||
// 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”");
|
||||
}
|
||||
if (StringUtils.isBlank(jobDesc)) {
|
||||
return new ReturnT<String>(500, "请输入“任务描述”");
|
||||
}
|
||||
if (StringUtils.isBlank(executorAddress)) {
|
||||
return new ReturnT<String>(500, "请输入“执行器地址”");
|
||||
}
|
||||
if (glueSwitch==0 && StringUtils.isBlank(executorHandler)) {
|
||||
return new ReturnT<String>(500, "请输入“jobHandler”");
|
||||
}
|
||||
if (StringUtils.isBlank(author)) {
|
||||
return new ReturnT<String>(500, "请输入“负责人”");
|
||||
}
|
||||
if (StringUtils.isBlank(alarmEmail)) {
|
||||
return new ReturnT<String>(500, "请输入“报警邮件”");
|
||||
}
|
||||
if (alarmThreshold < 0) {
|
||||
alarmThreshold = 0;
|
||||
}
|
||||
|
||||
XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName);
|
||||
jobInfo.setJobCron(jobCron);
|
||||
jobInfo.setJobDesc(jobDesc);
|
||||
jobInfo.setAuthor(author);
|
||||
jobInfo.setAlarmEmail(alarmEmail);
|
||||
jobInfo.setAlarmThreshold(alarmThreshold);
|
||||
jobInfo.setGlueSwitch(glueSwitch);
|
||||
jobInfo.setExecutorAddress(executorAddress);
|
||||
jobInfo.setExecutorHandler(executorHandler);
|
||||
jobInfo.setExecutorParam(executorParam);
|
||||
|
||||
try {
|
||||
// fresh quartz
|
||||
DynamicSchedulerUtil.rescheduleJob(jobInfo);
|
||||
|
||||
// fresh db
|
||||
xxlJobInfoDao.update(jobInfo);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> remove(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.removeJob(jobName, jobGroup);
|
||||
xxlJobInfoDao.delete(jobGroup, jobName);
|
||||
xxlJobLogDao.delete(jobGroup, jobName);
|
||||
xxlJobLogGlueDao.delete(jobGroup, jobName);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> pause(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.pauseJob(jobName, jobGroup); // jobStatus do not store
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> resume(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.resumeJob(jobName, jobGroup);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnT<String> triggerJob(String jobGroup, String jobName) {
|
||||
try {
|
||||
DynamicSchedulerUtil.triggerJob(jobName, jobGroup);
|
||||
return ReturnT.SUCCESS;
|
||||
} catch (SchedulerException e) {
|
||||
e.printStackTrace();
|
||||
return ReturnT.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
<context:component-scan base-package="com.xxl.job.admin.dao" />
|
||||
<context:component-scan base-package="com.xxl.job.admin.service, com.xxl.job.admin.dao" />
|
||||
|
||||
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
|
||||
<property name="templateLoaderPath" value="/WEB-INF/template/" />
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
</bean>
|
||||
|
||||
<!-- part 2 :for tx -->
|
||||
<!--
|
||||
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
@ -68,9 +67,8 @@
|
|||
</tx:advice>
|
||||
|
||||
<aop:config>
|
||||
<aop:pointcut id="txoperation" expression="execution(* com.xxl.job.admin.service.imp.*.*(..))" />
|
||||
<aop:pointcut id="txoperation" expression="execution(* com.xxl.job.admin.service.impl.*.*(..))" />
|
||||
<aop:advisor pointcut-ref="txoperation" advice-ref="txAdvice" />
|
||||
</aop:config>
|
||||
-->
|
||||
|
||||
</beans>
|
|
@ -11,7 +11,6 @@
|
|||
<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" />
|
||||
|
@ -20,6 +19,10 @@
|
|||
<result column="alarm_email" property="alarmEmail" />
|
||||
<result column="alarm_threshold" property="alarmThreshold" />
|
||||
|
||||
<result column="executor_address" property="executorAddress" />
|
||||
<result column="executor_handler" property="executorHandler" />
|
||||
<result column="executor_param" property="executorParam" />
|
||||
|
||||
<result column="glue_switch" property="glueSwitch" />
|
||||
<result column="glue_source" property="glueSource" />
|
||||
<result column="glue_remark" property="glueRemark" />
|
||||
|
@ -32,12 +35,14 @@
|
|||
t.job_cron,
|
||||
t.job_desc,
|
||||
t.job_class,
|
||||
t.job_data,
|
||||
t.add_time,
|
||||
t.update_time,
|
||||
t.author,
|
||||
t.alarm_email,
|
||||
t.alarm_threshold,
|
||||
t.executor_address,
|
||||
t.executor_handler,
|
||||
t.executor_param,
|
||||
t.glue_switch,
|
||||
t.glue_source,
|
||||
t.glue_remark
|
||||
|
@ -78,12 +83,14 @@
|
|||
job_cron,
|
||||
job_desc,
|
||||
job_class,
|
||||
job_data,
|
||||
add_time,
|
||||
update_time,
|
||||
author,
|
||||
alarm_email,
|
||||
alarm_threshold,
|
||||
executor_address,
|
||||
executor_handler,
|
||||
executor_param,
|
||||
glue_switch,
|
||||
glue_source,
|
||||
glue_remark
|
||||
|
@ -93,12 +100,14 @@
|
|||
#{jobCron},
|
||||
#{jobDesc},
|
||||
#{jobClass},
|
||||
#{jobData},
|
||||
NOW(),
|
||||
NOW(),
|
||||
#{author},
|
||||
#{alarmEmail},
|
||||
#{alarmThreshold},
|
||||
#{executorAddress},
|
||||
#{executorHandler},
|
||||
#{executorParam},
|
||||
#{glueSwitch},
|
||||
#{glueSource},
|
||||
#{glueRemark}
|
||||
|
@ -120,11 +129,13 @@
|
|||
SET
|
||||
job_cron = #{jobCron},
|
||||
job_desc = #{jobDesc},
|
||||
job_data = #{jobData},
|
||||
update_time = NOW(),
|
||||
author = #{author},
|
||||
alarm_email = #{alarmEmail},
|
||||
alarm_threshold = #{alarmThreshold},
|
||||
executor_address = #{executorAddress},
|
||||
executor_handler = #{executorHandler},
|
||||
executor_param = #{executorParam},
|
||||
glue_switch = #{glueSwitch},
|
||||
glue_source = #{glueSource},
|
||||
glue_remark = #{glueRemark}
|
||||
|
|
|
@ -11,7 +11,10 @@
|
|||
<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="executor_address" property="executorAddress" />
|
||||
<result column="executor_handler" property="executorHandler" />
|
||||
<result column="executor_param" property="executorParam" />
|
||||
|
||||
<result column="trigger_time" property="triggerTime" />
|
||||
<result column="trigger_status" property="triggerStatus" />
|
||||
|
@ -20,6 +23,7 @@
|
|||
<result column="handle_time" property="handleTime" />
|
||||
<result column="handle_status" property="handleStatus" />
|
||||
<result column="handle_msg" property="handleMsg" />
|
||||
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
|
@ -29,7 +33,9 @@
|
|||
t.job_cron,
|
||||
t.job_desc,
|
||||
t.job_class,
|
||||
t.job_data,
|
||||
t.executor_address,
|
||||
t.executor_handler,
|
||||
t.executor_param,
|
||||
t.trigger_time,
|
||||
t.trigger_status,
|
||||
t.trigger_msg,
|
||||
|
@ -98,14 +104,18 @@
|
|||
`job_cron`,
|
||||
`job_desc`,
|
||||
`job_class`,
|
||||
`job_data`
|
||||
`executor_address`,
|
||||
`executor_handler`,
|
||||
`executor_param`
|
||||
) VALUES (
|
||||
#{jobGroup},
|
||||
#{jobName},
|
||||
#{jobCron},
|
||||
#{jobDesc},
|
||||
#{jobClass},
|
||||
#{jobData}
|
||||
#{executorAddress},
|
||||
#{executorHandler},
|
||||
#{executorParam}
|
||||
);
|
||||
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
|
||||
SELECT LAST_INSERT_ID()
|
||||
|
@ -117,7 +127,10 @@
|
|||
SET
|
||||
`trigger_time`= #{triggerTime},
|
||||
`trigger_status`= #{triggerStatus},
|
||||
`trigger_msg`= #{triggerMsg}
|
||||
`trigger_msg`= #{triggerMsg},
|
||||
`executor_address`= #{executorAddress},
|
||||
`executor_handler`= #{executorHandler},
|
||||
`executor_param`= #{executorParam}
|
||||
WHERE `id`= #{id}
|
||||
</update>
|
||||
|
||||
|
|
|
@ -72,7 +72,9 @@
|
|||
<th name="jobDesc" >描述</th>
|
||||
<th name="jobCron" >Cron</th>
|
||||
<th name="jobClass" >JobBean</th>
|
||||
<th name="jobData" >任务数据</th>
|
||||
<th name="executorAddress" >执行器地址</th>
|
||||
<th name="executorHandler" >JobHandler</th>
|
||||
<th name="executorParam" >任务参数</th>
|
||||
<th name="addTime" >新增时间</th>
|
||||
<th name="updateTime" >更新时间</th>
|
||||
<th name="author" >负责人</th>
|
||||
|
@ -126,13 +128,13 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lastname" class="col-sm-2 control-label">执行器地址<font color="red">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“执行器地址”" maxlength="200" ></div>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="executorAddress" placeholder="请输入“执行器地址”,多个地址逗号分隔" maxlength="200" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">jobHandler<font color="red">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“jobHandler”" maxlength="200" ></div>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="请输入“jobHandler”" maxlength="200" ></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div>
|
||||
</div>
|
||||
|
@ -207,13 +209,13 @@ public class DemoJobHandler extends IJobHandler {
|
|||
|
||||
<div class="form-group">
|
||||
<label for="lastname" class="col-sm-2 control-label">执行器地址<font color="red">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“执行器地址”" maxlength="200" ></div>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="executorAddress" placeholder="请输入“执行器地址”,多个地址逗号分隔" maxlength="200" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">jobHandler<font color="red">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“jobHandler”" maxlength="200" ></div>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="请输入“jobHandler”" maxlength="200" ></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
|
||||
<label for="lastname" class="col-sm-2 control-label">负责人<font color="red">*</font></label>
|
||||
<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div>
|
||||
</div>
|
||||
|
|
|
@ -78,7 +78,9 @@
|
|||
<th name="jobCron" >Cron</th>
|
||||
<th name="jobDesc" >描述</th>
|
||||
<th name="jobClass" >JobBean</th>
|
||||
<th name="jobData" >任务数据</th>
|
||||
<th name="executorAddress" >执行器地址</th>
|
||||
<th name="executorHandler" >JobHandler</th>
|
||||
<th name="executorParam" >任务参数</th>
|
||||
<th name="triggerTime" >调度时间</th>
|
||||
<th name="triggerStatus" >调度结果</th>
|
||||
<th name="triggerMsg" >调度日志</th>
|
|
@ -33,17 +33,9 @@ $(function() {
|
|||
{ "data": 'jobDesc', "visible" : true},
|
||||
{ "data": 'jobCron', "visible" : true},
|
||||
{ "data": 'jobClass', "visible" : false},
|
||||
{
|
||||
"data": 'jobData',
|
||||
"visible" : true,
|
||||
"render": function ( data, type, row ) {
|
||||
var _jobData = eval('(' + data + ')'); // row.jobData
|
||||
var html = "<p title='" + data + "'>执行器:" + _jobData.handler_name +
|
||||
"<br>执行参数:" + _jobData.handler_params +
|
||||
"<br>执行器地址:" + _jobData.handler_address + "</p>";
|
||||
return html;
|
||||
}
|
||||
},
|
||||
{ "data": 'executorAddress', "visible" : false},
|
||||
{ "data": 'executorHandler', "visible" : false},
|
||||
{ "data": 'executorParam', "visible" : false},
|
||||
{
|
||||
"data": 'addTime',
|
||||
"visible" : false,
|
||||
|
@ -90,15 +82,12 @@ $(function() {
|
|||
var logUrl = base_url +'/joblog?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName;
|
||||
|
||||
// log url
|
||||
var codeHtml = "";
|
||||
if(row.glueSwitch != 0){
|
||||
var codeBtn = "";
|
||||
if(row.glueSwitch > 0){
|
||||
var codeUrl = base_url +'/jobcode?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName;
|
||||
codeHtml = '<button class="btn btn-warning btn-xs" type="button" onclick="javascript:window.open(\'' + codeUrl + '\')" >GLUE</button> '
|
||||
codeBtn = '<button class="btn btn-warning btn-xs" type="button" onclick="javascript:window.open(\'' + codeUrl + '\')" >GLUE</button> '
|
||||
}
|
||||
|
||||
// job data
|
||||
var jobDataMap = eval('(' + row.jobData + ')');
|
||||
|
||||
var html = '<p id="'+ row.id +'" '+
|
||||
' jobGroup="'+ row.jobGroup +'" '+
|
||||
' jobName="'+ row.jobName +'" '+
|
||||
|
@ -106,9 +95,9 @@ $(function() {
|
|||
' jobDesc="'+ row.jobDesc +'" '+
|
||||
' jobClass="'+ row.jobClass +'" '+
|
||||
' jobData="'+ row.jobData +'" '+
|
||||
' handler_params="'+jobDataMap.handler_params +'" '+
|
||||
' handler_address="'+ jobDataMap.handler_address +'" '+
|
||||
' handler_name="'+ jobDataMap.handler_name +'" '+
|
||||
' executorAddress="'+row.executorAddress +'" '+
|
||||
' executorHandler="'+ row.executorHandler +'" '+
|
||||
' executorParam="'+ row.executorParam +'" '+
|
||||
' author="'+ row.author +'" '+
|
||||
' alarmEmail="'+ row.alarmEmail +'" '+
|
||||
' alarmThreshold="'+ row.alarmThreshold +'" '+
|
||||
|
@ -118,7 +107,7 @@ $(function() {
|
|||
pause_resume +
|
||||
'<button class="btn btn-primary btn-xs" type="job_del" type="button" onclick="javascript:window.open(\'' + logUrl + '\')" >日志</button><br> '+
|
||||
'<button class="btn btn-warning btn-xs update" type="button">编辑</button> '+
|
||||
codeHtml +
|
||||
codeBtn +
|
||||
'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button> '+
|
||||
'</p>';
|
||||
|
||||
|
@ -236,11 +225,11 @@ $(function() {
|
|||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
handler_address : {
|
||||
executorAddress : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
handler_name : {
|
||||
executorHandler : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
|
@ -271,11 +260,11 @@ $(function() {
|
|||
required :"请输入“任务描述”." ,
|
||||
maxlength:"“任务描述”长度不应超过200位"
|
||||
},
|
||||
handler_address : {
|
||||
executorAddress : {
|
||||
required :"请输入“执行器地址”." ,
|
||||
maxlength:"“执行器地址”长度不应超过200位"
|
||||
},
|
||||
handler_name : {
|
||||
executorHandler : {
|
||||
required : "请输入“jobHandler”." ,
|
||||
maxlength: "“jobHandler”长度不应超过200位"
|
||||
},
|
||||
|
@ -359,9 +348,9 @@ $(function() {
|
|||
$("#updateModal .form input[name='jobName']").val($(this).parent('p').attr("jobName"));
|
||||
$("#updateModal .form input[name='jobCron']").val($(this).parent('p').attr("jobCron"));
|
||||
$("#updateModal .form input[name='jobDesc']").val($(this).parent('p').attr("jobDesc"));
|
||||
$("#updateModal .form input[name='handler_address']").val($(this).parent('p').attr("handler_address"));
|
||||
$("#updateModal .form input[name='handler_name']").val($(this).parent('p').attr("handler_name"));
|
||||
$("#updateModal .form input[name='handler_params']").val($(this).parent('p').attr("handler_params"));
|
||||
$("#updateModal .form input[name='executorAddress']").val($(this).parent('p').attr("executorAddress"));
|
||||
$("#updateModal .form input[name='executorHandler']").val($(this).parent('p').attr("executorHandler"));
|
||||
$("#updateModal .form input[name='executorParam']").val($(this).parent('p').attr("executorParam"));
|
||||
$("#updateModal .form input[name='author']").val($(this).parent('p').attr("author"));
|
||||
$("#updateModal .form input[name='alarmEmail']").val($(this).parent('p').attr("alarmEmail"));
|
||||
$("#updateModal .form input[name='alarmThreshold']").val($(this).parent('p').attr("alarmThreshold"));
|
||||
|
@ -393,11 +382,11 @@ $(function() {
|
|||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
handler_address : {
|
||||
executorAddress : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
handler_name : {
|
||||
executorHandler : {
|
||||
required : true ,
|
||||
maxlength: 200
|
||||
},
|
||||
|
@ -423,11 +412,11 @@ $(function() {
|
|||
required :"请输入“任务描述”." ,
|
||||
maxlength:"“任务描述”长度不应超过200位"
|
||||
},
|
||||
handler_address : {
|
||||
executorAddress : {
|
||||
required :"请输入“执行器地址”." ,
|
||||
maxlength:"“执行器地址”长度不应超过200位"
|
||||
},
|
||||
handler_name : {
|
||||
executorHandler : {
|
||||
required : "请输入“jobHandler”." ,
|
||||
maxlength: "“jobHandler”长度不应超过200位"
|
||||
},
|
||||
|
|
|
@ -60,22 +60,14 @@ $(function() {
|
|||
return data;
|
||||
}
|
||||
},
|
||||
{ "data": 'jobName'},
|
||||
{ "data": 'jobName', "visible" : false},
|
||||
{ "data": 'jobCron', "visible" : false},
|
||||
{ "data": 'jobDesc', "visible" : false},
|
||||
{ "data": 'jobClass', "visible" : false},
|
||||
{
|
||||
"data": 'jobData',
|
||||
"visible" : true,
|
||||
"render": function ( data, type, row ) {
|
||||
var _jobData = eval('(' + data + ')'); // row.jobData
|
||||
var html = "<p title='" + data + "'>JobHandler:" + _jobData.handler_name +
|
||||
"<br>执行参数:" + _jobData.handler_params +
|
||||
"<br>执行器地址:" + _jobData.handler_address + "</p>";
|
||||
|
||||
return data?'<a class="logMsg" href="javascript:;" >查看<span style="display:none;">'+ html +'</span></a>':"无";
|
||||
}
|
||||
},
|
||||
{ "data": 'executorAddress', "visible" : true},
|
||||
{ "data": 'executorHandler', "visible" : true},
|
||||
{ "data": 'executorParam', "visible" : true},
|
||||
{
|
||||
"data": 'triggerTime',
|
||||
"render": function ( data, type, row ) {
|
||||
|
@ -106,12 +98,6 @@ $(function() {
|
|||
"render": function ( data, type, row ) {
|
||||
// better support expression or string, not function
|
||||
return function () {
|
||||
// local job do not support trigger detail log, now
|
||||
var _jobData = eval('(' + row.jobData + ')');
|
||||
if (!_jobData.handler_address) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (row.triggerStatus == 'SUCCESS'){
|
||||
var temp = '<a href="javascript:;" class="logDetail" _id="'+ row.id +'">执行日志</a>';
|
||||
if(!row.handleStatus){
|
||||
|
|
|
@ -34,7 +34,6 @@ public class XxlJobInfoTest {
|
|||
info.setJobName("job_name");
|
||||
info.setJobCron("jobCron");
|
||||
info.setJobClass("jobClass");
|
||||
info.setJobData("jobData");
|
||||
int count = xxlJobInfoDao.save(info);
|
||||
System.out.println(count);
|
||||
System.out.println(info.getId());
|
||||
|
@ -48,7 +47,6 @@ public class XxlJobInfoTest {
|
|||
XxlJobInfo item = xxlJobInfoDao.load(null ,"job_name");
|
||||
|
||||
item.setJobCron("jobCron2");
|
||||
item.setJobData("jobData2");
|
||||
xxlJobInfoDao.update(item);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ public class XxlJobLogTest {
|
|||
xxlJobLog.setJobName("job_name");
|
||||
xxlJobLog.setJobCron("jobCron");
|
||||
xxlJobLog.setJobClass("jobClass");
|
||||
xxlJobLog.setJobData("jobData");
|
||||
int count = xxlJobLogDao.save(xxlJobLog);
|
||||
System.out.println(count);
|
||||
System.out.println(xxlJobLog.getId());
|
||||
|
|
|
@ -19,20 +19,49 @@ import com.xxl.job.core.util.JacksonUtil;
|
|||
public class HandlerRepository {
|
||||
private static Logger logger = LoggerFactory.getLogger(HandlerRepository.class);
|
||||
|
||||
public static final String NAMESPACE = "namespace";
|
||||
public enum NameSpaceEnum{RUN, KILL, LOG}
|
||||
|
||||
public static final String HANDLER_ADDRESS = "handler_address";
|
||||
public static final String HANDLER_PARAMS = "handler_params";
|
||||
|
||||
public static final String HANDLER_GLUE_SWITCH = "handler_glue_switch";
|
||||
public static final String HANDLER_NAME = "handler_name";
|
||||
public static final String HANDLER_JOB_GROUP = "handler_job_group";
|
||||
public static final String HANDLER_JOB_NAME = "handler_job_name";
|
||||
|
||||
public static final String TRIGGER_LOG_ID = "trigger_log_id";
|
||||
public static final String TRIGGER_LOG_ADDRESS = "trigger_log_address";
|
||||
public static final String TRIGGER_TIMESTAMP = "trigger_timestamp";
|
||||
public enum HandlerParamEnum{
|
||||
/**
|
||||
* trigger timestamp
|
||||
*/
|
||||
TIMESTAMP,
|
||||
/**
|
||||
* trigger action
|
||||
*/
|
||||
ACTION,
|
||||
/**
|
||||
* remote executor jobhandler
|
||||
*/
|
||||
EXECUTOR_HANDLER,
|
||||
/**
|
||||
* params of jobhandler
|
||||
*/
|
||||
EXECUTOR_PARAMS,
|
||||
/**
|
||||
* switch of job, if open glue model
|
||||
*/
|
||||
GLUE_SWITCH,
|
||||
/**
|
||||
* job group
|
||||
*/
|
||||
JOB_GROUP,
|
||||
/**
|
||||
* job name
|
||||
*/
|
||||
JOB_NAME,
|
||||
/**
|
||||
* address for callback log
|
||||
*/
|
||||
LOG_ADDRESS,
|
||||
/**
|
||||
* log id
|
||||
*/
|
||||
LOG_ID,
|
||||
/**
|
||||
* log date
|
||||
*/
|
||||
LOG_DATE
|
||||
}
|
||||
public enum ActionEnum{RUN, KILL, LOG, BEAT}
|
||||
|
||||
public static ConcurrentHashMap<String, HandlerThread> handlerTreadMap = new ConcurrentHashMap<String, HandlerThread>();
|
||||
|
||||
|
@ -53,27 +82,26 @@ public class HandlerRepository {
|
|||
callback.setStatus(RemoteCallBack.FAIL);
|
||||
|
||||
// check namespace
|
||||
String namespace = _param.get(HandlerRepository.NAMESPACE);
|
||||
String namespace = _param.get(HandlerParamEnum.ACTION.name());
|
||||
if (namespace==null || namespace.trim().length()==0) {
|
||||
callback.setMsg("param[NAMESPACE] can not be null.");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
|
||||
// parse namespace
|
||||
if (namespace.equals(HandlerRepository.NameSpaceEnum.RUN.name())) {
|
||||
// encryption check
|
||||
long timestamp = _param.get(HandlerRepository.TRIGGER_TIMESTAMP)!=null?Long.valueOf(_param.get(HandlerRepository.TRIGGER_TIMESTAMP)):-1;
|
||||
long timestamp = _param.get(HandlerParamEnum.TIMESTAMP.name())!=null?Long.valueOf(_param.get(HandlerParamEnum.TIMESTAMP.name())):-1;
|
||||
if (System.currentTimeMillis() - timestamp > 60000) {
|
||||
callback.setMsg("Timestamp check failed.");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
|
||||
// parse namespace
|
||||
if (namespace.equals(ActionEnum.RUN.name())) {
|
||||
// push data to queue
|
||||
String handler_glue_switch = _param.get(HandlerRepository.HANDLER_GLUE_SWITCH);
|
||||
String handler_glue_switch = _param.get(HandlerParamEnum.GLUE_SWITCH.name());
|
||||
HandlerThread handlerThread = null;
|
||||
if ("0".equals(handler_glue_switch)) {
|
||||
// bean model
|
||||
String handler_name = _param.get(HandlerRepository.HANDLER_NAME);
|
||||
String handler_name = _param.get(HandlerParamEnum.EXECUTOR_HANDLER.name());
|
||||
if (handler_name == null || handler_name.trim().length()==0) {
|
||||
callback.setMsg("bean model handler[HANDLER_NAME] not found.");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
|
@ -85,70 +113,81 @@ public class HandlerRepository {
|
|||
}
|
||||
} else {
|
||||
// glue
|
||||
String handler_job_group = _param.get(HandlerRepository.HANDLER_JOB_GROUP);
|
||||
String handler_job_name = _param.get(HandlerRepository.HANDLER_JOB_NAME);
|
||||
if (handler_job_group == null || handler_job_group.trim().length()==0 || handler_job_name == null || handler_job_name.trim().length()==0) {
|
||||
String job_group = _param.get(HandlerParamEnum.JOB_GROUP.name());
|
||||
String job_name = _param.get(HandlerParamEnum.JOB_NAME.name());
|
||||
if (job_group == null || job_group.trim().length()==0 || job_name == null || job_name.trim().length()==0) {
|
||||
callback.setMsg("glue model handler[job group or name] is null.");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
String glueHandleName = "glue_".concat(handler_job_group).concat("_").concat(handler_job_name);
|
||||
String glueHandleName = "glue_".concat(job_group).concat("_").concat(job_name);
|
||||
handlerThread = handlerTreadMap.get(glueHandleName);
|
||||
if (handlerThread==null) {
|
||||
HandlerRepository.regist(glueHandleName, new GlueJobHandler(handler_job_group, handler_job_name));
|
||||
HandlerRepository.regist(glueHandleName, new GlueJobHandler(job_group, job_name));
|
||||
}
|
||||
handlerThread = handlerTreadMap.get(glueHandleName);
|
||||
}
|
||||
|
||||
handlerThread.pushData(_param);
|
||||
callback.setStatus(RemoteCallBack.SUCCESS);
|
||||
} else if (namespace.equals(HandlerRepository.NameSpaceEnum.LOG.name())) {
|
||||
String trigger_log_id = _param.get(HandlerRepository.TRIGGER_LOG_ID);
|
||||
String trigger_timestamp = _param.get(HandlerRepository.TRIGGER_TIMESTAMP);
|
||||
if (trigger_log_id==null || trigger_timestamp==null) {
|
||||
callback.setMsg("trigger_log_id | trigger_timestamp can not be null.");
|
||||
} else if (namespace.equals(ActionEnum.LOG.name())) {
|
||||
String log_id = _param.get(HandlerParamEnum.LOG_ID.name());
|
||||
String log_date = _param.get(HandlerParamEnum.LOG_DATE.name());
|
||||
if (log_id==null || log_date==null) {
|
||||
callback.setMsg("LOG_ID | LOG_DATE can not be null.");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
int logId = -1;
|
||||
Date triggerDate = null;
|
||||
try {
|
||||
logId = Integer.valueOf(trigger_log_id);
|
||||
triggerDate = new Date(Long.valueOf(trigger_timestamp));
|
||||
logId = Integer.valueOf(log_id);
|
||||
triggerDate = new Date(Long.valueOf(log_date));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
if (logId<=0 || triggerDate==null) {
|
||||
callback.setMsg("trigger_log_id | trigger_timestamp is not parsed valid.");
|
||||
callback.setMsg("LOG_ID | LOG_DATE parse error.");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
String logConteng = XxlJobFileAppender.readLog(triggerDate, trigger_log_id);
|
||||
String logConteng = XxlJobFileAppender.readLog(triggerDate, log_id);
|
||||
callback.setStatus(RemoteCallBack.SUCCESS);
|
||||
callback.setMsg(logConteng);
|
||||
} else if (namespace.equals(HandlerRepository.NameSpaceEnum.KILL.name())) {
|
||||
// encryption check
|
||||
long timestamp = _param.get(HandlerRepository.TRIGGER_TIMESTAMP)!=null?Long.valueOf(_param.get(HandlerRepository.TRIGGER_TIMESTAMP)):-1;
|
||||
if (System.currentTimeMillis() - timestamp > 60000) {
|
||||
callback.setMsg("Timestamp check failed.");
|
||||
} else if (namespace.equals(ActionEnum.KILL.name())) {
|
||||
// kill handlerThread, and create new one
|
||||
String handler_glue_switch = _param.get(HandlerParamEnum.GLUE_SWITCH.name());
|
||||
String handlerName = null;
|
||||
if ("0".equals(handler_glue_switch)) {
|
||||
String executor_handler = _param.get(HandlerParamEnum.EXECUTOR_HANDLER.name());
|
||||
if (executor_handler==null) {
|
||||
callback.setMsg("bean job , param[EXECUTOR_HANDLER] is null");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
handlerName = executor_handler;
|
||||
} else {
|
||||
// glue
|
||||
String job_group = _param.get(HandlerParamEnum.JOB_GROUP.name());
|
||||
String job_name = _param.get(HandlerParamEnum.JOB_NAME.name());
|
||||
if (job_group==null || job_group.trim().length()==0 || job_name==null || job_name.trim().length()==0) {
|
||||
callback.setMsg("glue job , param[JOB_GROUP or JOB_NAME] is null");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
handlerName = "glue_".concat(job_group).concat("_").concat(job_name);
|
||||
}
|
||||
|
||||
// kill handlerThread, and create new one
|
||||
String handler_name = _param.get(HandlerRepository.HANDLER_NAME);
|
||||
if (handler_name!=null && handler_name.trim().length()>0) {
|
||||
HandlerThread handlerThread = handlerTreadMap.get(handler_name);
|
||||
HandlerThread handlerThread = handlerTreadMap.get(handlerName);
|
||||
if (handlerThread != null) {
|
||||
IJobHandler handler = handlerThread.getHandler();
|
||||
handlerThread.toStop();
|
||||
handlerThread.interrupt();
|
||||
regist(handler_name, handler);
|
||||
regist(handlerName, handler);
|
||||
callback.setStatus(RemoteCallBack.SUCCESS);
|
||||
} else {
|
||||
callback.setMsg("handler[" + handler_name + "] not found.");
|
||||
}
|
||||
}else{
|
||||
callback.setMsg("param[HANDLER_NAME] can not be null.");
|
||||
callback.setMsg("job handler[" + handlerName + "] not found.");
|
||||
}
|
||||
|
||||
} else if (namespace.equals(ActionEnum.BEAT.name())) {
|
||||
callback.setStatus(RemoteCallBack.SUCCESS);
|
||||
callback.setMsg(null);
|
||||
} else {
|
||||
callback.setMsg("param[NAMESPACE] is not valid.");
|
||||
callback.setMsg("param[Action] is not valid.");
|
||||
return JacksonUtil.writeValueAsString(callback);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.eclipse.jetty.util.ConcurrentHashSet;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.xxl.job.core.handler.HandlerRepository.HandlerParamEnum;
|
||||
import com.xxl.job.core.handler.IJobHandler.JobHandleStatus;
|
||||
import com.xxl.job.core.log.XxlJobFileAppender;
|
||||
import com.xxl.job.core.util.HttpUtil;
|
||||
|
@ -47,7 +48,7 @@ public class HandlerThread extends Thread{
|
|||
}
|
||||
|
||||
public void pushData(Map<String, String> param) {
|
||||
if (param.get(HandlerRepository.TRIGGER_LOG_ID)!=null && !logIdSet.contains(param.get(HandlerRepository.TRIGGER_LOG_ID))) {
|
||||
if (param.get(HandlerParamEnum.LOG_ID.name())!=null && !logIdSet.contains(param.get(HandlerParamEnum.LOG_ID.name()))) {
|
||||
handlerDataQueue.offer(param);
|
||||
}
|
||||
}
|
||||
|
@ -60,9 +61,9 @@ public class HandlerThread extends Thread{
|
|||
Map<String, String> handlerData = handlerDataQueue.poll();
|
||||
if (handlerData!=null) {
|
||||
i= 0;
|
||||
String trigger_log_address = handlerData.get(HandlerRepository.TRIGGER_LOG_ADDRESS);
|
||||
String trigger_log_id = handlerData.get(HandlerRepository.TRIGGER_LOG_ID);
|
||||
String handler_params = handlerData.get(HandlerRepository.HANDLER_PARAMS);
|
||||
String trigger_log_address = handlerData.get(HandlerParamEnum.LOG_ADDRESS.name());
|
||||
String trigger_log_id = handlerData.get(HandlerParamEnum.LOG_ID.name());
|
||||
String handler_params = handlerData.get(HandlerParamEnum.EXECUTOR_PARAMS.name());
|
||||
logIdSet.remove(trigger_log_id);
|
||||
|
||||
// parse param
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package com.xxl.job.core.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -98,9 +96,10 @@ public class HttpUtil {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
StringWriter out = new StringWriter();
|
||||
/*StringWriter out = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(out));
|
||||
callback.setMsg(out.toString());
|
||||
callback.setMsg(out.toString());*/
|
||||
callback.setMsg(e.getMessage());
|
||||
} finally{
|
||||
if (httpPost!=null) {
|
||||
httpPost.releaseConnection();
|
||||
|
|
Loading…
Reference in New Issue