xueli.xue 8 роки тому
батько
коміт
1e0ba18606

+ 2 - 0
db/tables_xxl_job.sql

@@ -156,6 +156,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (
   `author` varchar(64) DEFAULT NULL COMMENT '作者',
   `alarm_email` varchar(255) 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源代码',
@@ -169,6 +170,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` (
   `job_group` varchar(255) NOT NULL COMMENT '任务组',
   `job_name` varchar(255) NOT 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 '调度-结果',

+ 10 - 10
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobInfoController.java

@@ -33,27 +33,27 @@ public class JobInfoController {
 	@ResponseBody
 	public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,  
 			@RequestParam(required = false, defaultValue = "10") int length,
-			String jobGroup, String jobDesc, String filterTime) {
+			String jobGroup, String executorHandler, String filterTime) {
 		
-		return xxlJobService.pageList(start, length, jobGroup, jobDesc, filterTime);
+		return xxlJobService.pageList(start, length, jobGroup, executorHandler, filterTime);
 	}
 	
 	@RequestMapping("/add")
 	@ResponseBody
-	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc,
-			String executorAddress, String executorParam, String author, String alarmEmail,
-			int glueSwitch, String glueSource, String glueRemark) {
+	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc, String author, String alarmEmail,
+			String executorAddress, String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark) {
 		
-		return xxlJobService.add(jobGroup, jobCron, jobDesc, executorAddress, executorParam,
-				author, alarmEmail, glueSwitch, glueSource, glueRemark);
+		return xxlJobService.add(jobGroup, jobCron, jobDesc, author, alarmEmail,
+				executorAddress, executorHandler, executorParam, glueSwitch, glueSource, glueRemark);
 	}
 	
 	@RequestMapping("/reschedule")
 	@ResponseBody
-	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc,
-			String executorAddress, String executorParam, String author, String alarmEmail) {
+	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
+			String executorAddress, String executorHandler, String executorParam, int glueSwitch) {
 
-		return xxlJobService.reschedule(jobGroup, jobName, jobCron, jobDesc, executorAddress, executorParam, author, alarmEmail);
+		return xxlJobService.reschedule(jobGroup, jobName, jobCron, jobDesc, author, alarmEmail,
+				executorAddress, executorHandler, executorParam, glueSwitch);
 	}
 	
 	@RequestMapping("/remove")

+ 9 - 11
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java

@@ -22,6 +22,7 @@ public class XxlJobInfo {
 	private String alarmEmail;	// 报警邮件
 	
 	private String executorAddress;	// 执行器地址,有多个则逗号分隔
+	private String executorHandler;	// 执行器,任务Handler名称
 	private String executorParam;	// 执行器,任务参数
 	
 	private int glueSwitch;		// GLUE模式开关:0-否,1-是
@@ -31,9 +32,6 @@ public class XxlJobInfo {
 	// copy from quartz
 	private String jobStatus;	// 任务状态 【base on quartz】
 
-	// generate job key
-	private String jobKey;
-
 	public int getId() {
 		return id;
 	}
@@ -114,6 +112,14 @@ public class XxlJobInfo {
 		this.executorAddress = executorAddress;
 	}
 
+	public String getExecutorHandler() {
+		return executorHandler;
+	}
+
+	public void setExecutorHandler(String executorHandler) {
+		this.executorHandler = executorHandler;
+	}
+
 	public String getExecutorParam() {
 		return executorParam;
 	}
@@ -154,12 +160,4 @@ public class XxlJobInfo {
 		this.jobStatus = jobStatus;
 	}
 
-	public String getJobKey() {
-		return jobGroup.concat("_").concat(jobName);
-	}
-
-	public void setJobKey(String jobKey) {
-		this.jobKey = jobKey;
-	}
-
 }

+ 25 - 26
xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobMonitorHelper.java

@@ -30,36 +30,35 @@ public class JobMonitorHelper {
 			@Override
 			public void run() {
 				while (true) {
-					logger.info(">>>>>>>>>>> job monitor run ... ");
-					Integer jobLogId = JobMonitorHelper.helper.queue.poll();
-					if (jobLogId != null && jobLogId > 0) {
-						XxlJobLog log = DynamicSchedulerUtil.xxlJobLogDao.load(jobLogId);
-						if (log!=null) {
-							if (RemoteCallBack.SUCCESS.equals(log.getTriggerStatus()) && StringUtils.isBlank(log.getHandleStatus())) {
-								try {
-									TimeUnit.SECONDS.sleep(10);
-								} catch (InterruptedException e) {
-									e.printStackTrace();
+					try {
+						logger.info(">>>>>>>>>>> job monitor beat ... ");
+						Integer jobLogId = JobMonitorHelper.helper.queue.take();
+						if (jobLogId != null && jobLogId > 0) {
+							logger.info(">>>>>>>>>>> job monitor heat success, JobLogId:{}", jobLogId);
+							XxlJobLog log = DynamicSchedulerUtil.xxlJobLogDao.load(jobLogId);
+							if (log!=null) {
+								if (RemoteCallBack.SUCCESS.equals(log.getTriggerStatus()) && StringUtils.isBlank(log.getHandleStatus())) {
+									try {
+										TimeUnit.SECONDS.sleep(10);
+									} catch (InterruptedException e) {
+										e.printStackTrace();
+									}
+									JobMonitorHelper.monitor(jobLogId);
 								}
-								JobMonitorHelper.monitor(jobLogId);
-							}
-							if (RemoteCallBack.SUCCESS.equals(log.getTriggerStatus()) && RemoteCallBack.SUCCESS.equals(log.getHandleStatus())) {
-								// pass
-							}
-							if (RemoteCallBack.FAIL.equals(log.getTriggerStatus()) || RemoteCallBack.FAIL.equals(log.getHandleStatus())) {
-								XxlJobInfo info = DynamicSchedulerUtil.xxlJobInfoDao.load(log.getJobGroup(), log.getJobName());
-								if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
-									MailUtil.sendMail(info.getAlarmEmail(), "《调度监控报警-调度平台平台XXL-JOB》",
-											MessageFormat.format("任务调度失败, JobKey={0}, 任务描述:{1}.", info.getJobKey(), info.getJobDesc()), false, null);
+								if (RemoteCallBack.SUCCESS.equals(log.getTriggerStatus()) && RemoteCallBack.SUCCESS.equals(log.getHandleStatus())) {
+									// pass
+								}
+								if (RemoteCallBack.FAIL.equals(log.getTriggerStatus()) || RemoteCallBack.FAIL.equals(log.getHandleStatus())) {
+									XxlJobInfo info = DynamicSchedulerUtil.xxlJobInfoDao.load(log.getJobGroup(), log.getJobName());
+									if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
+										MailUtil.sendMail(info.getAlarmEmail(), "《调度监控报警-调度平台平台XXL-JOB》",
+												MessageFormat.format("任务调度失败, 任务组:{0}, 任务描述:{1}.", info.getJobGroup(), info.getJobDesc()), false, null);
+									}
 								}
 							}
 						}
-					} else {
-						try {
-							TimeUnit.SECONDS.sleep(20);
-						} catch (InterruptedException e) {
-							e.printStackTrace();
-						}
+					} catch (Exception e) {
+						logger.error("job monitor error:{}", e);
 					}
 				}
 			}

+ 2 - 2
xxl-job-admin/src/main/java/com/xxl/job/admin/dao/IXxlJobInfoDao.java

@@ -12,8 +12,8 @@ import com.xxl.job.admin.core.model.XxlJobLog;
  */
 public interface IXxlJobInfoDao {
 
-	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String jobDesc);
-	public int pageListCount(int offset, int pagesize, String jobGroup, String jobDesc);
+	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String executorHandler);
+	public int pageListCount(int offset, int pagesize, String jobGroup, String executorHandler);
 	
 	public int save(XxlJobInfo info);
 	

+ 4 - 4
xxl-job-admin/src/main/java/com/xxl/job/admin/dao/impl/XxlJobInfoDaoImpl.java

@@ -23,23 +23,23 @@ public class XxlJobInfoDaoImpl implements IXxlJobInfoDao {
 	public SqlSessionTemplate sqlSessionTemplate;
 
 	@Override
-	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String jobDesc) {
+	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String executorHandler) {
 		HashMap<String, Object> params = new HashMap<String, Object>();
 		params.put("offset", offset);
 		params.put("pagesize", pagesize);
 		params.put("jobGroup", jobGroup);
-		params.put("jobDesc", jobDesc);
+		params.put("executorHandler", executorHandler);
 		
 		return sqlSessionTemplate.selectList("XxlJobInfoMapper.pageList", params);
 	}
 
 	@Override
-	public int pageListCount(int offset, int pagesize, String jobGroup, String jobDesc) {
+	public int pageListCount(int offset, int pagesize, String jobGroup, String executorHandler) {
 		HashMap<String, Object> params = new HashMap<String, Object>();
 		params.put("offset", offset);
 		params.put("pagesize", pagesize);
 		params.put("jobGroup", jobGroup);
-		params.put("jobDesc", jobDesc);
+		params.put("executorHandler", executorHandler);
 		
 		return sqlSessionTemplate.selectOne("XxlJobInfoMapper.pageListCount", params);
 	}

+ 5 - 6
xxl-job-admin/src/main/java/com/xxl/job/admin/service/IXxlJobService.java

@@ -11,14 +11,13 @@ import com.xxl.job.admin.core.model.ReturnT;
  */
 public interface IXxlJobService {
 	
-	public Map<String, Object> pageList(int start, int length, String jobGroup, String jobDesc, String filterTime);
+	public Map<String, Object> pageList(int start, int length, String jobGroup, String executorHandler, String filterTime);
 	
-	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc,
-			String executorAddress,	String executorParam, String author, String alarmEmail,
-			int glueSwitch, String glueSource, String glueRemark);
+	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc,String author, String alarmEmail,
+			String executorAddress,	String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark);
 	
-	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc,
-			String handler_address, String handler_params, String author, String alarmEmail);
+	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
+			String executorAddress, String executorHandler, String executorParam, int glueSwitch);
 	
 	public ReturnT<String> remove(String jobGroup, String jobName);
 	

+ 53 - 42
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java

@@ -1,18 +1,6 @@
 package com.xxl.job.admin.service.impl;
 
-import java.util.*;
-
-import javax.annotation.Resource;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.time.DateFormatUtils;
-import org.apache.commons.lang.time.FastDateFormat;
-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;
@@ -20,6 +8,19 @@ 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;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.time.FastDateFormat;
+import org.quartz.CronExpression;
+import org.quartz.SchedulerException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * core job service for xxl-job
@@ -27,6 +28,7 @@ import com.xxl.job.admin.service.IXxlJobService;
  */
 @Service
 public class XxlJobServiceImpl implements IXxlJobService {
+	private static Logger logger = LoggerFactory.getLogger(XxlJobServiceImpl.class);
 
 	@Resource
 	private IXxlJobInfoDao xxlJobInfoDao;
@@ -36,11 +38,11 @@ public class XxlJobServiceImpl implements IXxlJobService {
 	private IXxlJobLogGlueDao xxlJobLogGlueDao;
 	
 	@Override
-	public Map<String, Object> pageList(int start, int length, String jobGroup, String jobDesc, String filterTime) {
-		
+	public Map<String, Object> pageList(int start, int length, String jobGroup, String executorHandler, String filterTime) {
+
 		// page list
-		List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, jobDesc);
-		int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, jobDesc);
+		List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, executorHandler);
+		int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, executorHandler);
 		
 		// fill job info
 		if (list!=null && list.size()>0) {
@@ -58,9 +60,8 @@ public class XxlJobServiceImpl implements IXxlJobService {
 	}
 
 	@Override
-	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc,
-			String executorAddress,	String executorParam, String author, String alarmEmail,
-			int glueSwitch, String glueSource, String glueRemark) {
+	public ReturnT<String> add(String jobGroup, String jobCron, String jobDesc, String author, String alarmEmail,
+			String executorAddress,	String executorHandler, String executorParam, int glueSwitch, String glueSource, String glueRemark) {
 		// valid
 		if (JobGroupEnum.match(jobGroup) == null) {
 			return new ReturnT<String>(500, "请选择“任务组”");
@@ -71,15 +72,18 @@ public class XxlJobServiceImpl implements IXxlJobService {
 		if (StringUtils.isBlank(jobDesc)) {
 			return new ReturnT<String>(500, "请输入“任务描述”");
 		}
-		if (StringUtils.isBlank(executorAddress)) {
-			return new ReturnT<String>(500, "请输入“执行器地址”");
-		}
 		if (StringUtils.isBlank(author)) {
 			return new ReturnT<String>(500, "请输入“负责人”");
 		}
 		if (StringUtils.isBlank(alarmEmail)) {
 			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”");
+		}
 
 		// generate jobName
 		String jobName = FastDateFormat.getInstance("yyyyMMddHHmmssSSSS").format(new Date());
@@ -100,33 +104,32 @@ public class XxlJobServiceImpl implements IXxlJobService {
 		jobInfo.setJobDesc(jobDesc);
 		jobInfo.setAuthor(author);
 		jobInfo.setAlarmEmail(alarmEmail);
+		jobInfo.setExecutorAddress(executorAddress);
+		jobInfo.setExecutorHandler(executorHandler);
+		jobInfo.setExecutorParam(executorParam);
 		jobInfo.setGlueSwitch(glueSwitch);
 		jobInfo.setGlueSource(glueSource);
 		jobInfo.setGlueRemark(glueRemark);
-		jobInfo.setExecutorAddress(executorAddress);
-		jobInfo.setExecutorParam(executorParam);
-		xxlJobInfoDao.save(jobInfo);
 
 		try {
 			// add job 2 quartz
 			boolean result = DynamicSchedulerUtil.addJob(jobInfo);
 			if (result) {
+				xxlJobInfoDao.save(jobInfo);
 				return ReturnT.SUCCESS;
 			} else {
-				xxlJobInfoDao.delete(jobGroup, jobName);
 				return new ReturnT<String>(500, "新增任务失败");
 			}
 		} catch (SchedulerException e) {
-			e.printStackTrace();
+			logger.error("", e);
 		}
 		return ReturnT.FAIL;
 	}
 
 	@Override
-	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc,
-			String executorAddress, String executorParam,
-			String author, String alarmEmail) {
-		
+	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String author, String alarmEmail,
+			String executorAddress, String executorHandler, String executorParam, int glueSwitch) {
+
 		// valid
 		if (JobGroupEnum.match(jobGroup) == null) {
 			return new ReturnT<String>(500, "请选择“任务组”");
@@ -140,33 +143,41 @@ public class XxlJobServiceImpl implements IXxlJobService {
 		if (StringUtils.isBlank(jobDesc)) {
 			return new ReturnT<String>(500, "请输入“任务描述”");
 		}
-		if (StringUtils.isBlank(executorAddress)) {
-			return new ReturnT<String>(500, "请输入“执行器地址”");
-		}
 		if (StringUtils.isBlank(author)) {
 			return new ReturnT<String>(500, "请输入“负责人”");
 		}
 		if (StringUtils.isBlank(alarmEmail)) {
 			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”");
+		}
+
+		// stage job info
 		XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName);
-		jobInfo.setJobDesc(jobDesc);
 		jobInfo.setJobCron(jobCron);
+		jobInfo.setJobDesc(jobDesc);
 		jobInfo.setAuthor(author);
 		jobInfo.setAlarmEmail(alarmEmail);
 		jobInfo.setExecutorAddress(executorAddress);
+		jobInfo.setExecutorHandler(executorHandler);
 		jobInfo.setExecutorParam(executorParam);
+		jobInfo.setGlueSwitch(glueSwitch);
 		
 		try {
 			// fresh quartz
-			DynamicSchedulerUtil.rescheduleJob(jobInfo);
-			
-			// fresh db
-			xxlJobInfoDao.update(jobInfo);
-			return ReturnT.SUCCESS;
+			boolean ret = DynamicSchedulerUtil.rescheduleJob(jobInfo);
+			if (ret) {
+				xxlJobInfoDao.update(jobInfo);
+				return ReturnT.SUCCESS;
+			} else {
+				return new ReturnT<String>(500, "更新任务失败");
+			}
 		} catch (SchedulerException e) {
-			e.printStackTrace();
+			logger.error("", e);
 		}
 		return ReturnT.FAIL;
 	}

+ 9 - 4
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml

@@ -18,6 +18,7 @@
 	    <result column="alarm_email" property="alarmEmail" />
 	    
 	    <result column="executor_address" property="executorAddress" />
+		<result column="executor_handler" property="executorHandler" />
 	    <result column="executor_param" property="executorParam" />
 	    
 	    <result column="glue_switch" property="glueSwitch" />
@@ -36,6 +37,7 @@
 		t.author,
 		t.alarm_email,
 		t.executor_address,
+		t.executor_handler,
 		t.executor_param,
 		t.glue_switch,
 		t.glue_source,
@@ -49,8 +51,8 @@
 			<if test="jobGroup != null and jobGroup != ''">
 				AND t.job_group = #{jobGroup}
 			</if>
-			<if test="jobDesc != null and jobDesc != ''">
-				AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')
+			<if test="executorHandler != null and executorHandler != ''">
+				AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')
 			</if>
 		</trim>
 		ORDER BY id DESC
@@ -64,8 +66,8 @@
 			<if test="jobGroup != null and jobGroup != ''">
 				AND t.job_group = #{jobGroup}
 			</if>
-			<if test="jobDesc != null and jobDesc != ''">
-				AND t.job_desc like CONCAT(CONCAT('%', #{jobDesc}), '%')
+			<if test="executorHandler != null and executorHandler != ''">
+				AND t.executor_handler like CONCAT(CONCAT('%', #{executorHandler}), '%')
 			</if>
 		</trim>
 	</select>
@@ -81,6 +83,7 @@
 			author,
 			alarm_email,
 			executor_address,
+			executor_handler,
 			executor_param,
 			glue_switch,
 			glue_source,
@@ -95,6 +98,7 @@
 			#{author},
 			#{alarmEmail},
 			#{executorAddress},
+			#{executorHandler},
 			#{executorParam},
 			#{glueSwitch},
 			#{glueSource},
@@ -121,6 +125,7 @@
 			author = #{author},
 			alarm_email = #{alarmEmail},
 			executor_address = #{executorAddress},
+			executor_handler = #{executorHandler},
 			executor_param = #{executorParam},
 			glue_switch = #{glueSwitch},
 			glue_source = #{glueSource},

+ 26 - 31
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl

@@ -38,7 +38,7 @@
 	    <section class="content">
 	    
 	    	<div class="row">
-	    		<div class="col-xs-2">
+	    		<div class="col-xs-4">
 	              	<div class="input-group">
 	                	<span class="input-group-addon">分组</span>
                 		<select class="form-control" id="jobGroup" >
@@ -48,18 +48,12 @@
 	                  	</select>
 	              	</div>
 	            </div>
-                <div class="col-xs-3">
+                <div class="col-xs-4">
                     <div class="input-group">
-                        <span class="input-group-addon">JobKey</span>
-                        <input type="text" class="form-control" id="JobKey" value="${jobName}" autocomplete="on" >
+                        <span class="input-group-addon">JobHandler</span>
+                        <input type="text" class="form-control" id="executorHandler" value="${jobName}" autocomplete="on" >
                     </div>
                 </div>
-	            <div class="col-xs-3">
-	              	<div class="input-group">
-	                	<span class="input-group-addon">描述</span>
-	                	<input type="text" class="form-control" id="jobDesc" value="${jobName}" autocomplete="on" >
-	              	</div>
-	            </div>
 	            <div class="col-xs-2">
 	            	<button class="btn btn-block btn-info" id="searchBtn">搜索</button>
 	            </div>
@@ -81,10 +75,10 @@
 					            		<th name="id" >id</th>
 					                	<th name="jobGroup" >jobGroup</th>
 					                  	<th name="jobName" >jobName</th>
-                                        <th name="JobKey" >JobKey</th>
 					                  	<th name="jobDesc" >描述</th>
 					                  	<th name="jobCron" >Cron</th>
 					                  	<th name="executorAddress" >执行器地址</th>
+                                        <th name="executorHandler" >JobJandler</th>
 					                  	<th name="executorParam" >任务参数</th>
 					                  	<th name="addTime" >新增时间</th>
 					                  	<th name="updateTime" >更新时间</th>
@@ -137,15 +131,16 @@
                         <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div>
 					</div>
 					<div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
-                        <label for="firstname" class="col-sm-2 control-label">任务模式<font color="red">*</font></label>
+                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
                         <div class="col-sm-4">
-                            <select class="form-control" name="glueSwitch" >
-                                <option value="0" >BEAN模式</option>
-                                <option value="1" >GLUE模式</option>
-                            </select>
-                        </div>
+                            <div class="input-group">
+								<input type="text" class="form-control" name="executorHandler" placeholder="请输入“JobHandler”" maxlength="100" >
+								<span class="input-group-addon"><b>GLUE</b>&nbsp;<input type="checkbox" class="ifGLUE" ></span>
+                                <input type="hidden" name="glueSwitch" value="0" >
+                            </div>
+						</div>
+						<label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
 					</div>
 					<div class="form-group">
 						<label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
@@ -212,15 +207,19 @@ public class DemoJobHandler extends IJobHandler {
                         <label for="lastname" class="col-sm-2 control-label">Cron<font color="red">*</font></label>
                         <div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Cron”" maxlength="20" ></div>
 					</div>
-					
-					<div class="form-group">
-                        <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
-                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
-                        <label for="firstname" class="col-sm-2 control-label">任务模式<font color="red">*</font></label>
+                    <div class="form-group">
+                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
                         <div class="col-sm-4">
-                            <input type="text" class="form-control glueSwitchTitle" readonly >
+                            <div class="input-group">
+                                <input type="text" class="form-control" name="executorHandler" placeholder="请输入“JobHandler”" maxlength="100" >
+                                <span class="input-group-addon"><b>GLUE</b>&nbsp;<input type="checkbox" class="ifGLUE" ></span>
+                                <input type="hidden" name="glueSwitch" value="0" >
+                            </div>
                         </div>
-					</div>
+                        <label for="firstname" class="col-sm-2 control-label">执行参数<font color="black">*</font></label>
+                        <div class="col-sm-4"><input type="text" class="form-control" name="executorParam" placeholder="请输入“执行参数”" maxlength="100" ></div>
+                    </div>
+
 					<div class="form-group">
 						<label for="lastname" class="col-sm-2 control-label">报警邮件<font color="red">*</font></label>
 						<div class="col-sm-4"><input type="text" class="form-control" name="alarmEmail" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="100" ></div>
@@ -229,16 +228,12 @@ public class DemoJobHandler extends IJobHandler {
 					</div>
 					<hr>
 					<div class="form-group">
-						<div class="col-sm-offset-3 col-sm-3">
+                        <div class="col-sm-offset-3 col-sm-6">
 							<button type="submit" class="btn btn-primary"  >保存</button>
 							<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                             <input type="hidden" name="jobGroup" >
                             <input type="hidden" name="jobName" >
 						</div>
-                        <label for="firstname" class="col-sm-2 control-label">JobKey</label>
-                        <div class="col-sm-4">
-                            <input type="text" class="form-control jobKey" readonly >
-                        </div>
 					</div>
 				</form>
          	</div>

+ 69 - 48
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js

@@ -10,7 +10,7 @@ $(function() {
 	        data : function ( d ) {
 	        	var obj = {};
 	        	obj.jobGroup = $('#jobGroup').val();
-	        	obj.jobDesc = $('#jobDesc').val();
+	        	obj.executorHandler = $('#executorHandler').val();
 	        	obj.start = d.start;
 	        	obj.length = d.length;
                 return obj;
@@ -35,10 +35,10 @@ $(function() {
 	            		}
             		},
 					{ "data": 'jobName', "visible" : false},
-					{ "data": 'jobKey', "visible" : true},
 	                { "data": 'jobDesc', "visible" : true},
 	                { "data": 'jobCron', "visible" : true},
 	                { "data": 'executorAddress', "visible" : false},
+					{ "data": 'executorHandler', "visible" : false},
 	                { "data": 'executorParam', "visible" : false},
 	                { 
 	                	"data": 'addTime', 
@@ -87,33 +87,33 @@ $(function() {
 	                			// log url
 	                			var codeBtn = "";
 	                			if(row.glueSwitch > 0){
-	                				var codeUrl = base_url +'/jobcode?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName;
-	                				codeBtn = '<button class="btn btn-warning btn-xs" type="button" onclick="javascript:window.open(\'' + codeUrl + '\')" >GLUE</button>  '
-	                			}
+									var codeUrl = base_url +'/jobcode?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName;
+									codeBtn = '<button class="btn btn-warning btn-xs" type="button" onclick="javascript:window.open(\'' + codeUrl + '\')" >GLUE</button>  '
+								}
 
-	                			var html = '<p id="'+ row.id +'" '+
-	                							' jobGroup="'+ row.jobGroup +'" '+
-	                							' jobName="'+ row.jobName +'" '+
-												' jobKey="'+ row.jobKey +'" '+
-	                							' jobCron="'+ row.jobCron +'" '+
-	                							' jobDesc="'+ row.jobDesc +'" '+
-	                							' executorAddress="'+row.executorAddress +'" '+
-	                							' executorParam="'+ row.executorParam +'" '+
-	                							' author="'+ row.author +'" '+
-	                							' alarmEmail="'+ row.alarmEmail +'" '+
-	                							' glueSwitch="'+ row.glueSwitch +'" '+
-	                							'>'+
-										'<button class="btn btn-primary btn-xs job_operate" type="job_trigger" type="button">执行</button>  '+
-										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>  '+
-										codeBtn +
-								  		'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>  '+
+								// html
+								var html = '<p id="'+ row.id +'" '+
+									' jobGroup="'+ row.jobGroup +'" '+
+									' jobName="'+ row.jobName +'" '+
+									' jobCron="'+ row.jobCron +'" '+
+									' jobDesc="'+ row.jobDesc +'" '+
+									' author="'+ row.author +'" '+
+									' alarmEmail="'+ row.alarmEmail +'" '+
+									' executorAddress="'+row.executorAddress +'" '+
+									' executorHandler="'+row.executorHandler +'" '+
+									' executorParam="'+ row.executorParam +'" '+
+									' glueSwitch="'+ row.glueSwitch +'" '+
+									'>'+
+									'<button class="btn btn-primary btn-xs job_operate" type="job_trigger" type="button">执行</button>  '+
+									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>  '+
+									codeBtn +
+									'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>  '+
 									'</p>';
-									
-	                			
+
 	                			return html;
-	                		};
+							};
 	                	}
 	                }
 	            ],
@@ -221,6 +221,9 @@ $(function() {
             executorAddress : {
             	required : true
             },
+			executorHandler : {
+				required : false
+			},
             alarmEmail : {
             	required : true
             },
@@ -238,6 +241,9 @@ $(function() {
             executorAddress : {
             	required :"请输入“执行器地址”."
             },
+			executorHandler : {
+				required : "请输入“jobHandler”."
+			},
             alarmEmail : {
             	required : "请输入“报警邮件”."
             },
@@ -277,6 +283,21 @@ $(function() {
 		$("#addModal .form .form-group").removeClass("has-error");
 		$(".remote_panel").show();	// remote
 	});
+
+	// GLUE模式开启
+	$(".ifGLUE").click(function(){
+		var ifGLUE = $(this).is(':checked');
+		var $executorHandler = $(this).parents("form").find("input[name='executorHandler']");
+		var $glueSwitch = $(this).parents("form").find("input[name='glueSwitch']");
+		if (ifGLUE) {
+			$executorHandler.val("");
+			$executorHandler.attr("readonly","readonly");
+			$glueSwitch.val(1);
+		} else {
+			$executorHandler.removeAttr("readonly");
+			$glueSwitch.val(0);
+		}
+	});
 	
 	// 更新
 	$("#job_list").on('click', '.update',function() {
@@ -284,20 +305,31 @@ $(function() {
 		// base data
 		$("#updateModal .form input[name='jobGroup']").val($(this).parent('p').attr("jobGroup"));
 		$("#updateModal .form input[name='jobName']").val($(this).parent('p').attr("jobName"));
-		$("#updateModal .form .jobKey").val( $(this).parent('p').attr("jobKey") );
 		$("#updateModal .form input[name='jobDesc']").val($(this).parent('p').attr("jobDesc"));
 		$("#updateModal .form input[name='jobCron']").val($(this).parent('p').attr("jobCron"));
-		$("#updateModal .form input[name='executorAddress']").val($(this).parent('p').attr("executorAddress"));
-		$("#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='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"));
 
 		// jobGroupTitle
 		var jobGroupTitle = $("#addModal .form select[name='jobGroup']").find("option[value='" + $(this).parent('p').attr("jobGroup") + "']").text();
 		$("#updateModal .form .jobGroupTitle").val(jobGroupTitle);
 
-        // glueSwitchTitle
-		$("#updateModal .form .glueSwitchTitle").val( ($(this).parent('p').attr("glueSwitch") == 0)?"BEAN模式":"GLUE模式" );
+        // glueSwitch
+		var glueSwitch = $(this).parent('p').attr("glueSwitch");
+		$("#updateModal .form input[name='glueSwitch']").val(glueSwitch);
+		var $ifGLUE = $("#updateModal .form .ifGLUE");
+		var $executorHandler = $("#updateModal .form input[name='executorHandler']");
+		if (glueSwitch == 1) {
+			$ifGLUE.attr("checked", true);
+			$executorHandler.val("");
+			$executorHandler.attr("readonly","readonly");
+		} else {
+			$ifGLUE.attr("checked", false);
+			$executorHandler.removeAttr("readonly");
+		}
 
 		// show
 		$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');
@@ -318,6 +350,9 @@ $(function() {
 			executorAddress : {
 				required : true
 			},
+			executorHandler : {
+				required : false
+			},
 			alarmEmail : {
 				required : true
 			},
@@ -335,6 +370,9 @@ $(function() {
 			executorAddress : {
 				required :"请输入“执行器地址”."
 			},
+			executorHandler : {
+				required : "请输入“jobHandler”."
+			},
 			alarmEmail : {
 				required : "请输入“报警邮件”."
 			},
@@ -353,7 +391,6 @@ $(function() {
             element.parent('div').append(error);  
         },
         submitHandler : function(form) {
-
 			// post
     		$.post(base_url + "/jobinfo/reschedule", $("#updateModal .form").serialize(), function(data, status) {
     			if (data.code == "200") {
@@ -374,22 +411,6 @@ $(function() {
 		$("#updateModal .form")[0].reset()
 	});
 
-	// GLUE模式开启
-	/*
-	 $("#addModal .form .ifGLUE").click(function(){
-         var ifGLUE = $(this).is(':checked');
-         var $executorHandler = $("#addModal .form input[name='executorHandler']");
-         var $glueSwitch = $("#addModal .form input[name='glueSwitch']");
-         if (ifGLUE) {
-         $executorHandler.val("");
-         $executorHandler.attr("readonly","readonly");
-         $glueSwitch.val(1);
-         } else {
-         $executorHandler.removeAttr("readonly");
-         $glueSwitch.val(0);
-         }
-	 });
-	 */
 
 	/*
 	// 新增-添加参数

+ 1 - 0
xxl-job-core/src/main/java/com/xxl/job/core/handler/HandlerThread.java

@@ -56,6 +56,7 @@ public class HandlerThread extends Thread{
 	public void run() {
 		while(!toStop){
 			try {
+				// to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout)
 				Map<String, String> handlerData = handlerDataQueue.poll(3L, TimeUnit.SECONDS);
 				if (handlerData!=null) {
 					i= 0;