xueli.xue 9 年前
父节点
当前提交
1b1e783f86

+ 2 - 2
README.md 查看文件

@@ -18,7 +18,7 @@ XXL-JOB是一个轻量级分布式任务调度框架,其核心设计目标是
18 18
 - 11、支持登录验证;
19 19
 - 12、GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯。
20 20
 - 12、数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
21
-- 14、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行;
21
+- 14、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔
22 22
 
23 23
 #### 1.3 发展
24 24
 于2015年中,我在github上创建XXL-JOB项目仓库并提交第一个commit,随之进行系统结构设计,UI选型,交互设计……
@@ -565,7 +565,7 @@ XXL-JOB会为每次调度请求生成一个单独的日志文件,通过重写L
565 565
 - 3、【重要】在 “调度中心” 支持HA的基础上,扩展执行器的Failover支持,支持配置多执行期地址;
566 566
 
567 567
 #### 6.6 版本 V1.4.0 新特性
568
-- 1、任务依赖: 通过事件触发方式实现, 任务执行成功并回调时会主动触发一次子任务的调度;
568
+- 1、任务依赖: 通过事件触发方式实现, 任务执行成功并回调时会主动触发一次子任务的调度, 多个子任务用逗号分隔;
569 569
 - 2、执行器底层实现代码进行重度重构, 优化底层建表脚本;
570 570
 - 3、执行器中任务线程分组逻辑优化: 之前根据执行器JobHandler进行线程分组,当多个任务复用Jobhanlder会导致相互阻塞。现改为根据调度中心任务进行任务线程分组,任务与任务执行相互隔离;
571 571
 - 4、执行器调度通讯方案优化, 通过Hex + HC实现建议RPC通讯协议, 优化了通讯参数的维护和解析流程;

+ 23 - 15
xxl-job-admin/src/main/java/com/xxl/job/admin/core/callback/XxlJobLogCallbackServerHandler.java 查看文件

@@ -47,24 +47,32 @@ public class XxlJobLogCallbackServerHandler extends AbstractHandler {
47 47
 			if (!ResponseModel.SUCCESS.equals(log.getHandleStatus())) {
48 48
 				XxlJobInfo xxlJobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(log.getJobGroup(), log.getJobName());
49 49
 				if (xxlJobInfo!=null && StringUtils.isNotBlank(xxlJobInfo.getChildJobKey())) {
50
-					String[] jobKeyArr = xxlJobInfo.getChildJobKey().split("_");
51
-					if (jobKeyArr!=null && jobKeyArr.length==2) {
52
-						XxlJobInfo childJobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKeyArr[0], jobKeyArr[1]);
53
-						if (childJobInfo!=null) {
54
-							try {
55
-								boolean ret = DynamicSchedulerUtil.triggerJob(childJobInfo.getJobName(), childJobInfo.getJobGroup());
50
+					childTriggerMsg = "<hr>";
51
+                    String[] childJobKeys = xxlJobInfo.getChildJobKey().split(",");
52
+					for (int i = 0; i < childJobKeys.length; i++) {
53
+						String[] jobKeyArr = childJobKeys[i].split("_");
54
+						if (jobKeyArr!=null && jobKeyArr.length==2) {
55
+							XxlJobInfo childJobInfo = DynamicSchedulerUtil.xxlJobInfoDao.load(jobKeyArr[0], jobKeyArr[1]);
56
+							if (childJobInfo!=null) {
57
+								try {
58
+									boolean ret = DynamicSchedulerUtil.triggerJob(childJobInfo.getJobName(), childJobInfo.getJobGroup());
56 59
 
57
-								// add msg
58
-                                childTriggerMsg += MessageFormat.format("<br> 触发子任务成功, 子任务Key: {0}, status: {1}, 子任务描述: {2}", xxlJobInfo.getChildJobKey(), ret, childJobInfo.getJobDesc());
59
-							} catch (SchedulerException e) {
60
-								logger.error("", e);
60
+									// add msg
61
+									childTriggerMsg += MessageFormat.format("<br> {0}/{1} 触发子任务成功, 子任务Key: {2}, status: {3}, 子任务描述: {4}",
62
+											(i+1), childJobKeys.length, childJobKeys[i], ret, childJobInfo.getJobDesc());
63
+								} catch (SchedulerException e) {
64
+									logger.error("", e);
65
+								}
66
+							} else {
67
+								childTriggerMsg += MessageFormat.format("<br> {0}/{1} 触发子任务失败, 子任务xxlJobInfo不存在, 子任务Key: {2}",
68
+										(i+1), childJobKeys.length, childJobKeys[i]);
61 69
 							}
62 70
 						} else {
63
-                            childTriggerMsg = "<br> 触发子任务失败, 子任务xxlJobInfo不存在, 子任务Key:" + xxlJobInfo.getChildJobKey();
64
-                        }
65
-					} else {
66
-                        childTriggerMsg = "<br> 触发子任务失败, 子任务Key格式错误, 子任务Key:" + xxlJobInfo.getChildJobKey();
67
-                    }
71
+							childTriggerMsg += MessageFormat.format("<br> {0}/{1} 触发子任务失败, 子任务Key格式错误, 子任务Key: {2}",
72
+									(i+1), childJobKeys.length, childJobKeys[i]);
73
+						}
74
+					}
75
+
68 76
 				}
69 77
 			}
70 78
 

+ 31 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java 查看文件

@@ -17,6 +17,7 @@ import org.slf4j.LoggerFactory;
17 17
 import org.springframework.stereotype.Service;
18 18
 
19 19
 import javax.annotation.Resource;
20
+import java.text.MessageFormat;
20 21
 import java.util.Date;
21 22
 import java.util.HashMap;
22 23
 import java.util.List;
@@ -86,6 +87,21 @@ public class XxlJobServiceImpl implements IXxlJobService {
86 87
 			return new ReturnT<String>(500, "请输入“JobHandler”");
87 88
 		}
88 89
 
90
+		// childJobKey valid
91
+		if (StringUtils.isNotBlank(childJobKey)) {
92
+			String[] childJobKeys = childJobKey.split(",");
93
+			for (String childJobKeyItem: childJobKeys) {
94
+				String[] childJobKeyArr = childJobKeyItem.split("_");
95
+				if (childJobKeyArr.length!=2) {
96
+					return new ReturnT<String>(500, MessageFormat.format("子任务Key({0})格式错误", childJobKeyItem));
97
+				}
98
+				XxlJobInfo childJobInfo = xxlJobInfoDao.load(childJobKeyArr[0], childJobKeyArr[1]);
99
+				if (childJobInfo==null) {
100
+					return new ReturnT<String>(500, MessageFormat.format("子任务Key({0})无效", childJobKeyItem));
101
+				}
102
+			}
103
+		}
104
+
89 105
 		// generate jobName
90 106
 		String jobName = FastDateFormat.getInstance("yyyyMMddHHmmssSSSS").format(new Date());
91 107
 		try {
@@ -158,6 +174,21 @@ public class XxlJobServiceImpl implements IXxlJobService {
158 174
 			return new ReturnT<String>(500, "请输入“JobHandler”");
159 175
 		}
160 176
 
177
+		// childJobKey valid
178
+		if (StringUtils.isNotBlank(childJobKey)) {
179
+			String[] childJobKeys = childJobKey.split(",");
180
+			for (String childJobKeyItem: childJobKeys) {
181
+				String[] childJobKeyArr = childJobKeyItem.split("_");
182
+				if (childJobKeyArr.length!=2) {
183
+					return new ReturnT<String>(500, MessageFormat.format("子任务Key({0})格式错误", childJobKeyItem));
184
+				}
185
+				XxlJobInfo childJobInfo = xxlJobInfoDao.load(childJobKeyArr[0], childJobKeyArr[1]);
186
+				if (childJobInfo==null) {
187
+					return new ReturnT<String>(500, MessageFormat.format("子任务Key({0})无效", childJobKeyItem));
188
+				}
189
+			}
190
+		}
191
+
161 192
 		// stage job info
162 193
 		XxlJobInfo jobInfo = xxlJobInfoDao.load(jobGroup, jobName);
163 194
 		jobInfo.setJobCron(jobCron);

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

@@ -151,7 +151,7 @@
151 151
 					</div>
152 152
                     <div class="form-group">
153 153
                         <label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
154
-                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key" maxlength="100" ></div>
154
+                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div>
155 155
                     </div>
156 156
                     <hr>
157 157
 					<div class="form-group">
@@ -232,7 +232,7 @@ public class DemoJobHandler extends IJobHandler {
232 232
 					</div>
233 233
                     <div class="form-group">
234 234
                         <label for="lastname" class="col-sm-2 control-label">子任务Key<font color="black">*</font></label>
235
-                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key" maxlength="100" ></div>
235
+                        <div class="col-sm-4"><input type="text" class="form-control" name="childJobKey" placeholder="请输入子任务的任务Key,如存在多个逗号分隔" maxlength="100" ></div>
236 236
                     </div>
237 237
 					<hr>
238 238
 					<div class="form-group">