xueli.xue 10 лет назад
Родитель
Сommit
554429ea59
19 измененных файлов: 571 добавлений и 547 удалений
  1. 113 97
      xxl-job-admin/src/main/java/com/xxl/job/controller/JobInfoController.java
  2. 5 3
      xxl-job-admin/src/main/java/com/xxl/job/controller/JobLogController.java
  3. 20 11
      xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobInfo.java
  4. 10 4
      xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobLog.java
  5. 76 52
      xxl-job-admin/src/main/java/com/xxl/job/core/util/DynamicSchedulerUtil.java
  6. 4 5
      xxl-job-admin/src/main/java/com/xxl/job/dao/IXxlJobInfoDao.java
  7. 16 11
      xxl-job-admin/src/main/java/com/xxl/job/dao/impl/XxlJobInfoDaoImpl.java
  8. 22 22
      xxl-job-admin/src/main/java/com/xxl/job/service/job/HttpJobBean.java
  9. 57 31
      xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml
  10. 5 1
      xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml
  11. 47 67
      xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl
  12. 2 1
      xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl
  13. 160 105
      xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
  14. 1 0
      xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js
  15. 4 4
      xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobInfoTest.java
  16. 2 2
      xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobLogTest.java
  17. 3 4
      xxl-job-client-demo/src/main/java/com/xxl/job/service/handler/DemoJobHandler.java
  18. 23 124
      xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerRepository.java
  19. 1 3
      xxl-job-client/src/main/java/com/xxl/job/client/handler/IJobHandler.java

+ 113 - 97
xxl-job-admin/src/main/java/com/xxl/job/controller/JobInfoController.java Просмотреть файл

1
 package com.xxl.job.controller;
1
 package com.xxl.job.controller;
2
 
2
 
3
-import java.io.UnsupportedEncodingException;
3
+import java.util.ArrayList;
4
 import java.util.HashMap;
4
 import java.util.HashMap;
5
 import java.util.List;
5
 import java.util.List;
6
 import java.util.Map;
6
 import java.util.Map;
7
-import java.util.Map.Entry;
8
-import java.util.Set;
9
 
7
 
10
 import javax.annotation.Resource;
8
 import javax.annotation.Resource;
11
-import javax.servlet.http.HttpServletRequest;
12
 
9
 
13
 import org.apache.commons.lang.StringUtils;
10
 import org.apache.commons.lang.StringUtils;
14
 import org.quartz.CronExpression;
11
 import org.quartz.CronExpression;
28
 import com.xxl.job.core.util.DynamicSchedulerUtil;
25
 import com.xxl.job.core.util.DynamicSchedulerUtil;
29
 import com.xxl.job.dao.IXxlJobInfoDao;
26
 import com.xxl.job.dao.IXxlJobInfoDao;
30
 import com.xxl.job.service.job.HttpJobBean;
27
 import com.xxl.job.service.job.HttpJobBean;
28
+import com.xxl.job.service.job.LocalJobBean;
29
+import com.xxl.job.service.job.LocalJobBeanB;
31
 
30
 
32
 /**
31
 /**
33
  * index controller
32
  * index controller
40
 	@Resource
39
 	@Resource
41
 	private IXxlJobInfoDao xxlJobInfoDao;
40
 	private IXxlJobInfoDao xxlJobInfoDao;
42
 	
41
 	
42
+	// remote job bean
43
+	public static Class <? extends Job> remoteJobBean = HttpJobBean.class;
44
+	// loacal job bean
45
+	public static List<Class <? extends Job>> localJobBeanList = new ArrayList<Class<? extends Job>>();
46
+	static{
47
+		localJobBeanList.add(LocalJobBean.class);
48
+		localJobBeanList.add(LocalJobBeanB.class);
49
+	}
50
+	
43
 	@RequestMapping
51
 	@RequestMapping
44
 	public String index(Model model) {
52
 	public String index(Model model) {
45
-		model.addAttribute("JobGroupList", JobGroupEnum.values());
53
+		model.addAttribute("localJobBeanList", localJobBeanList);			// 本地任务-列表
54
+		model.addAttribute("remoteJobBean", remoteJobBean);	// 远程任务-jobBean
55
+		model.addAttribute("JobGroupList", JobGroupEnum.values());			// 任务组列表
46
 		return "jobinfo/index";
56
 		return "jobinfo/index";
47
 	}
57
 	}
48
 	
58
 	
50
 	@ResponseBody
60
 	@ResponseBody
51
 	public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,  
61
 	public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,  
52
 			@RequestParam(required = false, defaultValue = "10") int length,
62
 			@RequestParam(required = false, defaultValue = "10") int length,
53
-			String jobName, String filterTime) {
63
+			String jobGroup, String jobName, String filterTime) {
54
 		
64
 		
55
 		// page list
65
 		// page list
56
-		List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobName, null, null);
57
-		int list_count = xxlJobInfoDao.pageListCount(start, length, jobName, null, null);
66
+		List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, jobName);
67
+		int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, jobName);
58
 		
68
 		
59
 		// fill job info
69
 		// fill job info
60
 		if (list!=null && list.size()>0) {
70
 		if (list!=null && list.size()>0) {
71
 		return maps;
81
 		return maps;
72
 	}
82
 	}
73
 	
83
 	
84
+	@SuppressWarnings("unchecked")
74
 	@RequestMapping("/add")
85
 	@RequestMapping("/add")
75
 	@ResponseBody
86
 	@ResponseBody
76
-	public ReturnT<String> add(HttpServletRequest request) {
77
-		String triggerKeyName = null;
78
-		String cronExpression = null;
79
-		Map<String, String> jobData = new HashMap<String, String>();
87
+	public ReturnT<String> add(String jobGroup, String jobName, String jobCron, String jobDesc, String jobClass,
88
+			String handler_params, String handler_address, String handler_name, 
89
+			String author, String alarm_email, int alarm_threshold) {
80
 		
90
 		
91
+		// valid
92
+		if (JobGroupEnum.match(jobGroup) == null) {
93
+			return new ReturnT<String>(500, "请选择“任务组”");
94
+		}
95
+		if (StringUtils.isBlank(jobName)) {
96
+			return new ReturnT<String>(500, "请输入“任务名”");
97
+		}
98
+		if (!CronExpression.isValidExpression(jobCron)) {
99
+			return new ReturnT<String>(500, "“corn”不合法");
100
+		}
101
+		if (StringUtils.isBlank(jobDesc)) {
102
+			return new ReturnT<String>(500, "请输入“任务描述”");
103
+		}
104
+		Class<? extends Job> jobClass_ = null;
81
 		try {
105
 		try {
82
-			request.setCharacterEncoding("utf-8");
83
-		} catch (UnsupportedEncodingException e1) {
106
+			Class<?> clazz = Class.forName(jobClass);
107
+			if (clazz!=null) {
108
+				jobClass_ = (Class<? extends Job>) clazz;
109
+			}
110
+		} catch (ClassNotFoundException e1) {
84
 			e1.printStackTrace();
111
 			e1.printStackTrace();
85
 		}
112
 		}
86
-		@SuppressWarnings("unchecked")
87
-		Set<Map.Entry<String, String[]>> paramSet = request.getParameterMap().entrySet();
88
-		for (Entry<String, String[]> param : paramSet) {
89
-			if (param.getKey().equals("triggerKeyName")) {
90
-				triggerKeyName = param.getValue()[0];
91
-			} else if (param.getKey().equals("cronExpression")) {
92
-				cronExpression = param.getValue()[0];
93
-			} else {
94
-				jobData.put(param.getKey(), (String) (param.getValue().length>0?param.getValue()[0]:param.getValue()));
95
-			}
113
+		if (jobClass_ == null) {
114
+			return new ReturnT<String>(500, "请选择“JobBean”");
96
 		}
115
 		}
97
-		
98
-		// triggerKeyName
99
-		if (StringUtils.isBlank(triggerKeyName)) {
100
-			return new ReturnT<String>(500, "请输入“任务key”");
116
+		if (jobClass_.getClass().getName().equals(remoteJobBean.getName())) {
117
+			if (StringUtils.isBlank(handler_address)) {
118
+				return new ReturnT<String>(500, "请输入“远程-机器地址”");
119
+			}
120
+			if (StringUtils.isBlank(handler_name)) {
121
+				return new ReturnT<String>(500, "请输入“远程-执行器”");
122
+			}
101
 		}
123
 		}
102
-		
103
-		// cronExpression
104
-		if (StringUtils.isBlank(cronExpression)) {
105
-			return new ReturnT<String>(500, "请输入“任务corn”");
124
+		if (StringUtils.isBlank(author)) {
125
+			return new ReturnT<String>(500, "请输入“负责人”");
106
 		}
126
 		}
107
-		if (!CronExpression.isValidExpression(cronExpression)) {
108
-			return new ReturnT<String>(500, "“任务corn”不合法");
127
+		if (StringUtils.isBlank(alarm_email)) {
128
+			return new ReturnT<String>(500, "请输入“报警邮件”");
109
 		}
129
 		}
110
 		
130
 		
111
-		// jobData
112
-		if (jobData.get(HandlerRepository.job_desc)==null || jobData.get(HandlerRepository.job_desc).toString().trim().length()==0) {
113
-			return new ReturnT<String>(500, "请输入“任务描述”");
114
-		}
115
-		if (jobData.get(HandlerRepository.job_url)==null || jobData.get(HandlerRepository.job_url).toString().trim().length()==0) {
116
-			return new ReturnT<String>(500, "请输入“任务URL”");
117
-		}
118
-		if (jobData.get(HandlerRepository.handleName)==null || jobData.get(HandlerRepository.handleName).toString().trim().length()==0) {
119
-			return new ReturnT<String>(500, "请输入“任务handler”");
131
+		try {
132
+			if (DynamicSchedulerUtil.checkExists(jobName, jobGroup)) {
133
+				return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
134
+			}
135
+		} catch (SchedulerException e1) {
136
+			e1.printStackTrace();
137
+			return new ReturnT<String>(500, "此任务已存在,请更换任务组或任务名");
120
 		}
138
 		}
121
 		
139
 		
122
-		// jobClass
123
-		Class<? extends Job> jobClass = HttpJobBean.class;
140
+		HashMap<String, String> jobDataMap = new HashMap<String, String>();
141
+		jobDataMap.put(HandlerRepository.HANDLER_PARAMS, handler_params);
142
+		jobDataMap.put(HandlerRepository.HANDLER_ADDRESS, handler_address);
143
+		jobDataMap.put(HandlerRepository.HANDLER_NAME, handler_name);
144
+		
145
+		// Backup to the database
146
+		XxlJobInfo jobInfo = new XxlJobInfo();
147
+		jobInfo.setJobGroup(jobGroup);
148
+		jobInfo.setJobName(jobName);
149
+		jobInfo.setJobCron(jobCron);
150
+		jobInfo.setJobDesc(jobDesc);
151
+		jobInfo.setJobClass(jobClass);
152
+		jobInfo.setJobData(JacksonUtil.writeValueAsString(jobDataMap));
153
+		jobInfo.setAuthor(author);
154
+		jobInfo.setAlarmEmail(alarm_email);
155
+		jobInfo.setAlarmThreshold(alarm_threshold);
156
+		xxlJobInfoDao.save(jobInfo);
124
 		
157
 		
125
 		try {
158
 		try {
126
 			// add job 2 quartz
159
 			// add job 2 quartz
127
-			boolean result = DynamicSchedulerUtil.addJob(triggerKeyName, cronExpression, jobClass, null);
128
-			if (!result) {
129
-				return new ReturnT<String>(500, "任务ID重复,请更换确认");
160
+			boolean result = DynamicSchedulerUtil.addJob(jobInfo);
161
+			if (result) {
162
+				return ReturnT.SUCCESS;
163
+			} else {
164
+				xxlJobInfoDao.delete(jobGroup, jobName);
165
+				return new ReturnT<String>(500, "新增任务失败");
130
 			}
166
 			}
131
-			// Backup to the database
132
-			XxlJobInfo jobInfo = new XxlJobInfo();
133
-			jobInfo.setJobName(triggerKeyName);
134
-			jobInfo.setJobCron(cronExpression);
135
-			jobInfo.setJobClass(jobClass.getName());
136
-			jobInfo.setJobData(JacksonUtil.writeValueAsString(jobData));
137
-			xxlJobInfoDao.save(jobInfo);
138
-			
139
-			return ReturnT.SUCCESS;
140
 		} catch (SchedulerException e) {
167
 		} catch (SchedulerException e) {
141
 			e.printStackTrace();
168
 			e.printStackTrace();
142
 		}
169
 		}
145
 	
172
 	
146
 	@RequestMapping("/reschedule")
173
 	@RequestMapping("/reschedule")
147
 	@ResponseBody
174
 	@ResponseBody
148
-	public ReturnT<String> reschedule(String triggerKeyName, String cronExpression) {
149
-		// triggerKeyName
150
-		if (StringUtils.isBlank(triggerKeyName)) {
151
-			return new ReturnT<String>(500, "请输入“任务key”");
175
+	public ReturnT<String> reschedule(String jobGroup, String jobName, String jobCron, String jobDesc, String jobClass,
176
+			String handler_params, String handler_address, String handler_name, 
177
+			String author, String alarm_email, int alarm_threshold) {
178
+		
179
+		// valid
180
+		if (JobGroupEnum.match(jobGroup) == null) {
181
+			return new ReturnT<String>(500, "请选择“任务组”");
152
 		}
182
 		}
153
-		// cronExpression
154
-		if (StringUtils.isBlank(cronExpression)) {
155
-			return new ReturnT<String>(500, "请输入“任务corn”");
183
+		if (StringUtils.isBlank(jobName)) {
184
+			return new ReturnT<String>(500, "请输入“任务名”");
156
 		}
185
 		}
157
-		if (!CronExpression.isValidExpression(cronExpression)) {
158
-			return new ReturnT<String>(500, "“任务corn”不合法");
186
+		if (!CronExpression.isValidExpression(jobCron)) {
187
+			return new ReturnT<String>(500, "“corn”不合法");
159
 		}
188
 		}
189
+		
190
+		XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName);
191
+		jobInfo.setJobCron(jobCron);
192
+		
160
 		try {
193
 		try {
161
-			DynamicSchedulerUtil.rescheduleJob(triggerKeyName, cronExpression);
194
+			// fresh quartz
195
+			DynamicSchedulerUtil.rescheduleJob(jobInfo);
162
 			
196
 			
163
-			// update
164
-			XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName);
165
-			if (jobInfo!=null) {
166
-				jobInfo.setJobCron(cronExpression);
167
-				xxlJobInfoDao.update(jobInfo);
168
-			}
197
+			// fresh db
198
+			xxlJobInfoDao.update(jobInfo);
169
 			return ReturnT.SUCCESS;
199
 			return ReturnT.SUCCESS;
170
 		} catch (SchedulerException e) {
200
 		} catch (SchedulerException e) {
171
 			e.printStackTrace();
201
 			e.printStackTrace();
175
 	
205
 	
176
 	@RequestMapping("/remove")
206
 	@RequestMapping("/remove")
177
 	@ResponseBody
207
 	@ResponseBody
178
-	public ReturnT<String> remove(String triggerKeyName) {
208
+	public ReturnT<String> remove(String jobGroup, String jobName) {
179
 		try {
209
 		try {
180
-			if (triggerKeyName!=null) {
181
-				DynamicSchedulerUtil.removeJob(triggerKeyName);
182
-				xxlJobInfoDao.delete(triggerKeyName);
183
-				return ReturnT.SUCCESS;
184
-			}
210
+			DynamicSchedulerUtil.removeJob(jobName, jobGroup);
211
+			xxlJobInfoDao.delete(jobGroup, jobName);
212
+			return ReturnT.SUCCESS;
185
 		} catch (SchedulerException e) {
213
 		} catch (SchedulerException e) {
186
 			e.printStackTrace();
214
 			e.printStackTrace();
187
 		}
215
 		}
190
 	
218
 	
191
 	@RequestMapping("/pause")
219
 	@RequestMapping("/pause")
192
 	@ResponseBody
220
 	@ResponseBody
193
-	public ReturnT<String> pause(String triggerKeyName) {
221
+	public ReturnT<String> pause(String jobGroup, String jobName) {
194
 		try {
222
 		try {
195
-			DynamicSchedulerUtil.pauseJob(triggerKeyName);
196
-			// update
197
-			XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName);
198
-			if (jobInfo!=null) {
199
-				jobInfo.setJobStatus("PAUSED");
200
-				xxlJobInfoDao.update(jobInfo);
201
-			}
223
+			DynamicSchedulerUtil.pauseJob(jobName, jobGroup);	// jobStatus do not store
202
 			return ReturnT.SUCCESS;
224
 			return ReturnT.SUCCESS;
203
 		} catch (SchedulerException e) {
225
 		} catch (SchedulerException e) {
204
 			e.printStackTrace();
226
 			e.printStackTrace();
208
 	
230
 	
209
 	@RequestMapping("/resume")
231
 	@RequestMapping("/resume")
210
 	@ResponseBody
232
 	@ResponseBody
211
-	public ReturnT<String> resume(String triggerKeyName) {
233
+	public ReturnT<String> resume(String jobGroup, String jobName) {
212
 		try {
234
 		try {
213
-			DynamicSchedulerUtil.resumeJob(triggerKeyName);
214
-			// update
215
-			XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName);
216
-			if (jobInfo!=null) {
217
-				jobInfo.setJobStatus("NORMAL");
218
-				xxlJobInfoDao.update(jobInfo);
219
-			}
235
+			DynamicSchedulerUtil.resumeJob(jobName, jobGroup);
220
 			return ReturnT.SUCCESS;
236
 			return ReturnT.SUCCESS;
221
 		} catch (SchedulerException e) {
237
 		} catch (SchedulerException e) {
222
 			e.printStackTrace();
238
 			e.printStackTrace();
226
 	
242
 	
227
 	@RequestMapping("/trigger")
243
 	@RequestMapping("/trigger")
228
 	@ResponseBody
244
 	@ResponseBody
229
-	public ReturnT<String> triggerJob(String triggerKeyName) {
245
+	public ReturnT<String> triggerJob(String jobGroup, String jobName) {
230
 		try {
246
 		try {
231
-			DynamicSchedulerUtil.triggerJob(triggerKeyName);
247
+			DynamicSchedulerUtil.triggerJob(jobName, jobGroup);
232
 			return ReturnT.SUCCESS;
248
 			return ReturnT.SUCCESS;
233
 		} catch (SchedulerException e) {
249
 		} catch (SchedulerException e) {
234
 			e.printStackTrace();
250
 			e.printStackTrace();

+ 5 - 3
xxl-job-admin/src/main/java/com/xxl/job/controller/JobLogController.java Просмотреть файл

33
 	public IXxlJobLogDao xxlJobLogDao;
33
 	public IXxlJobLogDao xxlJobLogDao;
34
 	
34
 	
35
 	@RequestMapping
35
 	@RequestMapping
36
-	public String index(Model model) {
36
+	public String index(Model model, String jobGroup, String jobName) {
37
+		model.addAttribute("jobGroup", jobGroup);
38
+		model.addAttribute("jobName", jobName);
37
 		model.addAttribute("JobGroupList", JobGroupEnum.values());
39
 		model.addAttribute("JobGroupList", JobGroupEnum.values());
38
 		return "joblog/index";
40
 		return "joblog/index";
39
 	}
41
 	}
71
 	
73
 	
72
 	@RequestMapping("/save")
74
 	@RequestMapping("/save")
73
 	@ResponseBody
75
 	@ResponseBody
74
-	public ReturnT<String> triggerLog(int triggerLogId, String status, String msg) {
75
-		XxlJobLog log = xxlJobLogDao.load(triggerLogId);
76
+	public ReturnT<String> triggerLog(int trigger_log_id, String status, String msg) {
77
+		XxlJobLog log = xxlJobLogDao.load(trigger_log_id);
76
 		if (log!=null) {
78
 		if (log!=null) {
77
 			log.setHandleTime(new Date());
79
 			log.setHandleTime(new Date());
78
 			log.setHandleStatus(status);
80
 			log.setHandleStatus(status);

+ 20 - 11
xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobInfo.java Просмотреть файл

10
 	
10
 	
11
 	private int id;
11
 	private int id;
12
 	
12
 	
13
-	private String jobGroup;	// base on quartz	任务组
14
-	private String jobName;		// base on quartz	任务名
15
-	private String jobCron;		// base on quartz	任务执行CRON表达式
16
-	private String jobClass;	// base on quartz	任务执行JobBean
17
-	private String jobData;		// base on db, Map-JSON-String	任务执行数据
13
+	private String jobGroup;	// 任务组
14
+	private String jobName;		// 任务名
15
+	private String jobCron;		// 任务执行CRON表达式 【base on quartz】
16
+	private String jobDesc;
17
+	private String jobClass;	// 任务执行JobBean 【base on quartz】
18
+	private String jobData;		// 任务执行数据 Map-JSON-String
18
 	
19
 	
19
 	private Date addTime;
20
 	private Date addTime;
20
 	private Date updateTime;
21
 	private Date updateTime;
21
 	
22
 	
22
-	private String author;		// 作者
23
+	private String author;		// 负责人
23
 	private String alarmEmail;	// 报警邮件
24
 	private String alarmEmail;	// 报警邮件
24
 	private int alarmThreshold;	// 报警阀值
25
 	private int alarmThreshold;	// 报警阀值
25
 	
26
 	
26
 	// copy from quartz
27
 	// copy from quartz
27
-	private String jobStatus;	// 任务状态
28
+	private String jobStatus;	// 任务状态 【base on quartz】
28
 
29
 
29
 	public int getId() {
30
 	public int getId() {
30
 		return id;
31
 		return id;
58
 		this.jobCron = jobCron;
59
 		this.jobCron = jobCron;
59
 	}
60
 	}
60
 
61
 
62
+	public String getJobDesc() {
63
+		return jobDesc;
64
+	}
65
+
66
+	public void setJobDesc(String jobDesc) {
67
+		this.jobDesc = jobDesc;
68
+	}
69
+
61
 	public String getJobClass() {
70
 	public String getJobClass() {
62
 		return jobClass;
71
 		return jobClass;
63
 	}
72
 	}
125
 	@Override
134
 	@Override
126
 	public String toString() {
135
 	public String toString() {
127
 		return "XxlJobInfo [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
136
 		return "XxlJobInfo [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
128
-				+ ", jobClass=" + jobClass + ", jobData=" + jobData + ", addTime=" + addTime + ", updateTime="
129
-				+ updateTime + ", author=" + author + ", alarmEmail=" + alarmEmail + ", alarmThreshold="
130
-				+ alarmThreshold + ", jobStatus=" + jobStatus + "]";
137
+				+ ", jobDesc=" + jobDesc + ", jobClass=" + jobClass + ", jobData=" + jobData + ", addTime=" + addTime
138
+				+ ", updateTime=" + updateTime + ", author=" + author + ", alarmEmail=" + alarmEmail
139
+				+ ", alarmThreshold=" + alarmThreshold + ", jobStatus=" + jobStatus + "]";
131
 	}
140
 	}
132
-	
141
+
133
 }
142
 }

+ 10 - 4
xxl-job-admin/src/main/java/com/xxl/job/core/model/XxlJobLog.java Просмотреть файл

14
 	private String jobGroup;
14
 	private String jobGroup;
15
 	private String jobName;
15
 	private String jobName;
16
 	private String jobCron;
16
 	private String jobCron;
17
+	private String jobDesc;
17
 	private String jobClass;
18
 	private String jobClass;
18
 	private String jobData;
19
 	private String jobData;
19
 	
20
 	
26
 	private Date handleTime;
27
 	private Date handleTime;
27
 	private String handleStatus;
28
 	private String handleStatus;
28
 	private String handleMsg;
29
 	private String handleMsg;
29
-	
30
 	public int getId() {
30
 	public int getId() {
31
 		return id;
31
 		return id;
32
 	}
32
 	}
51
 	public void setJobCron(String jobCron) {
51
 	public void setJobCron(String jobCron) {
52
 		this.jobCron = jobCron;
52
 		this.jobCron = jobCron;
53
 	}
53
 	}
54
+	public String getJobDesc() {
55
+		return jobDesc;
56
+	}
57
+	public void setJobDesc(String jobDesc) {
58
+		this.jobDesc = jobDesc;
59
+	}
54
 	public String getJobClass() {
60
 	public String getJobClass() {
55
 		return jobClass;
61
 		return jobClass;
56
 	}
62
 	}
103
 	@Override
109
 	@Override
104
 	public String toString() {
110
 	public String toString() {
105
 		return "XxlJobLog [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
111
 		return "XxlJobLog [id=" + id + ", jobGroup=" + jobGroup + ", jobName=" + jobName + ", jobCron=" + jobCron
106
-				+ ", jobClass=" + jobClass + ", jobData=" + jobData + ", triggerTime=" + triggerTime
107
-				+ ", triggerStatus=" + triggerStatus + ", triggerMsg=" + triggerMsg + ", handleTime=" + handleTime
108
-				+ ", handleStatus=" + handleStatus + ", handleMsg=" + handleMsg + "]";
112
+				+ ", jobDesc=" + jobDesc + ", jobClass=" + jobClass + ", jobData=" + jobData + ", triggerTime="
113
+				+ triggerTime + ", triggerStatus=" + triggerStatus + ", triggerMsg=" + triggerMsg + ", handleTime="
114
+				+ handleTime + ", handleStatus=" + handleStatus + ", handleMsg=" + handleMsg + "]";
109
 	}
115
 	}
110
 	
116
 	
111
 }
117
 }

+ 76 - 52
xxl-job-admin/src/main/java/com/xxl/job/core/util/DynamicSchedulerUtil.java Просмотреть файл

3
 import java.util.ArrayList;
3
 import java.util.ArrayList;
4
 import java.util.Date;
4
 import java.util.Date;
5
 import java.util.HashMap;
5
 import java.util.HashMap;
6
+import java.util.HashSet;
6
 import java.util.List;
7
 import java.util.List;
7
 import java.util.Map;
8
 import java.util.Map;
8
 import java.util.Set;
9
 import java.util.Set;
29
 import org.springframework.beans.factory.InitializingBean;
30
 import org.springframework.beans.factory.InitializingBean;
30
 import org.springframework.util.Assert;
31
 import org.springframework.util.Assert;
31
 
32
 
33
+import com.xxl.job.client.util.JacksonUtil;
32
 import com.xxl.job.core.model.XxlJobInfo;
34
 import com.xxl.job.core.model.XxlJobInfo;
33
 import com.xxl.job.dao.IXxlJobInfoDao;
35
 import com.xxl.job.dao.IXxlJobInfoDao;
34
 import com.xxl.job.dao.IXxlJobLogDao;
36
 import com.xxl.job.dao.IXxlJobLogDao;
124
 			e.printStackTrace();
126
 			e.printStackTrace();
125
 		}
127
 		}
126
 	}
128
 	}
129
+	
130
+	// check if exists
131
+	public static boolean checkExists(String jobName, String jobGroup) throws SchedulerException{
132
+		TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
133
+		return scheduler.checkExists(triggerKey);
134
+	}
127
 
135
 
128
 	// addJob 新增
136
 	// addJob 新增
129
-    public static boolean addJob(String triggerKeyName, String cronExpression, Class<? extends Job> jobClass, Map<String, Object> jobData) throws SchedulerException {
137
+    @SuppressWarnings("unchecked")
138
+	public static boolean addJob(XxlJobInfo jobInfo) throws SchedulerException {
130
     	// TriggerKey : name + group
139
     	// TriggerKey : name + group
131
-    	String group = Scheduler.DEFAULT_GROUP;
132
-        TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
140
+        TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup());
141
+        JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
133
         
142
         
134
         // TriggerKey valid if_exists
143
         // TriggerKey valid if_exists
135
-        if (scheduler.checkExists(triggerKey)) {
136
-            Trigger trigger = scheduler.getTrigger(triggerKey);
137
-            logger.info(">>>>>>>>> Already exist trigger [" + trigger + "] by key [" + triggerKey + "] in Scheduler");
144
+        if (checkExists(jobInfo.getJobName(), jobInfo.getJobGroup())) {
145
+            logger.info(">>>>>>>>> addJob fail, job already exist, jobInfo:{}", jobInfo);
138
             return false;
146
             return false;
139
         }
147
         }
140
         
148
         
141
         // CronTrigger : TriggerKey + cronExpression	// withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度
149
         // CronTrigger : TriggerKey + cronExpression	// withMisfireHandlingInstructionDoNothing 忽略掉调度终止过程中忽略的调度
142
-        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
150
+        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron()).withMisfireHandlingInstructionDoNothing();
143
         CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
151
         CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
144
 
152
 
145
         // JobDetail : jobClass
153
         // JobDetail : jobClass
146
-        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(triggerKeyName, group).build();
147
-        if (jobData!=null && jobData.size() > 0) {
154
+		Class<? extends Job> jobClass_ = null;
155
+		try {
156
+			jobClass_ = (Class<? extends Job>)Class.forName(jobInfo.getJobClass());
157
+		} catch (ClassNotFoundException e) {
158
+			e.printStackTrace();
159
+		}
160
+        
161
+		JobDetail jobDetail = JobBuilder.newJob(jobClass_).withIdentity(jobKey).build();
162
+        if (jobInfo.getJobData()!=null) {
148
         	JobDataMap jobDataMap = jobDetail.getJobDataMap();
163
         	JobDataMap jobDataMap = jobDetail.getJobDataMap();
149
-        	jobDataMap.putAll(jobData);	// JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
164
+        	jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));	// JobExecutionContext context.getMergedJobDataMap().get("mailGuid");
150
 		}
165
 		}
151
         
166
         
152
         // schedule : jobDetail + cronTrigger
167
         // schedule : jobDetail + cronTrigger
156
         return true;
171
         return true;
157
     }
172
     }
158
     
173
     
159
-    // reschedule 重置cron
160
-    public static boolean rescheduleJob(String triggerKeyName, String cronExpression) throws SchedulerException {
174
+    // reschedule
175
+    @SuppressWarnings("unchecked")
176
+	public static boolean rescheduleJob(XxlJobInfo jobInfo) throws SchedulerException {
177
+    	
178
+    	// TriggerKey valid if_exists
179
+        if (!checkExists(jobInfo.getJobName(), jobInfo.getJobGroup())) {
180
+        	logger.info(">>>>>>>>>>> rescheduleJob fail, job not exists, jobInfo:{}", jobInfo);
181
+            return false;
182
+        }
183
+        
161
         // TriggerKey : name + group
184
         // TriggerKey : name + group
162
-    	String group = Scheduler.DEFAULT_GROUP;
163
-        TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
185
+        TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), jobInfo.getJobGroup());
186
+        JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
164
         
187
         
165
-        boolean result = false;
166
-        if (scheduler.checkExists(triggerKey)) {
167
-            // CronTrigger : TriggerKey + cronExpression
168
-            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
169
-            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
170
-            
171
-            Date date = scheduler.rescheduleJob(triggerKey, cronTrigger);
172
-            result = true;
173
-            logger.info(">>>>>>>>>>> resumeJob success, triggerKey:{}, cronExpression:{}, date:{}", triggerKey, cronExpression, date);
174
-        } else {
175
-        	logger.info(">>>>>>>>>>> resumeJob fail, triggerKey:{}, cronExpression:{}", triggerKey, cronExpression);
176
-        }
177
-        return result;
188
+        // CronTrigger : TriggerKey + cronExpression
189
+        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getJobCron()).withMisfireHandlingInstructionDoNothing();
190
+        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build();
191
+        
192
+        //scheduler.rescheduleJob(triggerKey, cronTrigger);
193
+        
194
+        // JobDetail-JobDataMap fresh
195
+        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
196
+    	JobDataMap jobDataMap = jobDetail.getJobDataMap();
197
+    	jobDataMap.clear();
198
+    	jobDataMap.putAll(JacksonUtil.readValue(jobInfo.getJobData(), Map.class));
199
+    	
200
+    	// Trigger fresh
201
+    	HashSet<Trigger> triggerSet = new HashSet<Trigger>();
202
+    	triggerSet.add(cronTrigger);
203
+        
204
+        scheduler.scheduleJob(jobDetail, triggerSet, true);
205
+        logger.info(">>>>>>>>>>> resumeJob success, jobInfo:{}", jobInfo);
206
+        return true;
178
     }
207
     }
179
     
208
     
180
-    // unscheduleJob 删除
181
-    public static boolean removeJob(String triggerKeyName) throws SchedulerException {
209
+    // unscheduleJob
210
+    public static boolean removeJob(String jobName, String jobGroup) throws SchedulerException {
182
     	// TriggerKey : name + group
211
     	// TriggerKey : name + group
183
-    	String group = Scheduler.DEFAULT_GROUP;
184
-        TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
185
-        
212
+        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
186
         boolean result = false;
213
         boolean result = false;
187
-        if (scheduler.checkExists(triggerKey)) {
214
+        if (checkExists(jobName, jobGroup)) {
188
             result = scheduler.unscheduleJob(triggerKey);
215
             result = scheduler.unscheduleJob(triggerKey);
216
+            logger.info(">>>>>>>>>>> removeJob, triggerKey:{}, result [{}]", triggerKey, result);
189
         }
217
         }
190
-        logger.info(">>>>>>>>>>> removeJob, triggerKey:{}, result [{}]", triggerKey, result);
191
-        return result;
218
+        return true;
192
     }
219
     }
193
 
220
 
194
-    // Pause 暂停
195
-    public static boolean pauseJob(String triggerKeyName) throws SchedulerException {
221
+    // Pause
222
+    public static boolean pauseJob(String jobName, String jobGroup) throws SchedulerException {
196
     	// TriggerKey : name + group
223
     	// TriggerKey : name + group
197
-    	String group = Scheduler.DEFAULT_GROUP;
198
-        TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
224
+    	TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
199
         
225
         
200
         boolean result = false;
226
         boolean result = false;
201
-        if (scheduler.checkExists(triggerKey)) {
227
+        if (checkExists(jobName, jobGroup)) {
202
             scheduler.pauseTrigger(triggerKey);
228
             scheduler.pauseTrigger(triggerKey);
203
             result = true;
229
             result = true;
204
             logger.info(">>>>>>>>>>> pauseJob success, triggerKey:{}", triggerKey);
230
             logger.info(">>>>>>>>>>> pauseJob success, triggerKey:{}", triggerKey);
208
         return result;
234
         return result;
209
     }
235
     }
210
     
236
     
211
-    // resume 重启 
212
-    public static boolean resumeJob(String triggerKeyName) throws SchedulerException {
213
-        // TriggerKey : name + group
214
-    	String group = Scheduler.DEFAULT_GROUP;
215
-        TriggerKey triggerKey = TriggerKey.triggerKey(triggerKeyName, group);
237
+    // resume
238
+    public static boolean resumeJob(String jobName, String jobGroup) throws SchedulerException {
239
+    	// TriggerKey : name + group
240
+    	TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
216
         
241
         
217
         boolean result = false;
242
         boolean result = false;
218
-        if (scheduler.checkExists(triggerKey)) {
243
+        if (checkExists(jobName, jobGroup)) {
219
             scheduler.resumeTrigger(triggerKey);
244
             scheduler.resumeTrigger(triggerKey);
220
             result = true;
245
             result = true;
221
             logger.info(">>>>>>>>>>> resumeJob success, triggerKey:{}", triggerKey);
246
             logger.info(">>>>>>>>>>> resumeJob success, triggerKey:{}", triggerKey);
225
         return result;
250
         return result;
226
     }
251
     }
227
     
252
     
228
-    // run 执行一次 
229
-    public static boolean triggerJob(String triggerKeyName) throws SchedulerException {
230
-        // TriggerKey : name + group
231
-    	String group = Scheduler.DEFAULT_GROUP;
232
-        JobKey jobKey = JobKey.jobKey(triggerKeyName, group);
253
+    // run
254
+    public static boolean triggerJob(String jobName, String jobGroup) throws SchedulerException {
255
+    	// TriggerKey : name + group
256
+    	JobKey jobKey = new JobKey(jobName, jobGroup);
233
         
257
         
234
         boolean result = false;
258
         boolean result = false;
235
-        if (scheduler.checkExists(jobKey)) {
259
+        if (checkExists(jobName, jobGroup)) {
236
             scheduler.triggerJob(jobKey);
260
             scheduler.triggerJob(jobKey);
237
             result = true;
261
             result = true;
238
             logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);
262
             logger.info(">>>>>>>>>>> runJob success, jobKey:{}", jobKey);

+ 4 - 5
xxl-job-admin/src/main/java/com/xxl/job/dao/IXxlJobInfoDao.java Просмотреть файл

1
 package com.xxl.job.dao;
1
 package com.xxl.job.dao;
2
 
2
 
3
-import java.util.Date;
4
 import java.util.List;
3
 import java.util.List;
5
 
4
 
6
 import com.xxl.job.core.model.XxlJobInfo;
5
 import com.xxl.job.core.model.XxlJobInfo;
11
  */
10
  */
12
 public interface IXxlJobInfoDao {
11
 public interface IXxlJobInfoDao {
13
 
12
 
14
-	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd);
15
-	public int pageListCount(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd);
13
+	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String jobName);
14
+	public int pageListCount(int offset, int pagesize, String jobGroup, String jobName);
16
 	
15
 	
17
 	public int save(XxlJobInfo info);
16
 	public int save(XxlJobInfo info);
18
 	
17
 	
19
-	public XxlJobInfo load(String jobName);
18
+	public XxlJobInfo load(String jobGroup, String jobName);
20
 	
19
 	
21
 	public int update(XxlJobInfo item);
20
 	public int update(XxlJobInfo item);
22
 	
21
 	
23
-	public int delete(String jobName);
22
+	public int delete(String jobGroup, String jobName);
24
 	
23
 	
25
 }
24
 }

+ 16 - 11
xxl-job-admin/src/main/java/com/xxl/job/dao/impl/XxlJobInfoDaoImpl.java Просмотреть файл

1
 package com.xxl.job.dao.impl;
1
 package com.xxl.job.dao.impl;
2
 
2
 
3
-import java.util.Date;
4
 import java.util.HashMap;
3
 import java.util.HashMap;
5
 import java.util.List;
4
 import java.util.List;
6
 
5
 
23
 	public SqlSessionTemplate sqlSessionTemplate;
22
 	public SqlSessionTemplate sqlSessionTemplate;
24
 
23
 
25
 	@Override
24
 	@Override
26
-	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd) {
25
+	public List<XxlJobInfo> pageList(int offset, int pagesize, String jobGroup, String jobName) {
27
 		HashMap<String, Object> params = new HashMap<String, Object>();
26
 		HashMap<String, Object> params = new HashMap<String, Object>();
28
 		params.put("offset", offset);
27
 		params.put("offset", offset);
29
 		params.put("pagesize", pagesize);
28
 		params.put("pagesize", pagesize);
29
+		params.put("jobGroup", jobGroup);
30
 		params.put("jobName", jobName);
30
 		params.put("jobName", jobName);
31
-		params.put("addTimeStart", addTimeStart);
32
-		params.put("addTimeEnd", addTimeEnd);
33
 		
31
 		
34
 		return sqlSessionTemplate.selectList("XxlJobInfoMapper.pageList", params);
32
 		return sqlSessionTemplate.selectList("XxlJobInfoMapper.pageList", params);
35
 	}
33
 	}
36
 
34
 
37
 	@Override
35
 	@Override
38
-	public int pageListCount(int offset, int pagesize, String jobName, Date addTimeStart, Date addTimeEnd) {
36
+	public int pageListCount(int offset, int pagesize, String jobGroup, String jobName) {
39
 		HashMap<String, Object> params = new HashMap<String, Object>();
37
 		HashMap<String, Object> params = new HashMap<String, Object>();
40
 		params.put("offset", offset);
38
 		params.put("offset", offset);
41
 		params.put("pagesize", pagesize);
39
 		params.put("pagesize", pagesize);
40
+		params.put("jobGroup", jobGroup);
42
 		params.put("jobName", jobName);
41
 		params.put("jobName", jobName);
43
-		params.put("addTimeStart", addTimeStart);
44
-		params.put("addTimeEnd", addTimeEnd);
45
 		
42
 		
46
 		return sqlSessionTemplate.selectOne("XxlJobInfoMapper.pageListCount", params);
43
 		return sqlSessionTemplate.selectOne("XxlJobInfoMapper.pageListCount", params);
47
 	}
44
 	}
52
 	}
49
 	}
53
 
50
 
54
 	@Override
51
 	@Override
55
-	public XxlJobInfo load(String jobName) {
56
-		return sqlSessionTemplate.selectOne("XxlJobInfoMapper.load", jobName);
52
+	public XxlJobInfo load(String jobGroup, String jobName) {
53
+		HashMap<String, Object> params = new HashMap<String, Object>();
54
+		params.put("jobGroup", jobGroup);
55
+		params.put("jobName", jobName);
56
+		
57
+		return sqlSessionTemplate.selectOne("XxlJobInfoMapper.load", params);
57
 	}
58
 	}
58
 
59
 
59
 	@Override
60
 	@Override
62
 	}
63
 	}
63
 
64
 
64
 	@Override
65
 	@Override
65
-	public int delete(String jobName) {
66
-		return sqlSessionTemplate.update("XxlJobInfoMapper.delete", jobName);
66
+	public int delete(String jobGroup, String jobName) {
67
+		HashMap<String, Object> params = new HashMap<String, Object>();
68
+		params.put("jobGroup", jobGroup);
69
+		params.put("jobName", jobName);
70
+		
71
+		return sqlSessionTemplate.update("XxlJobInfoMapper.delete", params);
67
 	}
72
 	}
68
 	
73
 	
69
 }
74
 }

+ 22 - 22
xxl-job-admin/src/main/java/com/xxl/job/service/job/HttpJobBean.java Просмотреть файл

5
 import java.util.Map;
5
 import java.util.Map;
6
 
6
 
7
 import org.apache.commons.lang.StringUtils;
7
 import org.apache.commons.lang.StringUtils;
8
+import org.quartz.DisallowConcurrentExecution;
8
 import org.quartz.JobExecutionContext;
9
 import org.quartz.JobExecutionContext;
9
 import org.quartz.JobExecutionException;
10
 import org.quartz.JobExecutionException;
10
-import org.quartz.impl.triggers.CronTriggerImpl;
11
+import org.quartz.JobKey;
11
 import org.slf4j.Logger;
12
 import org.slf4j.Logger;
12
 import org.slf4j.LoggerFactory;
13
 import org.slf4j.LoggerFactory;
13
 import org.springframework.scheduling.quartz.QuartzJobBean;
14
 import org.springframework.scheduling.quartz.QuartzJobBean;
22
 
23
 
23
 /**
24
 /**
24
  * http job bean
25
  * http job bean
26
+ * “@DisallowConcurrentExecution” diable concurrent, thread size can not be only one, better given more
25
  * @author xuxueli 2015-12-17 18:20:34
27
  * @author xuxueli 2015-12-17 18:20:34
26
  */
28
  */
29
+@DisallowConcurrentExecution
27
 public class HttpJobBean extends QuartzJobBean {
30
 public class HttpJobBean extends QuartzJobBean {
28
 	private static Logger logger = LoggerFactory.getLogger(HttpJobBean.class);
31
 	private static Logger logger = LoggerFactory.getLogger(HttpJobBean.class);
29
-
32
+	
30
 	@SuppressWarnings("unchecked")
33
 	@SuppressWarnings("unchecked")
31
 	@Override
34
 	@Override
32
 	protected void executeInternal(JobExecutionContext context)
35
 	protected void executeInternal(JobExecutionContext context)
33
 			throws JobExecutionException {
36
 			throws JobExecutionException {
34
-		String triggerKey = context.getTrigger().getJobKey().getName();
35
-		
36
-		// jobDataMap 2 params
37
-		Map<String, String> params = new HashMap<String, String>();
38
-		XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(triggerKey);
39
-		if (jobInfo!=null && jobInfo.getJobData()!=null) {
40
-			params = JacksonUtil.readValue(jobInfo.getJobData(), Map.class);
41
-		}
42
-		
43
-		// corn
44
-		String cornExp = null;
45
-		if (context.getTrigger() instanceof CronTriggerImpl) {
46
-			CronTriggerImpl trigger = (CronTriggerImpl) context.getTrigger();
47
-			cornExp = trigger.getCronExpression();
48
-		}
37
+		JobKey jobKey = context.getTrigger().getJobKey();
49
 		
38
 		
39
+		XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKey.getGroup(), jobKey.getName());
40
+		HashMap<String, String> jobDataMap = (HashMap<String, String>) JacksonUtil.readValueRefer(jobInfo.getJobData(), Map.class);
50
 		// save log
41
 		// save log
51
 		XxlJobLog jobLog = new XxlJobLog();
42
 		XxlJobLog jobLog = new XxlJobLog();
52
-		jobLog.setJobName(triggerKey);
53
-		jobLog.setJobCron(cornExp);
43
+		jobLog.setJobGroup(jobInfo.getJobGroup());
44
+		jobLog.setJobName(jobInfo.getJobName());
45
+		jobLog.setJobCron(jobInfo.getJobCron());
46
+		jobLog.setJobDesc(jobInfo.getJobDesc());
47
+		jobLog.setJobClass(jobInfo.getJobClass());
48
+		jobLog.setJobData(jobInfo.getJobData());
49
+		
54
 		jobLog.setJobClass(HttpJobBean.class.getName());
50
 		jobLog.setJobClass(HttpJobBean.class.getName());
55
 		jobLog.setJobData(jobInfo.getJobData());
51
 		jobLog.setJobData(jobInfo.getJobData());
56
 		DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
52
 		DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
57
 		logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog);
53
 		logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog);
58
 		
54
 		
59
 		// trigger request
55
 		// trigger request
60
-		params.put(HandlerRepository.triggerLogId, String.valueOf(jobLog.getId()));
61
-		params.put(HandlerRepository.triggerLogUrl, PropertiesUtil.getString(HandlerRepository.triggerLogUrl));
62
-		String[] postResp = HttpUtil.post(params.get(HandlerRepository.job_url), params);
56
+		HashMap<String, String> params = new HashMap<String, String>();
57
+		params.put(HandlerRepository.TRIGGER_LOG_URL, PropertiesUtil.getString(HandlerRepository.TRIGGER_LOG_URL));
58
+		params.put(HandlerRepository.TRIGGER_LOG_ID, String.valueOf(jobLog.getId()));
59
+		params.put(HandlerRepository.HANDLER_NAME, jobDataMap.get(HandlerRepository.HANDLER_NAME));
60
+		params.put(HandlerRepository.HANDLER_PARAMS, jobDataMap.get(HandlerRepository.HANDLER_PARAMS));
61
+		
62
+		String[] postResp = HttpUtil.post(jobDataMap.get(HandlerRepository.HANDLER_ADDRESS), params);
63
 		logger.info(">>>>>>>>>>> xxl-job trigger http response, jobLog.id:{}, jobLog:{}", jobLog.getId(), jobLog);
63
 		logger.info(">>>>>>>>>>> xxl-job trigger http response, jobLog.id:{}, jobLog:{}", jobLog.getId(), jobLog);
64
 		
64
 		
65
 		// parse trigger response
65
 		// parse trigger response

+ 57 - 31
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml Просмотреть файл

6
 	<resultMap id="XxlJobInfo" type="com.xxl.job.core.model.XxlJobInfo" >
6
 	<resultMap id="XxlJobInfo" type="com.xxl.job.core.model.XxlJobInfo" >
7
 		<result column="id" property="id" />
7
 		<result column="id" property="id" />
8
 	
8
 	
9
+		<result column="job_group" property="jobGroup" />
9
 	    <result column="job_name" property="jobName" />
10
 	    <result column="job_name" property="jobName" />
10
 	    <result column="job_cron" property="jobCron" />
11
 	    <result column="job_cron" property="jobCron" />
12
+	    <result column="job_desc" property="jobDesc" />
11
 	    <result column="job_class" property="jobClass" />
13
 	    <result column="job_class" property="jobClass" />
12
 	    <result column="job_data" property="jobData" />
14
 	    <result column="job_data" property="jobData" />
13
 	    
15
 	    
14
 	    <result column="add_time" property="addTime" />
16
 	    <result column="add_time" property="addTime" />
15
 	    <result column="update_time" property="updateTime" />
17
 	    <result column="update_time" property="updateTime" />
18
+	    
19
+	    <result column="author" property="author" />
20
+	    <result column="alarm_email" property="alarmEmail" />
21
+	    <result column="alarm_threshold" property="alarmThreshold" />
16
 	</resultMap>
22
 	</resultMap>
17
 
23
 
18
 	<sql id="Base_Column_List">
24
 	<sql id="Base_Column_List">
19
 		t.id,
25
 		t.id,
26
+		t.job_group,
20
 		t.job_name,
27
 		t.job_name,
21
 		t.job_cron,
28
 		t.job_cron,
29
+		t.job_desc,
22
 		t.job_class,
30
 		t.job_class,
23
 		t.job_data,
31
 		t.job_data,
24
 		t.add_time,
32
 		t.add_time,
25
-		t.update_time
33
+		t.update_time,
34
+		t.author,
35
+		t.alarm_email,
36
+		t.alarm_threshold
26
 	</sql>
37
 	</sql>
27
 	
38
 	
28
 	<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
39
 	<select id="pageList" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
29
 		SELECT <include refid="Base_Column_List" />
40
 		SELECT <include refid="Base_Column_List" />
30
 		FROM xxl_job_qrtz_trigger_info AS t
41
 		FROM xxl_job_qrtz_trigger_info AS t
31
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
42
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
32
-			<if test="jobName != null and jobName!=''">
33
-				AND t.job_name = #{jobName}
34
-			</if>
35
-			<if test="addTimeStart != null">
36
-				AND t.add_time <![CDATA[ > ]]> #{addTimeStart}
43
+			<if test="jobGroup != null and jobGroup != ''">
44
+				AND t.job_group = #{jobGroup}
37
 			</if>
45
 			</if>
38
-			<if test="addTimeEnd != null">
39
-				AND t.add_time <![CDATA[ < ]]> #{addTimeEnd}
46
+			<if test="jobName != null and jobName != ''">
47
+				AND t.job_name like CONCAT(CONCAT('%', #{jobName}), '%')
40
 			</if>
48
 			</if>
41
 		</trim>
49
 		</trim>
42
 		ORDER BY id DESC
50
 		ORDER BY id DESC
47
 		SELECT count(1)
55
 		SELECT count(1)
48
 		FROM xxl_job_qrtz_trigger_info AS t
56
 		FROM xxl_job_qrtz_trigger_info AS t
49
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
57
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
50
-			<if test="jobName != null and jobName!=''">
51
-				AND t.job_name = #{jobName}
58
+			<if test="jobGroup != null and jobGroup != ''">
59
+				AND t.job_group = #{jobGroup}
52
 			</if>
60
 			</if>
53
-			<if test="addTimeStart != null">
54
-				AND t.add_time <![CDATA[ > ]]> #{addTimeStart}
55
-			</if>
56
-			<if test="addTimeEnd != null">
57
-				AND t.add_time <![CDATA[ < ]]> #{addTimeEnd}
61
+			<if test="jobName != null and jobName != ''">
62
+				AND t.job_name like CONCAT(CONCAT('%', #{jobName}), '%')
58
 			</if>
63
 			</if>
59
 		</trim>
64
 		</trim>
60
 	</select>
65
 	</select>
61
 	
66
 	
62
 	<insert id="save" parameterType="com.xxl.job.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" >
67
 	<insert id="save" parameterType="com.xxl.job.core.model.XxlJobInfo" useGeneratedKeys="true" keyProperty="id" >
63
 		INSERT INTO `xxl_job_qrtz_trigger_info` (
68
 		INSERT INTO `xxl_job_qrtz_trigger_info` (
64
-			`job_name`, 
65
-			`job_cron`, 
66
-			`job_class`, 
67
-			`job_data`,
68
-			`add_time`,
69
-			`update_time`
69
+			job_group,
70
+			job_name,
71
+			job_cron,
72
+			job_desc,
73
+			job_class,
74
+			job_data,
75
+			add_time,
76
+			update_time,
77
+			author,
78
+			alarm_email,
79
+			alarm_threshold
70
 		) VALUES (
80
 		) VALUES (
81
+			#{jobGroup}, 
71
 			#{jobName}, 
82
 			#{jobName}, 
72
 			#{jobCron}, 
83
 			#{jobCron}, 
84
+			#{jobDesc}, 
73
 			#{jobClass}, 
85
 			#{jobClass}, 
74
 			#{jobData},
86
 			#{jobData},
75
 			NOW(),
87
 			NOW(),
76
-			NOW()
88
+			NOW(),
89
+			#{author},
90
+			#{alarmEmail},
91
+			#{alarmThreshold}
77
 		);
92
 		);
78
 		<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> 
93
 		<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> 
79
 			SELECT LAST_INSERT_ID() 
94
 			SELECT LAST_INSERT_ID() 
80
 		</selectKey> 
95
 		</selectKey> 
81
 	</insert>
96
 	</insert>
82
 	
97
 	
83
-	<select id="load" parameterType="java.lang.String" resultMap="XxlJobInfo">
98
+	<select id="load" parameterType="java.util.HashMap" resultMap="XxlJobInfo">
84
 		SELECT <include refid="Base_Column_List" />
99
 		SELECT <include refid="Base_Column_List" />
85
 		FROM xxl_job_qrtz_trigger_info AS t
100
 		FROM xxl_job_qrtz_trigger_info AS t
86
-		WHERE t.job_name = #{jobName}
101
+		WHERE t.job_group = #{jobGroup}
102
+			AND t.job_name = #{jobName}
87
 	</select>
103
 	</select>
88
 	
104
 	
89
-	<update id="update">
105
+	<update id="update" parameterType="com.xxl.job.core.model.XxlJobInfo" >
90
 		UPDATE `xxl_job_qrtz_trigger_info` 
106
 		UPDATE `xxl_job_qrtz_trigger_info` 
91
-		SET `job_cron`= #{jobCron}, 
92
-			`job_data`= #{jobData},
93
-			`update_time`= NOW()
94
-		WHERE `id`= #{id}
107
+		SET 
108
+			job_cron = #{jobCron},
109
+			job_desc = #{jobDesc},
110
+			job_data = #{jobData},
111
+			update_time = NOW(),
112
+			author = #{author},
113
+			alarm_email = #{alarmEmail},
114
+			alarm_threshold = #{alarmThreshold}
115
+		WHERE job_group = #{jobGroup}
116
+			AND job_name = #{jobName}
95
 	</update>
117
 	</update>
96
 	
118
 	
97
 	<delete id="delete" parameterType="java.lang.String">
119
 	<delete id="delete" parameterType="java.lang.String">
98
-		delete from xxl_job_qrtz_trigger_info
99
-		where job_name = #{jobName}
120
+		DELETE
121
+		FROM
122
+			xxl_job_qrtz_trigger_info
123
+		WHERE
124
+			job_group = #{jobGroup}
125
+		AND job_name = #{jobName}
100
 	</delete>
126
 	</delete>
101
 	
127
 	
102
 </mapper>
128
 </mapper>

+ 5 - 1
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml Просмотреть файл

9
 	    <result column="job_group" property="jobGroup" />
9
 	    <result column="job_group" property="jobGroup" />
10
 	    <result column="job_name" property="jobName" />
10
 	    <result column="job_name" property="jobName" />
11
 	    <result column="job_cron" property="jobCron" />
11
 	    <result column="job_cron" property="jobCron" />
12
+	    <result column="job_desc" property="jobDesc" />
12
 	    <result column="job_class" property="jobClass" />
13
 	    <result column="job_class" property="jobClass" />
13
 	    <result column="job_data" property="jobData" />
14
 	    <result column="job_data" property="jobData" />
14
 	    
15
 	    
26
 		t.job_group,
27
 		t.job_group,
27
 		t.job_name,
28
 		t.job_name,
28
 		t.job_cron,
29
 		t.job_cron,
30
+		t.job_desc,
29
 		t.job_class,
31
 		t.job_class,
30
-		t.job_data,
32
+		t.job_desc,
31
 		t.trigger_time,
33
 		t.trigger_time,
32
 		t.trigger_status,
34
 		t.trigger_status,
33
 		t.trigger_msg,
35
 		t.trigger_msg,
94
 			`job_group`,
96
 			`job_group`,
95
 			`job_name`,
97
 			`job_name`,
96
 			`job_cron`, 
98
 			`job_cron`, 
99
+			`job_desc`,
97
 			`job_class`, 
100
 			`job_class`, 
98
 			`job_data`
101
 			`job_data`
99
 		) VALUES (
102
 		) VALUES (
100
 			#{jobGroup}, 
103
 			#{jobGroup}, 
101
 			#{jobName},
104
 			#{jobName},
102
 			#{jobCron},
105
 			#{jobCron},
106
+			#{jobDesc},
103
 			#{jobClass},
107
 			#{jobClass},
104
 			#{jobData}
108
 			#{jobData}
105
 		);
109
 		);

+ 47 - 67
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/index.ftl Просмотреть файл

42
 	            </div>
42
 	            </div>
43
 	            <div class="col-xs-4">
43
 	            <div class="col-xs-4">
44
 	              	<div class="input-group">
44
 	              	<div class="input-group">
45
-	                	<span class="input-group-addon">
46
-	                  		jobName
47
-	                	</span>
45
+	                	<span class="input-group-addon">任务名</span>
48
 	                	<input type="text" class="form-control" id="jobName" value="${jobName}" autocomplete="on" >
46
 	                	<input type="text" class="form-control" id="jobName" value="${jobName}" autocomplete="on" >
49
 	              	</div>
47
 	              	</div>
50
 	            </div>
48
 	            </div>
66
 			              	<table id="job_list" class="table table-bordered table-striped">
64
 			              	<table id="job_list" class="table table-bordered table-striped">
67
 				                <thead>
65
 				                <thead>
68
 					            	<tr>
66
 					            	<tr>
69
-					            		<th>id</th>
70
-					                	<th>任务Key</th>
71
-					                  	<th>任务Cron</th>
72
-					                  	<th>任务Class</th>
73
-					                  	<th>状态Status</th>
74
-					                  	<th>参数</th>
75
-					                  	<th>addTime</th>
76
-					                  	<th>updateTime</th>
67
+					            		<th name="id" >id</th>
68
+					                	<th name="jobGroup" >任务组</th>
69
+					                  	<th name="jobName" >任务名</th>
70
+					                  	<th name="jobCron" >Cron</th>
71
+					                  	<th name="jobDesc" >描述</th>
72
+					                  	<th name="jobClass" >JobBean</th>
73
+					                  	<th name="jobData" >任务数据</th>
74
+					                  	<th name="addTime" >新增时间</th>
75
+					                  	<th name="updateTime" >更新时间</th>
76
+					                  	<th name="author" >负责人</th>
77
+					                  	<th name="alarmEmail" >报警邮件</th>
78
+					                  	<th name="alarmThreshold" >报警阀值</th>
79
+					                  	<th name="jobStatus" >状态</th>
77
 					                  	<th>操作</th>
80
 					                  	<th>操作</th>
78
 					                </tr>
81
 					                </tr>
79
 				                </thead>
82
 				                </thead>
80
-				                <tbody>
81
-				                	<#--
82
-			                		<#if jobList?exists && jobList?size gt 0>
83
-									<#list jobList as item>
84
-									<tr>
85
-					            		<td>${item['TriggerKey'].name}</td>
86
-					                  	<td>${item['Trigger'].cronExpression}</td>
87
-					                  	<td>${item['JobDetail'].jobClass}</td>
88
-					                  	<td>
89
-					                  		<#assign jobDataMap = item['JobDetail'].jobDataMap />
90
-					                  		<#if jobDataMap?exists && jobDataMap?keys?size gt 0>
91
-					                  			<#list jobDataMap?keys as key>
92
-					                  				${key}	=	${jobDataMap[key]}	<br>
93
-					                  			</#list>
94
-					                  		</#if>
95
-					                  	</td>
96
-					                  	<td state="${item['TriggerState']}" >
97
-					                  		<#if item['TriggerState'] == 'NORMAL'>
98
-					                  			<button class="btn btn-block btn-success" type="button">运行ing</button>
99
-					                  		<#elseif item['TriggerState'] == 'PAUSED'>
100
-					                  			<button class="btn btn-block btn-warning" type="button">暂停ing</button>
101
-					                  		<#else>
102
-					                  			<button class="btn btn-block" type="button">${item['TriggerState']}</button>
103
-					                  		</#if>
104
-					                  	</td>
105
-					                  	<td>
106
-											<p name="${item['TriggerKey'].name}" group="${item['TriggerKey'].group}" 
107
-												cronExpression="${item['Trigger'].cronExpression}" jobClassName="${item['JobDetail'].jobClass}" jobDesc="${job_desc?if_exists}" >
108
-												<#if item['TriggerState'] == 'NORMAL'>
109
-													<button class="btn btn-info btn-xs job_operate" type="job_pause" type="button">暂停</button>
110
-												<#elseif item['TriggerState'] == 'PAUSED'>
111
-													<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button>
112
-												</#if>
113
-												<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行一次</button>
114
-												<button class="btn btn-info btn-xs update" type="button">更新corn</button>
115
-											  	<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>
116
-											  	<button class="btn btn-warning btn-xs" type="job_del" type="button" 
117
-											  		onclick="javascript:window.open('${request.contextPath}/joblog?jobName=${item['TriggerKey'].name}')" >查看日志</button>
118
-											</p>
119
-					                  	</td>
120
-					                </tr>
121
-									</#list>
122
-									</#if>
123
-									
124
-									-->
125
-				                </tbody>
83
+				                <tbody></tbody>
126
 				                <tfoot></tfoot>
84
 				                <tfoot></tfoot>
127
 							</table>
85
 							</table>
128
 						</div>
86
 						</div>
155
 		                  	</select>
113
 		                  	</select>
156
 						</div>
114
 						</div>
157
 						<label for="firstname" class="col-sm-2 control-label">任务名</label>
115
 						<label for="firstname" class="col-sm-2 control-label">任务名</label>
158
-						<div class="col-sm-4"><input type="text" class="form-control" name="triggerKeyName" placeholder="请输入任务Key" minlength="4" maxlength="100" ></div>
116
+						<div class="col-sm-4"><input type="text" class="form-control" name="jobName" placeholder="请输入“任务名”" minlength="4" maxlength="100" ></div>
159
 					</div>
117
 					</div>
160
 					<div class="form-group">
118
 					<div class="form-group">
161
-						<label for="lastname" class="col-sm-3 control-label">任务Corn</label>
162
-						<div class="col-sm-9"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn" maxlength="100" ></div>
119
+						<label for="lastname" class="col-sm-2 control-label">Corn</label>
120
+						<div class="col-sm-4"><input type="text" class="form-control" name="jobCron" placeholder="请输入“Corn”" maxlength="100" ></div>
121
+						<label for="lastname" class="col-sm-2 control-label">描述</label>
122
+						<div class="col-sm-4"><input type="text" class="form-control" name="jobDesc" placeholder="请输入“描述”" maxlength="200" ></div>
163
 					</div>
123
 					</div>
164
 					<div class="form-group">
124
 					<div class="form-group">
165
-						<label for="lastname" class="col-sm-3 control-label">任务描述</label>
166
-						<div class="col-sm-9"><input type="text" class="form-control" name="job_desc" placeholder="请输入任务描述" maxlength="200" ></div>
125
+						<label for="firstname" class="col-sm-2 control-label">JobBean</label>
126
+						<div class="col-sm-4">
127
+							<select class="form-control" name="jobClass" >
128
+								<#if remoteJobBean?exists >
129
+								<option value="${remoteJobBean.name}" jobClassType="remote" >【远程任务】</option>
130
+								</#if>
131
+								<#if localJobBeanList?exists && localJobBeanList?size gt 0 >
132
+								<#list localJobBeanList as localJobBean>
133
+									<option value="${localJobBean.name}" jobClassType="local" >${localJobBean.name}</option>
134
+								</#list>
135
+								</#if>
136
+		                  	</select>
137
+						</div>
138
+						<label for="firstname" class="col-sm-2 control-label">执行参数</label>
139
+						<div class="col-sm-4"><input type="text" class="form-control" name="handler_params" placeholder="请输入“执行参数”" maxlength="100" ></div>
140
+					</div>
141
+					<div class="form-group remote_panel">
142
+						<label for="lastname" class="col-sm-2 control-label">远程-机器地址</label>
143
+						<div class="col-sm-4"><input type="text" class="form-control" name="handler_address" placeholder="请输入“远程-机器地址”" maxlength="200" ></div>
144
+						<label for="lastname" class="col-sm-2 control-label">远程-执行器</label>
145
+						<div class="col-sm-4"><input type="text" class="form-control" name="handler_name" placeholder="请输入“远程-执行器”" maxlength="200" ></div>
167
 					</div>
146
 					</div>
168
 					<div class="form-group">
147
 					<div class="form-group">
169
-						<label for="lastname" class="col-sm-3 control-label">任务URL</label>
170
-						<div class="col-sm-9"><input type="text" class="form-control" name="job_url" placeholder="请输入任务URL" maxlength="200" ></div>
148
+						<label for="lastname" class="col-sm-2 control-label">负责人</label>
149
+						<div class="col-sm-4"><input type="text" class="form-control" name="author" placeholder="请输入“负责人”" maxlength="200" ></div>
150
+						<label for="lastname" class="col-sm-2 control-label">报警邮件</label>
151
+						<div class="col-sm-4"><input type="text" class="form-control" name="alarm_email" placeholder="请输入“报警邮件”,多个邮件地址逗号分隔" maxlength="200" ></div>
171
 					</div>
152
 					</div>
172
 					<div class="form-group">
153
 					<div class="form-group">
173
-						<label for="lastname" class="col-sm-3 control-label">任务handler</label>
174
-						<div class="col-sm-9"><input type="text" class="form-control" name="handleName" placeholder="请输入任务handler" maxlength="200" ></div>
154
+						<label for="lastname" class="col-sm-2 control-label">报警阈值</label>
155
+						<div class="col-sm-4"><input type="text" class="form-control" name="alarm_threshold" placeholder="请输入“报警阈值”" maxlength="200" ></div>
175
 					</div>
156
 					</div>
176
 					<div class="form-group">
157
 					<div class="form-group">
177
 						<div class="col-sm-offset-3 col-sm-9">
158
 						<div class="col-sm-offset-3 col-sm-9">
178
 							<button type="submit" class="btn btn-primary"  >保存</button>
159
 							<button type="submit" class="btn btn-primary"  >保存</button>
179
 							<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
160
 							<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
180
-							<button type="button" class="btn btn-info pull-right addParam">+ arg</button>
181
 						</div>
161
 						</div>
182
 					</div>
162
 					</div>
183
 				</form>
163
 				</form>

+ 2 - 1
xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl Просмотреть файл

35
 	                	<span class="input-group-addon">任务组</span>
35
 	                	<span class="input-group-addon">任务组</span>
36
                 		<select class="form-control" id="jobGroup" >
36
                 		<select class="form-control" id="jobGroup" >
37
                 			<#list JobGroupList as group>
37
                 			<#list JobGroupList as group>
38
-                				<option value="${group}" <#if jobInfo?exists && group == jobInfo.jobGroup>selected</#if> >${group.desc}</option>
38
+                				<option value="${group}" <#if jobGroup == group>selected</#if> >${group.desc}</option>
39
                 			</#list>
39
                 			</#list>
40
 	                  	</select>
40
 	                  	</select>
41
 	              	</div>
41
 	              	</div>
74
 					                	<th name="jobGroup" >任务组</th>
74
 					                	<th name="jobGroup" >任务组</th>
75
 					                  	<th name="jobName" >任务名</th>
75
 					                  	<th name="jobName" >任务名</th>
76
 					                  	<th name="jobCron" >Cron</th>
76
 					                  	<th name="jobCron" >Cron</th>
77
+					                  	<th name="jobDesc" >描述</th>
77
 					                  	<th name="jobClass" >JobBean</th>
78
 					                  	<th name="jobClass" >JobBean</th>
78
 					                  	<th name="jobData" >任务数据</th>
79
 					                  	<th name="jobData" >任务数据</th>
79
 					                  	<th name="triggerTime" >调度时间</th>
80
 					                  	<th name="triggerTime" >调度时间</th>

+ 160 - 105
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js Просмотреть файл

7
 		"ajax": {
7
 		"ajax": {
8
 			url: base_url + "/jobinfo/pageList",
8
 			url: base_url + "/jobinfo/pageList",
9
 	        data : function ( d ) {
9
 	        data : function ( d ) {
10
-                d.jobName = $('#jobName').val()
10
+	        	d.jobGroup = $('#jobGroup').val();
11
+                d.jobName = $('#jobName').val();
11
             }
12
             }
12
 	    },
13
 	    },
14
+	    "searching": false,
15
+	    "ordering": false,
13
 	    //"scrollX": true,	// X轴滚动条,取消自适应
16
 	    //"scrollX": true,	// X轴滚动条,取消自适应
14
 	    "columns": [
17
 	    "columns": [
15
 	                { "data": 'id', "bSortable": false, "visible" : false},
18
 	                { "data": 'id', "bSortable": false, "visible" : false},
16
-	                { "data": 'jobName', "bSortable": false},
17
-	                { "data": 'jobCron', "bSortable": false, "visible" : true},
18
-	                { "data": 'jobClass', "bSortable": false, "visible" : false},
19
-	                { "data": 'jobStatus', "bSortable": false, "visible" : true},
20
-	                { "data": 'jobData', "bSortable": false, "visible" : true},
19
+	                { 
20
+	                	"data": 'jobGroup', 
21
+	                	"render": function ( data, type, row ) {
22
+	            			var groupMenu = $("#jobGroup").find("option");
23
+	            			for ( var index in $("#jobGroup").find("option")) {
24
+	            				if ($(groupMenu[index]).attr('value') == data) {
25
+									return $(groupMenu[index]).html();
26
+								}
27
+							}
28
+	            			return data;
29
+	            		}
30
+            		},
31
+	                { "data": 'jobName'},
32
+	                { "data": 'jobCron', "visible" : true},
33
+	                { "data": 'jobDesc', "visible" : false},
34
+	                { "data": 'jobClass', "visible" : true},
35
+	                { 
36
+	                	"data": 'jobData',
37
+	                	"visible" : true,
38
+	                	"render": function ( data, type, row ) {
39
+	                		return data?'<a class="logTips" href="javascript:;" >查看<span style="display:none;">'+ data +'</span></a>':"无";
40
+	                	}
41
+	                },
21
 	                { 
42
 	                { 
22
 	                	"data": 'addTime', 
43
 	                	"data": 'addTime', 
23
-	                	"bSortable": false, 
44
+	                	"visible" : false, 
24
 	                	"render": function ( data, type, row ) {
45
 	                	"render": function ( data, type, row ) {
25
 	                		return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
46
 	                		return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
26
 	                	}
47
 	                	}
27
 	                },
48
 	                },
28
 	                { 
49
 	                { 
29
 	                	"data": 'updateTime', 
50
 	                	"data": 'updateTime', 
30
-	                	"bSortable": false, 
51
+	                	"visible" : false, 
31
 	                	"render": function ( data, type, row ) {
52
 	                	"render": function ( data, type, row ) {
32
 	                		return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
53
 	                		return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
33
 	                	}
54
 	                	}
34
 	                },
55
 	                },
35
-	                { "data": '操作' , "bSortable": false,
56
+	                { "data": 'author', "visible" : true},
57
+	                { "data": 'alarmEmail', "visible" : false},
58
+	                { "data": 'alarmThreshold', "visible" : false},
59
+	                { 
60
+	                	"data": 'jobStatus', 
61
+	                	"visible" : true,
62
+	                	"render": function ( data, type, row ) {
63
+	                		if ('NORMAL' == data) {
64
+	                			return '<small class="label label-success" ><i class="fa fa-clock-o"></i>'+ data +'</small>'; 
65
+							} else if ('PAUSED' == data){
66
+								return '<small class="label label-default"><i class="fa fa-clock-o"></i>'+ data +'</small>'; 
67
+							}
68
+	                		return data;
69
+	                	}
70
+	                },
71
+	                { "data": '操作' ,
36
 	                	"render": function ( data, type, row ) {
72
 	                	"render": function ( data, type, row ) {
37
 	                		return function(){
73
 	                		return function(){
38
 	                			// status
74
 	                			// status
43
 									pause_resume = '<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button>  ';
79
 									pause_resume = '<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button>  ';
44
 								}
80
 								}
45
 	                			// log url
81
 	                			// log url
46
-	                			var logUrl = base_url +'/joblog?jobName='+ row.jobName;
82
+	                			var logUrl = base_url +'/joblog?jobGroup='+ row.jobGroup +'&jobName='+ row.jobName;
47
 	                			
83
 	                			
48
 	                			// job data
84
 	                			// job data
49
 	                			var jobDataMap = eval('(' + row.jobData + ')');
85
 	                			var jobDataMap = eval('(' + row.jobData + ')');
50
 	                			
86
 	                			
51
-	                			var html = '<p jobName="'+ row.jobName +'" '+
52
-	                							' cronExpression="'+ row.jobCron +'" '+
53
-	                							' job_desc="'+jobDataMap.job_desc +'" '+
54
-	                							' job_url="'+ jobDataMap.job_url +'" '+
55
-	                							' handleName="'+ jobDataMap.handleName +'" '+
87
+	                			var html = '<p id="'+ row.id +'" '+
88
+	                							' jobGroup="'+ row.jobGroup +'" '+
89
+	                							' jobName="'+ row.jobName +'" '+
90
+	                							' jobCron="'+ row.jobCron +'" '+
91
+	                							' jobDesc="'+ row.jobDesc +'" '+
92
+	                							' jobClass="'+ row.jobClass +'" '+
93
+	                							' jobData="'+ row.jobData +'" '+
94
+	                							' author="'+ row.author +'" '+
95
+	                							' alarmEmail="'+ row.alarmEmail +'" '+
96
+	                							' alarmThreshold="'+ row.alarmThreshold +'" '+
97
+	                							' handler_params="'+jobDataMap.handler_params +'" '+
98
+	                							' handler_address="'+ jobDataMap.handler_address +'" '+
99
+	                							' handler_name="'+ jobDataMap.handler_name +'" '+
56
 	                							'>'+
100
 	                							'>'+
57
 	                					pause_resume +
101
 	                					pause_resume +
58
 										'<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行</button>  '+
102
 										'<button class="btn btn-info btn-xs job_operate" type="job_trigger" type="button">执行</button>  '+
59
-										'<button class="btn btn-info btn-xs update" type="button">更新corn</button>  '+
60
-									  	'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>  '+
103
+										'<button class="btn btn-warning btn-xs update" type="button">编辑</button><br> '+
61
 									  	'<button class="btn btn-warning btn-xs" type="job_del" type="button" '+
104
 									  	'<button class="btn btn-warning btn-xs" type="job_del" type="button" '+
62
-									  		'onclick="javascript:window.open(\'' + logUrl + '\')" >查看日志</button>'+
105
+									  		'onclick="javascript:window.open(\'' + logUrl + '\')" >查看日志</button> '+
106
+								  		'<button class="btn btn-danger btn-xs job_operate" type="job_del" type="button">删除</button>  '+
63
 									'</p>';
107
 									'</p>';
64
 									
108
 									
65
 	                			
109
 	                			
68
 	                	}
112
 	                	}
69
 	                }
113
 	                }
70
 	            ],
114
 	            ],
71
-	    "searching": false,
72
-	    "ordering": true,
73
 		"language" : {
115
 		"language" : {
74
 			"sProcessing" : "处理中...",
116
 			"sProcessing" : "处理中...",
75
 			"sLengthMenu" : "每页 _MENU_ 条记录",
117
 			"sLengthMenu" : "每页 _MENU_ 条记录",
96
 		}
138
 		}
97
 	});
139
 	});
98
 	
140
 	
141
+	// 日志弹框提示
142
+	$('#job_list').on('click', '.logTips', function(){
143
+		var msg = $(this).find('span').html();
144
+		ComAlertTec.show(msg);
145
+	});
146
+	
99
 	// 搜索按钮
147
 	// 搜索按钮
100
 	$('#searchBtn').on('click', function(){
148
 	$('#searchBtn').on('click', function(){
101
 		jobTable.fnDraw();
149
 		jobTable.fnDraw();
108
 		var type = $(this).attr("type");
156
 		var type = $(this).attr("type");
109
 		if ("job_pause" == type) {
157
 		if ("job_pause" == type) {
110
 			typeName = "暂停";
158
 			typeName = "暂停";
111
-			url = base_url + "/job/pause";
159
+			url = base_url + "/jobinfo/pause";
112
 		} else if ("job_resume" == type) {
160
 		} else if ("job_resume" == type) {
113
 			typeName = "恢复";
161
 			typeName = "恢复";
114
-			url = base_url + "/job/resume";
162
+			url = base_url + "/jobinfo/resume";
115
 		} else if ("job_del" == type) {
163
 		} else if ("job_del" == type) {
116
 			typeName = "删除";
164
 			typeName = "删除";
117
-			url = base_url + "/job/remove";
165
+			url = base_url + "/jobinfo/remove";
118
 		} else if ("job_trigger" == type) {
166
 		} else if ("job_trigger" == type) {
119
-			typeName = "执行一次";
120
-			url = base_url + "/job/trigger";
167
+			typeName = "执行";
168
+			url = base_url + "/jobinfo/trigger";
121
 		} else {
169
 		} else {
122
 			return;
170
 			return;
123
 		}
171
 		}
124
 		
172
 		
125
-		var name = $(this).parent('p').attr("jobName");
173
+		var jobGroup = $(this).parent('p').attr("jobGroup");
174
+		var jobName = $(this).parent('p').attr("jobName");
126
 		
175
 		
127
 		ComConfirm.show("确认" + typeName + "?", function(){
176
 		ComConfirm.show("确认" + typeName + "?", function(){
128
 			$.ajax({
177
 			$.ajax({
129
 				type : 'POST',
178
 				type : 'POST',
130
 				url : url,
179
 				url : url,
131
 				data : {
180
 				data : {
132
-					"triggerKeyName" :	name
181
+					"jobGroup" : jobGroup,
182
+					"jobName"  : jobName
133
 				},
183
 				},
134
 				dataType : "json",
184
 				dataType : "json",
135
 				success : function(data){
185
 				success : function(data){
162
         errorClass : 'help-block',
212
         errorClass : 'help-block',
163
         focusInvalid : true,  
213
         focusInvalid : true,  
164
         rules : {  
214
         rules : {  
165
-        	triggerKeyName : {  
215
+        	jobName : {  
166
         		required : true ,
216
         		required : true ,
167
                 minlength: 4,
217
                 minlength: 4,
168
                 maxlength: 100,
218
                 maxlength: 100,
169
                 myValid01:true
219
                 myValid01:true
170
             },  
220
             },  
171
-            cronExpression : {  
221
+            jobCron : {  
172
             	required : true ,
222
             	required : true ,
173
                 maxlength: 100
223
                 maxlength: 100
174
             },  
224
             },  
175
-            job_desc : {  
225
+            jobDesc : {  
176
             	required : true ,
226
             	required : true ,
177
                 maxlength: 200
227
                 maxlength: 200
178
             },
228
             },
179
-            job_url : {
229
+            handler_address : {
180
             	required : true ,
230
             	required : true ,
181
                 maxlength: 200
231
                 maxlength: 200
182
             },
232
             },
183
-            handleName : {
233
+            handler_name : {
184
             	required : true ,
234
             	required : true ,
185
                 maxlength: 200
235
                 maxlength: 200
236
+            },
237
+            author : {
238
+            	required : true ,
239
+                maxlength: 200
240
+            },
241
+            alarm_email : {
242
+            	required : true ,
243
+                maxlength: 200
244
+            },
245
+            alarm_threshold : {
246
+            	required : true ,
247
+            	digits:true
186
             }
248
             }
187
         }, 
249
         }, 
188
         messages : {  
250
         messages : {  
189
-        	triggerKeyName : {  
190
-        		required :"请输入“任务Key”."  ,
191
-                minlength:"“任务Key”长度不应低于4位",
192
-                maxlength:"“任务Key”长度不应超过100位"
251
+        	jobName : {  
252
+        		required :"请输入“任务名”"  ,
253
+                minlength:"“任务”长度不应低于4位",
254
+                maxlength:"“任务”长度不应超过100位"
193
             },  
255
             },  
194
-            cronExpression : {
195
-            	required :"请输入“任务Corn”."  ,
196
-                maxlength:"“任务Corn”长度不应超过100位"
256
+            jobCron : {
257
+            	required :"请输入“Corn”."  ,
258
+                maxlength:"“Corn”长度不应超过100位"
197
             },  
259
             },  
198
-            job_desc : {
260
+            jobDesc : {
199
             	required :"请输入“任务描述”."  ,
261
             	required :"请输入“任务描述”."  ,
200
                 maxlength:"“任务描述”长度不应超过200位"
262
                 maxlength:"“任务描述”长度不应超过200位"
201
             },  
263
             },  
202
-            job_url : {
203
-            	required :"请输入“任务URL”."  ,
204
-                maxlength:"“任务URL”长度不应超过200位"
264
+            handler_address : {
265
+            	required :"请输入“远程-机器地址”."  ,
266
+                maxlength:"“远程-机器地址”长度不应超过200位"
205
             },
267
             },
206
-            handleName : {
207
-            	required : "请输入“任务handler”."  ,
208
-                maxlength: "“任务handler”长度不应超过200位"
268
+            handler_name : {
269
+            	required : "请输入“远程-执行器”."  ,
270
+                maxlength: "“远程-执行器”长度不应超过200位"
271
+            },
272
+            author : {
273
+            	required : "请输入“负责人”."  ,
274
+                maxlength: "“负责人”长度不应超过50位"
275
+            },
276
+            alarm_email : {
277
+            	required : "请输入“报警邮件”."  ,
278
+                maxlength: "“报警邮件”长度不应超过200位"
279
+            },
280
+            alarm_threshold : {
281
+            	required : "请输入“报警阈值”."  ,
282
+            	digits:"阀值应该为整数."
209
             }
283
             }
210
         }, 
284
         }, 
211
 		highlight : function(element) {  
285
 		highlight : function(element) {  
219
             element.parent('div').append(error);  
293
             element.parent('div').append(error);  
220
         },
294
         },
221
         submitHandler : function(form) {
295
         submitHandler : function(form) {
222
-        	
223
-        	var triggerKeyName = $('#addModal input[name="triggerKeyName"]').val();
224
-        	var cronExpression = $('#addModal input[name="cronExpression"]').val();
225
-        	var job_desc = $('#addModal input[name="job_desc"]').val();
226
-        	var job_url = $('#addModal input[name="job_url"]').val();
227
-        	var handleName = $('#addModal input[name="handleName"]').val();
228
-        	
229
-        	var paramStr = 'triggerKeyName=' + triggerKeyName + 
230
-        		'&cronExpression=' + cronExpression + 
231
-        		'&job_desc=' + job_desc +
232
-        		'&job_url=' + job_url +
233
-        		'&handleName=' + handleName;
234
-        	
235
-        	var ifFin = true;
236
-        	$('#addModal .newParam').each(function(){
237
-        		ifFin = false;
238
-        		var key = $(this).find('input[name="key"]').val();
239
-        		var value = $(this).find('input[name="value"]').val();
240
-        		if (!key) {
241
-        			ComAlert.show(2, "新增参数key不可为空");
242
-        			return;
243
-				} else {
244
-					if(!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(key)){
245
-						ComAlert.show(2, "新增参数key不合法, 只支持英文字母开头,只含有英文字母、数字和下划线");
246
-	        			return;
247
-					}
248
-				}
249
-        		paramStr += "&" + key + "=" + value;
250
-        		ifFin = true;
251
-        	});
252
-        	
253
-        	if(ifFin){
254
-        		$.post(base_url + "/job/add", paramStr, function(data, status) {
255
-        			if (data.code == "200") {
256
-        				ComAlert.show(1, "新增调度任务成功", function(){
257
-        					window.location.reload();
258
-        				});
259
-        			} else {
260
-        				if (data.msg) {
261
-        					ComAlert.show(2, data.msg);
262
-        				} else {
263
-        					ComAlert.show(2, "新增失败");
264
-        				}
265
-        			}
266
-        		});
267
-        	}
296
+        	$.post(base_url + "/jobinfo/add",  $("#addModal .form").serialize(), function(data, status) {
297
+    			if (data.code == "200") {
298
+    				ComAlert.show(1, "新增调度任务成功", function(){
299
+    					ComAlert.show(1, "新增任务成功");
300
+    					jobTable.fnDraw();
301
+    				});
302
+    			} else {
303
+    				if (data.msg) {
304
+    					ComAlert.show(2, data.msg);
305
+    				} else {
306
+    					ComAlert.show(2, "新增失败");
307
+    				}
308
+    			}
309
+    		});
268
 		}
310
 		}
269
 	});
311
 	});
270
 	$("#addModal").on('hide.bs.modal', function () {
312
 	$("#addModal").on('hide.bs.modal', function () {
273
 		$("#addModal .form .form-group").removeClass("has-error");
315
 		$("#addModal .form .form-group").removeClass("has-error");
274
 	});
316
 	});
275
 	
317
 	
276
-	// 新增-添加参数
277
-	$("#addModal .addParam").on('click', function () {
278
-		var html = '<div class="form-group newParam">'+
279
-				'<label for="lastname" class="col-sm-2 control-label">参数&nbsp;<button class="btn btn-danger btn-xs removeParam" type="button">移除</button></label>'+
280
-				'<div class="col-sm-4"><input type="text" class="form-control" name="key" placeholder="请输入参数key[将会强转为String]" maxlength="200" /></div>'+
281
-				'<div class="col-sm-6"><input type="text" class="form-control" name="value" placeholder="请输入参数value[将会强转为String]" maxlength="200" /></div>'+
282
-			'</div>';
283
-		$(this).parents('.form-group').parent().append(html);
284
-		
285
-		$("#addModal .removeParam").on('click', function () {
286
-			$(this).parents('.form-group').remove();
287
-		});
288
-	});
318
+	// 远程任务/本地任务,切换
319
+	$("#addModal select[name='jobClass']").change(function() {
320
+		//console.log($(this).val());
321
+		console.log( $(this).val().indexOf('HttpJobBean') );
322
+		if($(this).val().indexOf('HttpJobBean') > -1){
323
+			$(".remote_panel").show();	// remote
324
+		} else if($(this).val().indexOf('HttpJobBean') == -1){
325
+			$(".remote_panel").hide();	// local
326
+		}
327
+    });
289
 	
328
 	
290
 	// 更新
329
 	// 更新
291
 	$("#job_list").on('click', '.update',function() {
330
 	$("#job_list").on('click', '.update',function() {
376
 		$("#updateModal .form")[0].reset()
415
 		$("#updateModal .form")[0].reset()
377
 	});
416
 	});
378
 	
417
 	
418
+	
419
+	/*
420
+	// 新增-添加参数
421
+	$("#addModal .addParam").on('click', function () {
422
+		var html = '<div class="form-group newParam">'+
423
+				'<label for="lastname" class="col-sm-2 control-label">参数&nbsp;<button class="btn btn-danger btn-xs removeParam" type="button">移除</button></label>'+
424
+				'<div class="col-sm-4"><input type="text" class="form-control" name="key" placeholder="请输入参数key[将会强转为String]" maxlength="200" /></div>'+
425
+				'<div class="col-sm-6"><input type="text" class="form-control" name="value" placeholder="请输入参数value[将会强转为String]" maxlength="200" /></div>'+
426
+			'</div>';
427
+		$(this).parents('.form-group').parent().append(html);
428
+		
429
+		$("#addModal .removeParam").on('click', function () {
430
+			$(this).parents('.form-group').remove();
431
+		});
432
+	});
433
+	*/
379
 });
434
 });

+ 1 - 0
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js Просмотреть файл

33
             		},
33
             		},
34
 	                { "data": 'jobName'},
34
 	                { "data": 'jobName'},
35
 	                { "data": 'jobCron', "visible" : false},
35
 	                { "data": 'jobCron', "visible" : false},
36
+	                { "data": 'jobDesc', "visible" : false},
36
 	                { "data": 'jobClass', "visible" : false},
37
 	                { "data": 'jobClass', "visible" : false},
37
 	                { 
38
 	                { 
38
 	                	"data": 'jobData',
39
 	                	"data": 'jobData',

+ 4 - 4
xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobInfoTest.java Просмотреть файл

21
 	
21
 	
22
 	@Test
22
 	@Test
23
 	public void pageList(){
23
 	public void pageList(){
24
-		List<XxlJobInfo> list = xxlJobInfoDao.pageList(0, 20, null, null, null);
25
-		int list_count = xxlJobInfoDao.pageListCount(0, 20, null, null, null);
24
+		List<XxlJobInfo> list = xxlJobInfoDao.pageList(0, 20, null, null);
25
+		int list_count = xxlJobInfoDao.pageListCount(0, 20, null, null);
26
 		
26
 		
27
 		System.out.println(list);
27
 		System.out.println(list);
28
 		System.out.println(list_count);
28
 		System.out.println(list_count);
39
 		System.out.println(count);
39
 		System.out.println(count);
40
 		System.out.println(info.getId());
40
 		System.out.println(info.getId());
41
 		
41
 		
42
-		XxlJobInfo item = xxlJobInfoDao.load("job_name");
42
+		XxlJobInfo item = xxlJobInfoDao.load(null ,"job_name");
43
 		System.out.println(item);
43
 		System.out.println(item);
44
 	}
44
 	}
45
 	
45
 	
46
 	@Test
46
 	@Test
47
 	public void update(){
47
 	public void update(){
48
-		XxlJobInfo item = xxlJobInfoDao.load("job_name");
48
+		XxlJobInfo item = xxlJobInfoDao.load(null ,"job_name");
49
 		
49
 		
50
 		item.setJobCron("jobCron2");
50
 		item.setJobCron("jobCron2");
51
 		item.setJobData("jobData2");
51
 		item.setJobData("jobData2");

+ 2 - 2
xxl-job-admin/src/test/java/com/xxl/job/dao/impl/XxlJobLogTest.java Просмотреть файл

57
 	
57
 	
58
 	@Test
58
 	@Test
59
 	public void pageList(){
59
 	public void pageList(){
60
-		List<XxlJobLog> list = xxlJobLogDao.pageList(0, 20, null, null, null);
61
-		int list_count = xxlJobLogDao.pageListCount(0, 20, null, null, null);
60
+		List<XxlJobLog> list = xxlJobLogDao.pageList(0, 20, null, null, null, null);
61
+		int list_count = xxlJobLogDao.pageListCount(0, 20, null, null, null, null);
62
 		
62
 		
63
 		System.out.println(list);
63
 		System.out.println(list);
64
 		System.out.println(list_count);
64
 		System.out.println(list_count);

+ 3 - 4
xxl-job-client-demo/src/main/java/com/xxl/job/service/handler/DemoJobHandler.java Просмотреть файл

1
 package com.xxl.job.service.handler;
1
 package com.xxl.job.service.handler;
2
 
2
 
3
-import java.util.Map;
4
 import java.util.Random;
3
 import java.util.Random;
5
 import java.util.concurrent.TimeUnit;
4
 import java.util.concurrent.TimeUnit;
6
 
5
 
20
 	private static transient Logger logger = LoggerFactory.getLogger(DemoJobHandler.class);
19
 	private static transient Logger logger = LoggerFactory.getLogger(DemoJobHandler.class);
21
 	
20
 	
22
 	public DemoJobHandler() {
21
 	public DemoJobHandler() {
23
-		HandlerRepository.regist(DemoJobHandler.class.getName(), this);
22
+		HandlerRepository.regist("demoJobHandler", this);
24
 	}
23
 	}
25
 	
24
 	
26
 	@Override
25
 	@Override
27
-	public JobHandleStatus handle(Map<String, String> param) throws Exception {
28
-		logger.info(" ... param:{}", param);
26
+	public JobHandleStatus handle(String... params) throws Exception {
27
+		logger.info(" ... params:" + params);
29
 		TimeUnit.SECONDS.sleep(new Random().nextInt(5));
28
 		TimeUnit.SECONDS.sleep(new Random().nextInt(5));
30
 		return JobHandleStatus.SUCCESS;
29
 		return JobHandleStatus.SUCCESS;
31
 	}
30
 	}

+ 23 - 124
xxl-job-client/src/main/java/com/xxl/job/client/handler/HandlerRepository.java Просмотреть файл

1
 package com.xxl.job.client.handler;
1
 package com.xxl.job.client.handler;
2
 
2
 
3
-import java.io.PrintWriter;
4
-import java.io.StringWriter;
5
 import java.util.HashMap;
3
 import java.util.HashMap;
6
 import java.util.Map;
4
 import java.util.Map;
7
 import java.util.concurrent.ConcurrentHashMap;
5
 import java.util.concurrent.ConcurrentHashMap;
8
-import java.util.concurrent.LinkedBlockingQueue;
9
-import java.util.concurrent.TimeUnit;
10
 
6
 
11
 import org.slf4j.Logger;
7
 import org.slf4j.Logger;
12
 import org.slf4j.LoggerFactory;
8
 import org.slf4j.LoggerFactory;
13
 
9
 
14
-import com.xxl.job.client.handler.IJobHandler.JobHandleStatus;
15
 import com.xxl.job.client.util.HttpUtil;
10
 import com.xxl.job.client.util.HttpUtil;
16
 import com.xxl.job.client.util.JacksonUtil;
11
 import com.xxl.job.client.util.JacksonUtil;
17
 
12
 
18
-
19
 /**
13
 /**
20
  * handler repository
14
  * handler repository
21
  * @author xuxueli 2015-12-19 19:28:44
15
  * @author xuxueli 2015-12-19 19:28:44
23
 public class HandlerRepository {
17
 public class HandlerRepository {
24
 	private static Logger logger = LoggerFactory.getLogger(HandlerRepository.class);
18
 	private static Logger logger = LoggerFactory.getLogger(HandlerRepository.class);
25
 	
19
 	
26
-	public static final String job_desc = "job_desc";
27
-	public static final String job_url = "job_url";
28
-	public static final String handleName = "handleName";
29
-	public static final String triggerLogId = "triggerLogId";
30
-	public static final String triggerLogUrl = "triggerLogUrl";
31
-
32
-	// handler class map
33
-	private static ConcurrentHashMap<String, IJobHandler> handlerClassMap = new ConcurrentHashMap<String, IJobHandler>();
34
-	// handler thread map
35
-	private static ConcurrentHashMap<String, HandlerThread> handlerTreadMap = new ConcurrentHashMap<String, HandlerThread>();
36
-	// handler date queue map
37
-	private static ConcurrentHashMap<String, LinkedBlockingQueue<Map<String, String>>> handlerDataQueueMap = new ConcurrentHashMap<String, LinkedBlockingQueue<Map<String, String>>>();
20
+	public static final String HANDLER_ADDRESS = "handler_address";
21
+	public static final String HANDLER_NAME = "handler_name";
22
+	public static final String HANDLER_PARAMS = "handler_params";
23
+	
24
+	public static final String TRIGGER_LOG_ID = "trigger_log_id";
25
+	public static final String TRIGGER_LOG_URL = "trigger_log_url";
26
+	
27
+	public static ConcurrentHashMap<String, HandlerThread> handlerTreadMap = new ConcurrentHashMap<String, HandlerThread>();
38
 	
28
 	
39
 	// regist handler
29
 	// regist handler
40
 	public static void regist(String handleName, IJobHandler handler){
30
 	public static void regist(String handleName, IJobHandler handler){
41
-		handlerClassMap.put(handleName, handler);
42
-		LinkedBlockingQueue<Map<String, String>> handlerDateQueue = new LinkedBlockingQueue<Map<String, String>>();
43
-		handlerDataQueueMap.put(handleName, handlerDateQueue);
44
-		HandlerThread handlerThread = new HandlerThread(handleName);
31
+		HandlerThread handlerThread = new HandlerThread(handler);
45
 		handlerThread.start();
32
 		handlerThread.start();
46
-		handlerTreadMap.put(handleName, handlerThread);
47
-		logger.info(">>>>>>>>>>> xxl-job regist handler success, handleName:{}, handler:{}, handlerDateQueue:{}, handlerThread:{}", 
48
-				new Object[]{handleName, handler, handlerDateQueue, handlerThread});
49
-	}
50
-	
51
-	// create handler thread
52
-	static class HandlerThread extends Thread{
53
-		private String _handleName;
54
-		public HandlerThread(String _handleName) {
55
-			this._handleName = _handleName;
56
-		}
57
-		public boolean isValid = true;
58
-		public void stopThread(){
59
-			isValid = false;
60
-		}
61
-		@Override
62
-		public void run() {
63
-			while (isValid) {
64
-				LinkedBlockingQueue<Map<String, String>> handlerDateQueue = handlerDataQueueMap.get(_handleName);
65
-				Map<String, String> handlerData = handlerDateQueue.poll();
66
-				if (handlerData!=null) {
67
-					// handle job
68
-					JobHandleStatus _status = JobHandleStatus.FAIL;
69
-					String _msg = null;
70
-					try {
71
-						IJobHandler handler = handlerClassMap.get(_handleName);
72
-						_status = handler.handle(handlerData);
73
-					} catch (Exception e) {
74
-						e.printStackTrace();
75
-						_status = JobHandleStatus.FAIL;
76
-						StringWriter out = new StringWriter();
77
-						e.printStackTrace(new PrintWriter(out));
78
-						_msg = out.toString();
79
-					}
80
-
81
-					// callback handler info
82
-					String callback_response[] = null;
83
-					try {
84
-						String _triggerLogUrl = handlerData.get(HandlerRepository.triggerLogUrl);
85
-						HashMap<String, String> params = new HashMap<String, String>();
86
-						params.put(HandlerRepository.triggerLogId, handlerData.get(HandlerRepository.triggerLogId));
87
-						params.put(HttpUtil.status, _status.name());
88
-						params.put(HttpUtil.msg, _msg);
89
-						callback_response = HttpUtil.post(_triggerLogUrl, params);
90
-					} catch (Exception e) {
91
-						e.printStackTrace();
92
-					}
93
-					logger.info("<<<<<<<<<<< xxl-job thread handle, handlerData:{}, callback_status:{}, callback_msg:{}, callback_response:{}, thread:{}", 
94
-							new Object[]{handlerData, _status, _msg, callback_response, this});
95
-				} else {
96
-					try {
97
-						TimeUnit.MILLISECONDS.sleep(200);
98
-					} catch (InterruptedException e) {
99
-						e.printStackTrace();
100
-					}
101
-				}
102
-			}
103
-		}
33
+		handlerTreadMap.put(handleName, handlerThread);	// putIfAbsent
34
+		logger.info(">>>>>>>>>>> xxl-job regist handler success, handleName:{}, handler:{}", new Object[]{handleName, handler});
104
 	}
35
 	}
105
 	
36
 	
106
 	// handler push to queue
37
 	// handler push to queue
107
 	public static String pushHandleQueue(Map<String, String> _param) {
38
 	public static String pushHandleQueue(Map<String, String> _param) {
39
+		logger.info(">>>>>>>>>>> xxl-job pushHandleQueue start, _param:{}", new Object[]{_param});
108
 		
40
 		
109
-		// resuolt
41
+		// result
110
 		String _status = HttpUtil.FAIL;
42
 		String _status = HttpUtil.FAIL;
111
 		String _msg = "";
43
 		String _msg = "";
44
+		
112
 		// push data to queue
45
 		// push data to queue
113
-		String _handleName = _param.get(HandlerRepository.handleName);
114
-		int _triggerLogId = Integer.valueOf(_param.get(HandlerRepository.triggerLogId));	 // 次数应校验,停止队列功能为开发
115
-		try {
116
-			if (_handleName!=null && _handleName.trim().length()>0) {
117
-				IJobHandler handler = handlerClassMap.get(_handleName);
118
-				if (handler != null) {
119
-					// push data to handler queue
120
-					LinkedBlockingQueue<Map<String, String>> handlerDateQueue = handlerDataQueueMap.get(_handleName);
121
-					if (handlerDateQueue == null) {
122
-						handlerDateQueue = new LinkedBlockingQueue<Map<String, String>>();
123
-						handlerDataQueueMap.put(_handleName, handlerDateQueue);
124
-						logger.info(">>>>>>>>>>> xxl-job handler lazy fresh handlerDateQueue, _handleName:{}, handler:{}, handlerDateQueue:{}", 
125
-								new Object[]{_handleName, handler, handlerDateQueue});
126
-					}
127
-					// check handler thread
128
-					HandlerThread handlerThreadOld = handlerTreadMap.get(_handleName);
129
-					if (!handlerThreadOld.isAlive()) {
130
-						handlerThreadOld.stopThread();
131
-						HandlerThread handlerThread = new HandlerThread(_handleName);
132
-						handlerThread.start();
133
-						handlerTreadMap.put(_handleName, handlerThread);
134
-						logger.info(">>>>>>>>>>> xxl-job handler lazy fresh thread, _handleName:{}, handler:{}, handlerThread:{}", 
135
-								new Object[]{_handleName, handler, handlerThread});
136
-					}
137
-					// push to queue
138
-					handlerDateQueue.offer(_param);
139
-					_status = HttpUtil.SUCCESS;
140
-				}
141
-			}
142
-		} catch (Exception e) {
143
-			e.printStackTrace();
144
-			StringWriter out = new StringWriter();
145
-			e.printStackTrace(new PrintWriter(out));
146
-			_status = HttpUtil.FAIL;
147
-			_msg = out.toString();
46
+		HandlerThread handlerThread = handlerTreadMap.get(_param.get(HandlerRepository.HANDLER_NAME));
47
+		if (handlerThread != null) {
48
+			handlerThread.pushData(_param);
49
+			_status = HttpUtil.SUCCESS;
50
+		} else {
51
+			_msg = "handler not found.";
148
 		}
52
 		}
149
-		logger.info(">>>>>>>>>>> xxl-job pushHandleQueue, _handleName:{}, _triggerLogId:{}, _param:{}, _status:{}, _msg:{}", 
150
-				new Object[]{_handleName, _triggerLogId, _param, _status, _msg});
151
 		
53
 		
152
 		HashMap<String, String> triggerData = new HashMap<String, String>();
54
 		HashMap<String, String> triggerData = new HashMap<String, String>();
55
+		triggerData.put(HandlerRepository.TRIGGER_LOG_ID, _param.get(HandlerRepository.TRIGGER_LOG_ID));
153
 		triggerData.put(HttpUtil.status, _status);
56
 		triggerData.put(HttpUtil.status, _status);
154
 		triggerData.put(HttpUtil.msg, _msg);
57
 		triggerData.put(HttpUtil.msg, _msg);
155
-		return JacksonUtil.writeValueAsString(triggerData);
156
 		
58
 		
157
-		/**
158
-		 * trigger-log : 
159
-		 * 		trigger side : store trigger-info >> trigger request >> update trigger-response-status
160
-		 * 		job side : handler trigger >> update trigger-result
161
-		 */
59
+		logger.info(">>>>>>>>>>> xxl-job pushHandleQueue end, triggerData:{}", new Object[]{triggerData});
60
+		return JacksonUtil.writeValueAsString(triggerData);
162
 	}
61
 	}
163
 	
62
 	
164
 }
63
 }

+ 1 - 3
xxl-job-client/src/main/java/com/xxl/job/client/handler/IJobHandler.java Просмотреть файл

1
 package com.xxl.job.client.handler;
1
 package com.xxl.job.client.handler;
2
 
2
 
3
-import java.util.Map;
4
-
5
 /**
3
 /**
6
  * remote job handler
4
  * remote job handler
7
  * @author xuxueli 2015-12-19 19:06:38
5
  * @author xuxueli 2015-12-19 19:06:38
15
 	 * @return 
13
 	 * @return 
16
 	 * @throws Exception
14
 	 * @throws Exception
17
 	 */
15
 	 */
18
-	public abstract JobHandleStatus handle(Map<String, String> param) throws Exception;
16
+	public abstract JobHandleStatus handle(String... params) throws Exception;
19
 	
17
 	
20
 	public enum JobHandleStatus{
18
 	public enum JobHandleStatus{
21
 		/**
19
 		/**