浏览代码

调度信息迁移至DB中

xueli.xue 9 年前
父节点
当前提交
2bc58f34ed

+ 72 - 8
xxl-job-admin/src/main/java/com/xxl/job/controller/JobController.java 查看文件

@@ -7,6 +7,7 @@ import java.util.Map;
7 7
 import java.util.Map.Entry;
8 8
 import java.util.Set;
9 9
 
10
+import javax.annotation.Resource;
10 11
 import javax.servlet.http.HttpServletRequest;
11 12
 
12 13
 import org.apache.commons.lang.StringUtils;
@@ -16,11 +17,15 @@ import org.quartz.SchedulerException;
16 17
 import org.springframework.stereotype.Controller;
17 18
 import org.springframework.ui.Model;
18 19
 import org.springframework.web.bind.annotation.RequestMapping;
20
+import org.springframework.web.bind.annotation.RequestParam;
19 21
 import org.springframework.web.bind.annotation.ResponseBody;
20 22
 
21 23
 import com.xxl.job.client.handler.HandlerRepository;
24
+import com.xxl.job.client.util.JacksonUtil;
22 25
 import com.xxl.job.core.model.ReturnT;
26
+import com.xxl.job.core.model.XxlJobInfo;
23 27
 import com.xxl.job.core.util.DynamicSchedulerUtil;
28
+import com.xxl.job.dao.IXxlJobInfoDao;
24 29
 import com.xxl.job.service.job.HttpJobBean;
25 30
 
26 31
 /**
@@ -31,19 +36,47 @@ import com.xxl.job.service.job.HttpJobBean;
31 36
 @RequestMapping("/job")
32 37
 public class JobController {
33 38
 	
39
+	@Resource
40
+	private IXxlJobInfoDao xxlJobInfoDao;
41
+	
34 42
 	@RequestMapping
35 43
 	public String index(Model model) {
36
-		List<Map<String, Object>> jobList = DynamicSchedulerUtil.getJobList();
37
-		model.addAttribute("jobList", jobList);
44
+		//List<Map<String, Object>> jobList = DynamicSchedulerUtil.getJobList();
45
+		//model.addAttribute("jobList", jobList);
38 46
 		return "job/index";
39 47
 	}
40 48
 	
49
+	@RequestMapping("/pageList")
50
+	@ResponseBody
51
+	public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,  
52
+			@RequestParam(required = false, defaultValue = "10") int length,
53
+			String jobName, String filterTime) {
54
+		
55
+		// page list
56
+		List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobName, null, null);
57
+		int list_count = xxlJobInfoDao.pageListCount(start, length, jobName, null, null);
58
+		
59
+		// fill job info
60
+		if (list!=null && list.size()>0) {
61
+			for (XxlJobInfo jobInfo : list) {
62
+				DynamicSchedulerUtil.fillJobInfo(jobInfo);
63
+			}
64
+		}
65
+		
66
+		// package result
67
+		Map<String, Object> maps = new HashMap<String, Object>();
68
+	    maps.put("recordsTotal", list_count);		// 总记录数
69
+	    maps.put("recordsFiltered", list_count);	// 过滤后的总记录数
70
+	    maps.put("data", list);  					// 分页列表
71
+		return maps;
72
+	}
73
+	
41 74
 	@RequestMapping("/add")
42 75
 	@ResponseBody
43 76
 	public ReturnT<String> add(HttpServletRequest request) {
44 77
 		String triggerKeyName = null;
45 78
 		String cronExpression = null;
46
-		Map<String, Object> jobData = new HashMap<String, Object>();
79
+		Map<String, String> jobData = new HashMap<String, String>();
47 80
 		
48 81
 		try {
49 82
 			request.setCharacterEncoding("utf-8");
@@ -58,7 +91,7 @@ public class JobController {
58 91
 			} else if (param.getKey().equals("cronExpression")) {
59 92
 				cronExpression = param.getValue()[0];
60 93
 			} else {
61
-				jobData.put(param.getKey(), param.getValue().length>0?param.getValue()[0]:param.getValue());
94
+				jobData.put(param.getKey(), (String) (param.getValue().length>0?param.getValue()[0]:param.getValue()));
62 95
 			}
63 96
 		}
64 97
 		
@@ -90,10 +123,19 @@ public class JobController {
90 123
 		Class<? extends Job> jobClass = HttpJobBean.class;
91 124
 		
92 125
 		try {
93
-			boolean result = DynamicSchedulerUtil.addJob(triggerKeyName, cronExpression, jobClass, jobData);
126
+			// add job 2 quartz
127
+			boolean result = DynamicSchedulerUtil.addJob(triggerKeyName, cronExpression, jobClass, null);
94 128
 			if (!result) {
95 129
 				return new ReturnT<String>(500, "任务ID重复,请更换确认");
96 130
 			}
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
+			
97 139
 			return ReturnT.SUCCESS;
98 140
 		} catch (SchedulerException e) {
99 141
 			e.printStackTrace();
@@ -117,6 +159,13 @@ public class JobController {
117 159
 		}
118 160
 		try {
119 161
 			DynamicSchedulerUtil.rescheduleJob(triggerKeyName, cronExpression);
162
+			
163
+			// update
164
+			XxlJobInfo jobInfo = xxlJobInfoDao.load(triggerKeyName);
165
+			if (jobInfo!=null) {
166
+				jobInfo.setJobCron(cronExpression);
167
+				xxlJobInfoDao.update(jobInfo);
168
+			}
120 169
 			return ReturnT.SUCCESS;
121 170
 		} catch (SchedulerException e) {
122 171
 			e.printStackTrace();
@@ -128,12 +177,15 @@ public class JobController {
128 177
 	@ResponseBody
129 178
 	public ReturnT<String> remove(String triggerKeyName) {
130 179
 		try {
131
-			DynamicSchedulerUtil.removeJob(triggerKeyName);
132
-			return ReturnT.SUCCESS;
180
+			if (triggerKeyName!=null) {
181
+				DynamicSchedulerUtil.removeJob(triggerKeyName);
182
+				xxlJobInfoDao.delete(triggerKeyName);
183
+				return ReturnT.SUCCESS;
184
+			}
133 185
 		} catch (SchedulerException e) {
134 186
 			e.printStackTrace();
135
-			return ReturnT.FAIL;
136 187
 		}
188
+		return ReturnT.FAIL;
137 189
 	}
138 190
 	
139 191
 	@RequestMapping("/pause")
@@ -141,6 +193,12 @@ public class JobController {
141 193
 	public ReturnT<String> pause(String triggerKeyName) {
142 194
 		try {
143 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
+			}
144 202
 			return ReturnT.SUCCESS;
145 203
 		} catch (SchedulerException e) {
146 204
 			e.printStackTrace();
@@ -153,6 +211,12 @@ public class JobController {
153 211
 	public ReturnT<String> resume(String triggerKeyName) {
154 212
 		try {
155 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
+			}
156 220
 			return ReturnT.SUCCESS;
157 221
 		} catch (SchedulerException e) {
158 222
 			e.printStackTrace();

+ 36 - 2
xxl-job-admin/src/main/java/com/xxl/job/core/util/DynamicSchedulerUtil.java 查看文件

@@ -23,11 +23,14 @@ import org.quartz.Trigger.TriggerState;
23 23
 import org.quartz.TriggerBuilder;
24 24
 import org.quartz.TriggerKey;
25 25
 import org.quartz.impl.matchers.GroupMatcher;
26
+import org.quartz.impl.triggers.CronTriggerImpl;
26 27
 import org.slf4j.Logger;
27 28
 import org.slf4j.LoggerFactory;
28 29
 import org.springframework.beans.factory.InitializingBean;
29 30
 import org.springframework.util.Assert;
30 31
 
32
+import com.xxl.job.core.model.XxlJobInfo;
33
+import com.xxl.job.dao.IXxlJobInfoDao;
31 34
 import com.xxl.job.dao.IXxlJobLogDao;
32 35
 
33 36
 /**
@@ -43,8 +46,11 @@ public final class DynamicSchedulerUtil implements InitializingBean {
43 46
     public void setXxlJobLogDao(IXxlJobLogDao xxlJobLogDao) {
44 47
 		DynamicSchedulerUtil.xxlJobLogDao = xxlJobLogDao;
45 48
 	}
46
-    public static IXxlJobLogDao getXxlJobLogDao() {
47
-		return xxlJobLogDao;
49
+    // xxlJobInfoDao
50
+    public static IXxlJobInfoDao xxlJobInfoDao;
51
+    @Resource
52
+    public void setXxlJobInfoDao(IXxlJobInfoDao xxlJobInfoDao) {
53
+		DynamicSchedulerUtil.xxlJobInfoDao = xxlJobInfoDao;
48 54
 	}
49 55
     
50 56
     // Scheduler
@@ -90,6 +96,34 @@ public final class DynamicSchedulerUtil implements InitializingBean {
90 96
 		}
91 97
 		return jobList;
92 98
 	}
99
+	
100
+	// fill job info
101
+	public static void fillJobInfo(XxlJobInfo jobInfo) {
102
+		// TriggerKey : name + group
103
+        TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getJobName(), Scheduler.DEFAULT_GROUP);
104
+        JobKey jobKey = new JobKey(jobInfo.getJobName(), Scheduler.DEFAULT_GROUP);
105
+        try {
106
+			Trigger trigger = scheduler.getTrigger(triggerKey);
107
+			JobDetail jobDetail = scheduler.getJobDetail(jobKey);
108
+			TriggerState triggerState = scheduler.getTriggerState(triggerKey);
109
+			
110
+			// parse params
111
+			if (trigger!=null && trigger instanceof CronTriggerImpl) {
112
+				String cronExpression = ((CronTriggerImpl) trigger).getCronExpression();
113
+				jobInfo.setJobCron(cronExpression);
114
+			}
115
+			if (jobDetail!=null) {
116
+				String jobClass = jobDetail.getJobClass().getName();
117
+				jobInfo.setJobClass(jobClass);
118
+			}
119
+			if (triggerState!=null) {
120
+				jobInfo.setJobStatus(triggerState.name());
121
+			}
122
+			
123
+		} catch (SchedulerException e) {
124
+			e.printStackTrace();
125
+		}
126
+	}
93 127
 
94 128
 	// addJob 新增
95 129
     public static boolean addJob(String triggerKeyName, String cronExpression, Class<? extends Job> jobClass, Map<String, Object> jobData) throws SchedulerException {

+ 4 - 0
xxl-job-admin/src/main/java/com/xxl/job/dao/IXxlJobLogDao.java 查看文件

@@ -6,6 +6,10 @@ import java.util.List;
6 6
 
7 7
 import com.xxl.job.core.model.XxlJobLog;
8 8
 
9
+/**
10
+ * job log
11
+ * @author xuxueli 2016-1-12 18:03:06
12
+ */
9 13
 public interface IXxlJobLogDao {
10 14
 	
11 15
 	public int save(XxlJobLog xxlJobLog);

+ 4 - 0
xxl-job-admin/src/main/java/com/xxl/job/dao/impl/XxlJobLogDaoImpl.java 查看文件

@@ -12,6 +12,10 @@ import org.springframework.stereotype.Repository;
12 12
 import com.xxl.job.core.model.XxlJobLog;
13 13
 import com.xxl.job.dao.IXxlJobLogDao;
14 14
 
15
+/**
16
+ * job log
17
+ * @author xuxueli 2016-1-12 18:03:06
18
+ */
15 19
 @Repository
16 20
 public class XxlJobLogDaoImpl implements IXxlJobLogDao {
17 21
 	

+ 8 - 10
xxl-job-admin/src/main/java/com/xxl/job/service/job/HttpJobBean.java 查看文件

@@ -3,7 +3,6 @@ package com.xxl.job.service.job;
3 3
 import java.util.Date;
4 4
 import java.util.HashMap;
5 5
 import java.util.Map;
6
-import java.util.Map.Entry;
7 6
 
8 7
 import org.apache.commons.lang.StringUtils;
9 8
 import org.quartz.JobExecutionContext;
@@ -16,6 +15,7 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
16 15
 import com.xxl.job.client.handler.HandlerRepository;
17 16
 import com.xxl.job.client.util.HttpUtil;
18 17
 import com.xxl.job.client.util.JacksonUtil;
18
+import com.xxl.job.core.model.XxlJobInfo;
19 19
 import com.xxl.job.core.model.XxlJobLog;
20 20
 import com.xxl.job.core.util.DynamicSchedulerUtil;
21 21
 import com.xxl.job.core.util.PropertiesUtil;
@@ -27,18 +27,17 @@ import com.xxl.job.core.util.PropertiesUtil;
27 27
 public class HttpJobBean extends QuartzJobBean {
28 28
 	private static Logger logger = LoggerFactory.getLogger(HttpJobBean.class);
29 29
 
30
+	@SuppressWarnings("unchecked")
30 31
 	@Override
31 32
 	protected void executeInternal(JobExecutionContext context)
32 33
 			throws JobExecutionException {
33
-		
34 34
 		String triggerKey = context.getTrigger().getJobKey().getName();
35
+		
35 36
 		// jobDataMap 2 params
36
-		Map<String, Object> jobDataMap = context.getMergedJobDataMap().getWrappedMap();
37 37
 		Map<String, String> params = new HashMap<String, String>();
38
-		if (jobDataMap!=null && jobDataMap.size()>0) {
39
-			for (Entry<String, Object> item : jobDataMap.entrySet()) {
40
-				params.put(item.getKey(), String.valueOf(item.getValue()));
41
-			}
38
+		XxlJobInfo jobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(triggerKey);
39
+		if (jobInfo!=null && jobInfo.getJobData()!=null) {
40
+			params = JacksonUtil.readValue(jobInfo.getJobData(), Map.class);
42 41
 		}
43 42
 		
44 43
 		// corn
@@ -53,7 +52,7 @@ public class HttpJobBean extends QuartzJobBean {
53 52
 		jobLog.setJobName(triggerKey);
54 53
 		jobLog.setJobCron(cornExp);
55 54
 		jobLog.setJobClass(HttpJobBean.class.getName());
56
-		jobLog.setJobData(JacksonUtil.writeValueAsString(params));
55
+		jobLog.setJobData(jobInfo.getJobData());
57 56
 		DynamicSchedulerUtil.xxlJobLogDao.save(jobLog);
58 57
 		logger.info(">>>>>>>>>>> xxl-job trigger start, jobLog:{}", jobLog);
59 58
 		
@@ -70,8 +69,7 @@ public class HttpJobBean extends QuartzJobBean {
70 69
 		jobLog.setTriggerTime(new Date());
71 70
 		jobLog.setTriggerStatus(HttpUtil.FAIL);
72 71
 		jobLog.setTriggerMsg("[responseMsg]:"+responseMsg+"<br>[exceptionMsg]:"+exceptionMsg);
73
-		if (StringUtils.isNotBlank(responseMsg)) {
74
-			@SuppressWarnings("unchecked")
72
+		if (StringUtils.isNotBlank(responseMsg) && responseMsg.indexOf("{")>-1 ) {
75 73
 			Map<String, String> responseMap = JacksonUtil.readValue(responseMsg, Map.class);
76 74
 			if (responseMap!=null && StringUtils.isNotBlank(responseMap.get(HttpUtil.status))) {
77 75
 				jobLog.setTriggerStatus(responseMap.get(HttpUtil.status));

+ 1 - 1
xxl-job-admin/src/main/resources/applicationcontext-database.xml 查看文件

@@ -31,7 +31,7 @@
31 31
 	
32 32
 	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
33 33
 		<property name="dataSource" ref="dataSource" />
34
-		<property name="mapperLocations" value="classpath*:com/xxl/job/core/model/mapper/*.xml"/>
34
+		<property name="mapperLocations" value="classpath*:mybatis-mapper/*.xml"/>
35 35
 	</bean>
36 36
     
37 37
     <!-- scope must be "prototype" when junit -->

xxl-job-admin/src/main/java/com/xxl/job/core/model/mapper/XxlJobLogMapper.xml → xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml 查看文件


+ 0 - 2
xxl-job-admin/src/main/webapp/WEB-INF/template/help.ftl 查看文件

@@ -68,8 +68,6 @@
68 68
 	
69 69
 	<!-- footer -->
70 70
 	<@netCommon.commonFooter />
71
-	<!-- control -->
72
-	<@netCommon.commonControl />
73 71
 </div>
74 72
 <@netCommon.commonScript />
75 73
 </body>

+ 53 - 26
xxl-job-admin/src/main/webapp/WEB-INF/template/job/index.ftl 查看文件

@@ -28,32 +28,53 @@
28 28
 		
29 29
 		<!-- Main content -->
30 30
 	    <section class="content">
31
+	    
32
+	    	<div class="row">
33
+	            <div class="col-xs-4">
34
+	              	<div class="input-group">
35
+	                	<span class="input-group-addon">
36
+	                  		jobName
37
+	                	</span>
38
+	                	<input type="text" class="form-control" id="jobName" value="${jobName}" autocomplete="on" >
39
+	              	</div>
40
+	            </div>
41
+	            <div class="col-xs-2">
42
+	            	<button class="btn btn-block btn-info" id="searchBtn">搜索</button>
43
+	            </div>
44
+	            <div class="col-xs-2">
45
+	            	<button class="btn btn-block btn-success add" type="button">+新增任务</button>
46
+	            </div>
47
+          	</div>
48
+	    	
31 49
 			<div class="row">
32 50
 				<div class="col-xs-12">
33 51
 					<div class="box">
34 52
 			            <div class="box-header">
35 53
 			            	<h3 class="box-title">调度列表</h3>
36
-			            	<button class="btn btn-info btn-xs add" type="button">+新增任务</button>
37 54
 			            </div>
38 55
 			            <div class="box-body">
39 56
 			              	<table id="job_list" class="table table-bordered table-striped">
40 57
 				                <thead>
41 58
 					            	<tr>
42
-					                	<th>调度key</th>
43
-					                  	<th>cron</th>
44
-					                  	<!--<th>类路径</th>-->
59
+					            		<th>id</th>
60
+					                	<th>任务Key</th>
61
+					                  	<th>任务Cron</th>
62
+					                  	<th>任务Class</th>
63
+					                  	<th>状态Status</th>
45 64
 					                  	<th>参数</th>
46
-					                  	<th>状态</th>
65
+					                  	<th>addTime</th>
66
+					                  	<th>updateTime</th>
47 67
 					                  	<th>操作</th>
48 68
 					                </tr>
49 69
 				                </thead>
50 70
 				                <tbody>
71
+				                	<#--
51 72
 			                		<#if jobList?exists && jobList?size gt 0>
52 73
 									<#list jobList as item>
53 74
 									<tr>
54 75
 					            		<td>${item['TriggerKey'].name}</td>
55 76
 					                  	<td>${item['Trigger'].cronExpression}</td>
56
-					                  	<!--<td>${item['JobDetail'].jobClass}</td>-->
77
+					                  	<td>${item['JobDetail'].jobClass}</td>
57 78
 					                  	<td>
58 79
 					                  		<#assign jobDataMap = item['JobDetail'].jobDataMap />
59 80
 					                  		<#if jobDataMap?exists && jobDataMap?keys?size gt 0>
@@ -89,17 +110,10 @@
89 110
 					                </tr>
90 111
 									</#list>
91 112
 									</#if>
113
+									
114
+									-->
92 115
 				                </tbody>
93
-				                <tfoot>
94
-					            	<tr>
95
-					                  	<th>调度key</th>
96
-					                  	<th>cron</th>
97
-					                  	<!--<th>类路径</th>-->
98
-					                  	<th>参数</th>
99
-					                  	<th>状态</th>
100
-					                  	<th>操作</th>
101
-					                </tr>
102
-				                </tfoot>
116
+				                <tfoot></tfoot>
103 117
 							</table>
104 118
 						</div>
105 119
 					</div>
@@ -110,8 +124,6 @@
110 124
 	
111 125
 	<!-- footer -->
112 126
 	<@netCommon.commonFooter />
113
-	<!-- control -->
114
-	<@netCommon.commonControl />
115 127
 </div>
116 128
 
117 129
 <!-- job新增.模态框 -->
@@ -129,19 +141,19 @@
129 141
 					</div>
130 142
 					<div class="form-group">
131 143
 						<label for="lastname" class="col-sm-3 control-label">任务Corn</label>
132
-						<div class="col-sm-9"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn[允许修改]" maxlength="100" ></div>
144
+						<div class="col-sm-9"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn" maxlength="100" ></div>
133 145
 					</div>
134 146
 					<div class="form-group">
135 147
 						<label for="lastname" class="col-sm-3 control-label">任务描述</label>
136
-						<div class="col-sm-9"><input type="text" class="form-control" name="job_desc" placeholder="请输入任务描述[不支持修改]" maxlength="200" ></div>
148
+						<div class="col-sm-9"><input type="text" class="form-control" name="job_desc" placeholder="请输入任务描述" maxlength="200" ></div>
137 149
 					</div>
138 150
 					<div class="form-group">
139 151
 						<label for="lastname" class="col-sm-3 control-label">任务URL</label>
140
-						<div class="col-sm-9"><input type="text" class="form-control" name="job_url" placeholder="请输入任务URL[不支持修改]" maxlength="200" ></div>
152
+						<div class="col-sm-9"><input type="text" class="form-control" name="job_url" placeholder="请输入任务URL" maxlength="200" ></div>
141 153
 					</div>
142 154
 					<div class="form-group">
143 155
 						<label for="lastname" class="col-sm-3 control-label">任务handler</label>
144
-						<div class="col-sm-9"><input type="text" class="form-control" name="handleName" placeholder="请输入任务handler[不支持修改]" maxlength="200" ></div>
156
+						<div class="col-sm-9"><input type="text" class="form-control" name="handleName" placeholder="请输入任务handler" maxlength="200" ></div>
145 157
 					</div>
146 158
 					<div class="form-group">
147 159
 						<div class="col-sm-offset-3 col-sm-9">
@@ -166,12 +178,24 @@
166 178
          	<div class="modal-body">
167 179
 				<form class="form-horizontal form" role="form" >
168 180
 					<div class="form-group">
169
-						<label for="firstname" class="col-sm-2 control-label">任务Key</label>
170
-						<div class="col-sm-10"><input type="text" class="form-control" name="triggerKeyName" placeholder="请输入任务Key" minlength="4" maxlength="100" readonly ></div>
181
+						<label for="firstname" class="col-sm-3 control-label">任务Key</label>
182
+						<div class="col-sm-9"><input type="text" class="form-control" name="triggerKeyName" placeholder="请输入任务Key" minlength="4" maxlength="100" readonly ></div>
183
+					</div>
184
+					<div class="form-group">
185
+						<label for="lastname" class="col-sm-3 control-label">任务Corn</label>
186
+						<div class="col-sm-9"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn" maxlength="100" ></div>
171 187
 					</div>
172 188
 					<div class="form-group">
173
-						<label for="lastname" class="col-sm-2 control-label">任务Corn</label>
174
-						<div class="col-sm-10"><input type="text" class="form-control" name="cronExpression" placeholder="请输入任务Corn" maxlength="100" ></div>
189
+						<label for="lastname" class="col-sm-3 control-label">任务描述</label>
190
+						<div class="col-sm-9"><input type="text" class="form-control" name="job_desc" placeholder="请输入任务描述" maxlength="200" ></div>
191
+					</div>
192
+					<div class="form-group">
193
+						<label for="lastname" class="col-sm-3 control-label">任务URL</label>
194
+						<div class="col-sm-9"><input type="text" class="form-control" name="job_url" placeholder="请输入任务URL" maxlength="200" ></div>
195
+					</div>
196
+					<div class="form-group">
197
+						<label for="lastname" class="col-sm-3 control-label">任务handler</label>
198
+						<div class="col-sm-9"><input type="text" class="form-control" name="handleName" placeholder="请输入任务handler" maxlength="200" ></div>
175 199
 					</div>
176 200
 					<div class="form-group">
177 201
 						<div class="col-sm-offset-2 col-sm-10">
@@ -191,6 +215,9 @@
191 215
 <script src="${request.contextPath}/static/adminlte/plugins/datatables/jquery.dataTables.min.js"></script>
192 216
 <script src="${request.contextPath}/static/adminlte/plugins/datatables/dataTables.bootstrap.min.js"></script>
193 217
 <script src="${request.contextPath}/static/plugins/jquery/jquery.validate.min.js"></script>
218
+<!-- daterangepicker -->
219
+<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/moment.min.js"></script>
220
+<script src="${request.contextPath}/static/adminlte/plugins/daterangepicker/daterangepicker.js"></script>
194 221
 <script>var base_url = '${request.contextPath}';</script>
195 222
 <script src="${request.contextPath}/static/js/job.index.1.js"></script>
196 223
 </body>

+ 0 - 2
xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/index.ftl 查看文件

@@ -84,8 +84,6 @@
84 84
 	
85 85
 	<!-- footer -->
86 86
 	<@netCommon.commonFooter />
87
-	<!-- control -->
88
-	<@netCommon.commonControl />
89 87
 </div>
90 88
 
91 89
 <@netCommon.commonScript />

+ 109 - 9
xxl-job-admin/src/main/webapp/static/js/job.index.1.js 查看文件

@@ -1,6 +1,75 @@
1 1
 $(function() {
2 2
 	// init date tables
3
-	$("#job_list").DataTable({
3
+	var jobTable = $("#job_list").dataTable({
4
+		"deferRender": true,
5
+		"processing" : true, 
6
+	    "serverSide": true,
7
+		"ajax": {
8
+			url: base_url + "/job/pageList",
9
+	        data : function ( d ) {
10
+                d.jobName = $('#jobName').val()
11
+            }
12
+	    },
13
+	    //"scrollX": true,	// X轴滚动条,取消自适应
14
+	    "columns": [
15
+	                { "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},
21
+	                { 
22
+	                	"data": 'addTime', 
23
+	                	"bSortable": false, 
24
+	                	"render": function ( data, type, row ) {
25
+	                		return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
26
+	                	}
27
+	                },
28
+	                { 
29
+	                	"data": 'updateTime', 
30
+	                	"bSortable": false, 
31
+	                	"render": function ( data, type, row ) {
32
+	                		return data?moment(new Date(data)).format("YYYY-MM-DD HH:mm:ss"):"";
33
+	                	}
34
+	                },
35
+	                { "data": '操作' , "bSortable": false,
36
+	                	"render": function ( data, type, row ) {
37
+	                		return function(){
38
+	                			// status
39
+	                			var pause_resume = "";
40
+	                			if ('NORMAL' == row.jobStatus) {
41
+	                				pause_resume = '<button class="btn btn-info btn-xs job_operate" type="job_pause" type="button">暂停</button>  ';
42
+								} else if ('PAUSED' == row.jobStatus){
43
+									pause_resume = '<button class="btn btn-info btn-xs job_operate" type="job_resume" type="button">恢复</button>  ';
44
+								}
45
+	                			// log url
46
+	                			var logUrl = base_url +'/joblog?jobName='+ row.jobName;
47
+	                			
48
+	                			// job data
49
+	                			var jobDataMap = eval('(' + row.jobData + ')');
50
+	                			
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 +'" '+
56
+	                							'>'+
57
+	                					pause_resume +
58
+										'<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>  '+
61
+									  	'<button class="btn btn-warning btn-xs" type="job_del" type="button" '+
62
+									  		'onclick="javascript:window.open(\'' + logUrl + '\')" >查看日志</button>'+
63
+									'</p>';
64
+									
65
+	                			
66
+	                			return html;
67
+	                		};
68
+	                	}
69
+	                }
70
+	            ],
71
+	    "searching": false,
72
+	    "ordering": true,
4 73
 		"language" : {
5 74
 			"sProcessing" : "处理中...",
6 75
 			"sLengthMenu" : "每页 _MENU_ 条记录",
@@ -27,8 +96,13 @@ $(function() {
27 96
 		}
28 97
 	});
29 98
 	
99
+	// 搜索按钮
100
+	$('#searchBtn').on('click', function(){
101
+		jobTable.fnDraw();
102
+	});
103
+	
30 104
 	// job operate
31
-	$(".job_operate").click(function() {
105
+	$("#job_list").on('click', '.job_operate',function() {
32 106
 		var typeName;
33 107
 		var url;
34 108
 		var type = $(this).attr("type");
@@ -48,22 +122,21 @@ $(function() {
48 122
 			return;
49 123
 		}
50 124
 		
51
-		var name = $(this).parent('p').attr("name");
52
-		var group = $(this).parent('p').attr("group");
125
+		var name = $(this).parent('p').attr("jobName");
53 126
 		
54 127
 		ComConfirm.show("确认" + typeName + "?", function(){
55 128
 			$.ajax({
56 129
 				type : 'POST',
57 130
 				url : url,
58 131
 				data : {
59
-					"triggerKeyName" :	name,
60
-					"group"			 :	group
132
+					"triggerKeyName" :	name
61 133
 				},
62 134
 				dataType : "json",
63 135
 				success : function(data){
64 136
 					if (data.code == 200) {
65 137
 						ComAlert.show(1, typeName + "成功", function(){
66
-							window.location.reload();
138
+							//window.location.reload();
139
+							jobTable.fnDraw();
67 140
 						});
68 141
 					} else {
69 142
 						ComAlert.show(1, typeName + "失败");
@@ -215,9 +288,12 @@ $(function() {
215 288
 	});
216 289
 	
217 290
 	// 更新
218
-	$(".update").click(function(){
219
-		$("#updateModal .form input[name='triggerKeyName']").val($(this).parent('p').attr("name"));
291
+	$("#job_list").on('click', '.update',function() {
292
+		$("#updateModal .form input[name='triggerKeyName']").val($(this).parent('p').attr("jobName"));
220 293
 		$("#updateModal .form input[name='cronExpression']").val($(this).parent('p').attr("cronExpression"));
294
+		$("#updateModal .form input[name='job_desc']").val($(this).parent('p').attr("job_desc"));
295
+		$("#updateModal .form input[name='job_url']").val($(this).parent('p').attr("job_url"));
296
+		$("#updateModal .form input[name='handleName']").val($(this).parent('p').attr("handleName"));
221 297
 		$('#updateModal').modal({backdrop: false, keyboard: false}).modal('show');
222 298
 	});
223 299
 	var updateModalValidate = $("#updateModal .form").validate({
@@ -233,6 +309,18 @@ $(function() {
233 309
             cronExpression : {  
234 310
             	required : true ,
235 311
                 maxlength: 100
312
+            },  
313
+            job_desc : {  
314
+            	required : true ,
315
+                maxlength: 200
316
+            },
317
+            job_url : {
318
+            	required : true ,
319
+                maxlength: 200
320
+            },
321
+            handleName : {
322
+            	required : true ,
323
+                maxlength: 200
236 324
             }
237 325
         }, 
238 326
         messages : {  
@@ -244,6 +332,18 @@ $(function() {
244 332
             cronExpression : {
245 333
             	required :"请输入“任务Corn”."  ,
246 334
                 maxlength:"“任务Corn”不应超过100位"
335
+            },  
336
+            job_desc : {
337
+            	required :"请输入“任务描述”."  ,
338
+                maxlength:"“任务描述”长度不应超过200位"
339
+            },  
340
+            job_url : {
341
+            	required :"请输入“任务URL”."  ,
342
+                maxlength:"“任务URL”长度不应超过200位"
343
+            },
344
+            handleName : {
345
+            	required : "请输入“任务handler”."  ,
346
+                maxlength: "“任务handler”长度不应超过200位"
247 347
             }
248 348
         }, 
249 349
 		highlight : function(element) {  

+ 4 - 4
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js 查看文件

@@ -29,7 +29,7 @@ $(function() {
29 29
 	                { "data": 'triggerStatus', "bSortable": false},
30 30
 	                { "data": 'triggerMsg',"bSortable": false,
31 31
 	                	"render": function ( data, type, row ) {
32
-	                		return data?'<a class="logTips" title="'+ data +'">调度日志</a>':"无";
32
+	                		return data?'<a class="logTips" href="javascript:;" >调度日志<span style="display:none;">'+ data +'</span></a>':"无";
33 33
 	                	}
34 34
 	                },
35 35
 	                { 
@@ -42,7 +42,7 @@ $(function() {
42 42
 	                { "data": 'handleStatus',"bSortable": false},
43 43
 	                { "data": 'handleMsg' , "bSortable": false,
44 44
 	                	"render": function ( data, type, row ) {
45
-	                		return data?'<a class="logTips" title="'+ data +'">执行日志</a>':"无";
45
+	                		return data?'<a class="logTips" href="javascript:;" >执行日志<span style="display:none;">'+ data +'</span></a>':"无";
46 46
 	                	}
47 47
 	                }
48 48
 	            ],
@@ -76,8 +76,8 @@ $(function() {
76 76
 	
77 77
 	// 日志弹框提示
78 78
 	$('#joblog_list').on('click', '.logTips', function(){
79
-		var title = $(this).attr('title');
80
-		ComAlertTec.show(title);
79
+		var msg = $(this).find('span').html();
80
+		ComAlertTec.show(msg);
81 81
 	});
82 82
 	
83 83
 	// 过滤时间

+ 3 - 0
xxl-job-client/src/main/java/com/xxl/job/client/util/HttpUtil.java 查看文件

@@ -64,6 +64,9 @@ public class HttpUtil {
64 64
 				responseMsg = EntityUtils.toString(entity, "UTF-8");
65 65
 				EntityUtils.consume(entity);
66 66
 			}
67
+			if (response.getStatusLine().getStatusCode() != 200) {
68
+				exceptionMsg = "response.getStatusLine().getStatusCode() = " + response.getStatusLine().getStatusCode();
69
+			}
67 70
 		} catch (Exception e) {
68 71
 			e.printStackTrace();
69 72
 			StringWriter out = new StringWriter();