Browse Source

Merge branch 'master' into feature/timeout

许雪里 7 years ago
parent
commit
c3c7ded5e0
No account linked to committer's email
59 changed files with 393 additions and 159 deletions
  1. 30 0
      README.md
  2. 59 35
      doc/XXL-JOB-English-Documentation.md
  3. 111 39
      doc/XXL-JOB官方文档.md
  4. 4 3
      doc/db/tables_xxl_job.sql
  5. BIN
      doc/images/img_6yC0.png
  6. BIN
      doc/images/img_9235.png
  7. BIN
      doc/images/img_BPLG.png
  8. BIN
      doc/images/img_EB65.png
  9. BIN
      doc/images/img_Fgql.png
  10. BIN
      doc/images/img_Hr2T.png
  11. BIN
      doc/images/img_Qohm.png
  12. BIN
      doc/images/img_UDSo.png
  13. BIN
      doc/images/img_V3vF.png
  14. BIN
      doc/images/img_Wb2o.png
  15. BIN
      doc/images/img_Ypik.png
  16. BIN
      doc/images/img_Z5wp.png
  17. BIN
      doc/images/img_Z9Qr.png
  18. BIN
      doc/images/img_ZAhX.png
  19. BIN
      doc/images/img_ZAsz.png
  20. BIN
      doc/images/img_bNwm.png
  21. BIN
      doc/images/img_dNUJ.png
  22. BIN
      doc/images/img_eYrv.png
  23. BIN
      doc/images/img_hIci.png
  24. BIN
      doc/images/img_iUw0.png
  25. BIN
      doc/images/img_inc8.png
  26. BIN
      doc/images/img_jOAU.png
  27. BIN
      doc/images/img_jrdI.png
  28. BIN
      doc/images/img_o8HQ.png
  29. BIN
      doc/images/img_oLlM.png
  30. BIN
      doc/images/img_tJOq.png
  31. BIN
      doc/images/img_tvGI.png
  32. 7 0
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/conf/XxlJobAdminConfig.java
  33. 11 0
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/schedule/XxlJobDynamicScheduler.java
  34. 5 5
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobFailMonitorHelper.java
  35. 1 1
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/I18nUtil.java
  36. 2 1
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/LocalCacheUtil.java
  37. 8 2
      xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/MailUtil.java
  38. 4 5
      xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java
  39. 3 0
      xxl-job-admin/src/main/resources/i18n/message.properties
  40. 3 0
      xxl-job-admin/src/main/resources/i18n/message_en.properties
  41. 17 11
      xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml
  42. 1 0
      xxl-job-admin/src/main/resources/xxl-job-admin.properties
  43. 2 2
      xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl
  44. 1 1
      xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
  45. 1 1
      xxl-job-admin/src/test/java/com/xxl/job/admin/util/MailUtilTest.java
  46. 8 0
      xxl-job-core/src/main/java/com/xxl/job/core/biz/AdminBiz.java
  47. 14 1
      xxl-job-core/src/main/java/com/xxl/job/core/biz/model/HandleCallbackParam.java
  48. 8 4
      xxl-job-core/src/main/java/com/xxl/job/core/enums/ExecutorBlockStrategyEnum.java
  49. 5 5
      xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java
  50. 12 3
      xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java
  51. 13 15
      xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java
  52. 8 4
      xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobLogger.java
  53. 1 2
      xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/NetComClientProxy.java
  54. 2 2
      xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/jetty/client/JettyClient.java
  55. 14 8
      xxl-job-core/src/main/java/com/xxl/job/core/thread/JobThread.java
  56. 17 4
      xxl-job-core/src/main/java/com/xxl/job/core/thread/TriggerCallbackThread.java
  57. 3 4
      xxl-job-core/src/main/java/com/xxl/job/core/util/HttpClientUtil.java
  58. 17 1
      xxl-job-core/src/main/java/com/xxl/job/core/util/ScriptUtil.java
  59. 1 0
      xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml

+ 30 - 0
README.md View File

156
     - 64、未来无线网
156
     - 64、未来无线网
157
     - 65、厦门瓷禧网络有限公司
157
     - 65、厦门瓷禧网络有限公司
158
     - 66、北京递蓝科软件股份有限公司
158
     - 66、北京递蓝科软件股份有限公司
159
+    - 67、郑州创海软件科技公司
160
+    - 68、北京国槐信息科技有限公司
161
+    - 69、浪潮软件集团
162
+    - 70、多立恒(北京)信息技术有限公司
163
+    - 71、广州极迅客信息科技有限公司
164
+    - 72、赫基(中国)集团股份有限公司
165
+    - 73、海投汇
166
+    - 74、上海润益创业孵化器管理股份有限公司
167
+    - 75、汉纳森(厦门)数据股份有限公司
168
+    - 76、安信信托
169
+    - 77、岚儒财富
170
+    - 78、捷道软件
171
+    - 79、湖北享七网络科技有限公司
172
+    - 80、湖南创发科技责任有限公司
173
+    - 81、深圳小安时代互联网金融服务有限公司
174
+    - 82、湖北享七网络科技有限公司
175
+    - 83、钱包行云(北京)科技有限公司
176
+    - 84、360金融 (360)
177
+    - 85、易企秀
178
+    - 86、摩贝(上海)生物科技有限公司
179
+    - 87、广东芯智慧科技有限公司
180
+    - 88、联想集团 (联想)
181
+    - 89、怪兽充电
182
+    - 90、行圆汽车
183
+    - 91、深圳店店通科技邮箱公司
184
+    - 92、京东 (京东)
185
+    - 93、米庄理财
186
+    - 94、咖啡易融
187
+    - 95、梧桐诚选
188
+    - 96、恒大地产 (恒大)
159
 	- ……
189
 	- ……
160
 
190
 
161
 > 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
191
 > 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。

+ 59 - 35
doc/XXL-JOB-English-Documentation.md View File

121
     - 65、厦门瓷禧网络有限公司
121
     - 65、厦门瓷禧网络有限公司
122
     - 66、北京递蓝科软件股份有限公司
122
     - 66、北京递蓝科软件股份有限公司
123
     - 67、郑州创海软件科技公司
123
     - 67、郑州创海软件科技公司
124
+    - 68、北京国槐信息科技有限公司
125
+    - 69、浪潮软件集团
126
+    - 70、多立恒(北京)信息技术有限公司
127
+    - 71、广州极迅客信息科技有限公司
128
+    - 72、赫基(中国)集团股份有限公司
129
+    - 73、海投汇
130
+    - 74、上海润益创业孵化器管理股份有限公司
131
+    - 75、汉纳森(厦门)数据股份有限公司
132
+    - 76、安信信托
133
+    - 77、岚儒财富
134
+    - 78、捷道软件
135
+    - 79、湖北享七网络科技有限公司
136
+    - 80、湖南创发科技责任有限公司
137
+    - 81、深圳小安时代互联网金融服务有限公司
138
+    - 82、湖北享七网络科技有限公司
139
+    - 83、钱包行云(北京)科技有限公司
140
+    - 84、360金融 (360)
141
+    - 85、易企秀
142
+    - 86、摩贝(上海)生物科技有限公司
143
+    - 87、广东芯智慧科技有限公司
144
+    - 88、联想集团 (联想)
145
+    - 89、怪兽充电
146
+    - 90、行圆汽车
147
+    - 91、深圳店店通科技邮箱公司
148
+    - 92、京东 (京东)
149
+    - 93、米庄理财
150
+    - 94、咖啡易融
151
+    - 95、梧桐诚选
152
+    - 96、恒大地产 (恒大)
124
 	- ……
153
 	- ……
125
 
154
 
126
 > The company that access and use this product is welcome to register at the [address](https://github.com/xuxueli/xxl-job/issues/1 ), only for product promotion. 
155
 > The company that access and use this product is welcome to register at the [address](https://github.com/xuxueli/xxl-job/issues/1 ), only for product promotion. 
227
 If you has finished step 1,then you can compile the project in maven and deploy the war package to tomcat.
256
 If you has finished step 1,then you can compile the project in maven and deploy the war package to tomcat.
228
 the url to visit is :http://localhost:8080/xxl-job-admin (this address will be used by executor and use it as callback url),the index page after login in is as follow
257
 the url to visit is :http://localhost:8080/xxl-job-admin (this address will be used by executor and use it as callback url),the index page after login in is as follow
229
 
258
 
230
-![index page after login in](https://static.oschina.net/uploads/img/201705/08194505_6yC0.png "index page after login in")
259
+![index page after login in](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_6yC0.png "index page after login in")
231
 
260
 
232
 Now,the “xxl-job-admin” project is deployed success.
261
 Now,the “xxl-job-admin” project is deployed success.
233
 
262
 
321
 #### Step 1:Create new job
350
 #### Step 1:Create new job
322
 Login in xxl-job-admin,click on the"新建任务" button, configure the job params as follows and click "保存" button to save the job info.
351
 Login in xxl-job-admin,click on the"新建任务" button, configure the job params as follows and click "保存" button to save the job info.
323
 
352
 
324
-![task management](https://static.oschina.net/uploads/img/201704/27205910_o8HQ.png "task management")
353
+![task management](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_o8HQ.png "task management")
325
 
354
 
326
-![create task](https://static.oschina.net/uploads/img/201704/27210202_SE2u.png "create task")
355
+![create task](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAsz.png "create task")
327
 
356
 
328
 #### Step 2:develop “GLUE模式(Java)” job
357
 #### Step 2:develop “GLUE模式(Java)” job
329
 Click “GLUE” button on the right of the job to go to GLUE editor view as shown below。“GLUE模式(Java)” mode task has been inited with default task code for printing Hello World。 ( “GLUE模式(Java)” mode task is a java code fragment implements IJobHandler interface,it will be executed in executor,you can use @Resource/@Autowire to inject other java bean instance,if you want to see more info please go to chapter 3)
358
 Click “GLUE” button on the right of the job to go to GLUE editor view as shown below。“GLUE模式(Java)” mode task has been inited with default task code for printing Hello World。 ( “GLUE模式(Java)” mode task is a java code fragment implements IJobHandler interface,it will be executed in executor,you can use @Resource/@Autowire to inject other java bean instance,if you want to see more info please go to chapter 3)
330
 
359
 
331
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27210307_Fgql.png "在这里输入图片标题")
360
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Fgql.png "在这里输入图片标题")
332
 
361
 
333
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27210314_dNUJ.png "在这里输入图片标题")
362
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_dNUJ.png "在这里输入图片标题")
334
 
363
 
335
 #### Step 3:trigger task
364
 #### Step 3:trigger task
336
 If you want to run the job manually please click "执行" button on the right of the job(usually we trigger job by Cron expression)
365
 If you want to run the job manually please click "执行" button on the right of the job(usually we trigger job by Cron expression)
338
 #### Step 4:view log 
367
 #### Step 4:view log 
339
 Click “日志” button on the right side of the task you will go to the task log list ,you will see the schedule history records of the task and the schedule detail info,execution info and execution params.If you click the “执行日志” button on the right side of the task log record,you will go to log console and view the execute log in the course of task execution.
368
 Click “日志” button on the right side of the task you will go to the task log list ,you will see the schedule history records of the task and the schedule detail info,execution info and execution params.If you click the “执行日志” button on the right side of the task log record,you will go to log console and view the execute log in the course of task execution.
340
 
369
 
341
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27232850_inc8.png "在这里输入图片标题")
370
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_inc8.png "在这里输入图片标题")
342
 
371
 
343
 On the log console,you can view task execution log on the executor immediately after it dump to log file,so you can monitor the task execution process by Rolling way.
372
 On the log console,you can view task execution log on the executor immediately after it dump to log file,so you can monitor the task execution process by Rolling way.
344
 
373
 
345
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27211631_eYrv.png "在这里输入图片标题")
374
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_eYrv.png "在这里输入图片标题")
346
 
375
 
347
 ## 3. Task details
376
 ## 3. Task details
348
 
377
 
390
     - 3, add  “@JobHandler(value=" customize jobhandler name")” annotation,the value stand for JobHandler name,it will be used as JobHandler property when create a new task in the schedule center.
419
     - 3, add  “@JobHandler(value=" customize jobhandler name")” annotation,the value stand for JobHandler name,it will be used as JobHandler property when create a new task in the schedule center.
391
     (go and see DemoJobHandler in the xxl-job-executor-example project, as shown below)
420
     (go and see DemoJobHandler in the xxl-job-executor-example project, as shown below)
392
 
421
 
393
-![输入图片说明](https://static.oschina.net/uploads/img/201607/23232347_oLlM.png "在这里输入图片标题")
422
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_oLlM.png "在这里输入图片标题")
394
 
423
 
395
 #### Step 2:create task in schedule center
424
 #### Step 2:create task in schedule center
396
 If you want learn more about configure item please go and sedd “Description of configuration item”,select  "BEAN模式" as run mode,property JobHandler please fill in the value defined by @JobHande.
425
 If you want learn more about configure item please go and sedd “Description of configuration item”,select  "BEAN模式" as run mode,property JobHandler please fill in the value defined by @JobHande.
397
 
426
 
398
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27225124_yrcO.png "在这里输入图片标题")
427
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAsz.png "在这里输入图片标题")
399
 
428
 
400
 ### 3.2 GLUE模式(Java)
429
 ### 3.2 GLUE模式(Java)
401
 Task source code is maintained in the schedule center and can be updated by Web IDE online, it will be compiled and effective real-time,didn’t need to assign JobHandler,develop flow shown as below:
430
 Task source code is maintained in the schedule center and can be updated by Web IDE online, it will be compiled and effective real-time,didn’t need to assign JobHandler,develop flow shown as below:
403
 #### Step 1:create task in schedule center
432
 #### Step 1:create task in schedule center
404
 If you want learn more about configure item please go and sedd “Description of configuration item”,select "GLUE模式(Java)" as run mode.
433
 If you want learn more about configure item please go and sedd “Description of configuration item”,select "GLUE模式(Java)" as run mode.
405
 
434
 
406
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27210202_SE2u.png "在这里输入图片标题")
435
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_tJOq.png "在这里输入图片标题")
407
 
436
 
408
 #### Step 2:develop task source code
437
 #### Step 2:develop task source code
409
 Select the task record and click “GLUE” button on the righe of it,it will go to GLUE task’s WEB IDE page,on this page yo can edit you task code(also can edit in other IDE tools,copy and paste into this page).
438
 Select the task record and click “GLUE” button on the righe of it,it will go to GLUE task’s WEB IDE page,on this page yo can edit you task code(also can edit in other IDE tools,copy and paste into this page).
410
 
439
 
411
 Version backtrack(support 30 versions while backtrack):on the WEB IDE page of GLUE task,on upper right corner drop down box please select “版本回溯”,it will display GLUE updated history,select the version you want it will display the source code of this version,it will backtrace the version while click save button. 
440
 Version backtrack(support 30 versions while backtrack):on the WEB IDE page of GLUE task,on upper right corner drop down box please select “版本回溯”,it will display GLUE updated history,select the version you want it will display the source code of this version,it will backtrace the version while click save button. 
412
 
441
 
413
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27210314_dNUJ.png "在这里输入图片标题")
442
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_dNUJ.png "在这里输入图片标题")
414
 
443
 
415
 ### 3.3 GLUE模式(Shell)
444
 ### 3.3 GLUE模式(Shell)
416
 
445
 
422
 
451
 
423
 Actually it is a shell script fragment.
452
 Actually it is a shell script fragment.
424
 
453
 
425
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27232259_iUw0.png "在这里输入图片标题")
454
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_iUw0.png "在这里输入图片标题")
426
 
455
 
427
 ### 3.4 GLUE模式(Python)
456
 ### 3.4 GLUE模式(Python)
428
 
457
 
434
 
463
 
435
 Actually it is a python script fragment.
464
 Actually it is a python script fragment.
436
 
465
 
437
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27232305_BPLG.png "在这里输入图片标题")
466
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_BPLG.png "在这里输入图片标题")
438
 
467
 
439
 
468
 
440
 ## 4. Task Management
469
 ## 4. Task Management
441
 ### 4.0 configure executor
470
 ### 4.0 configure executor
442
 click"执行器管理" on the left menu,it will go to the page as shown below:
471
 click"执行器管理" on the left menu,it will go to the page as shown below:
443
-![输入图片说明](https://static.oschina.net/uploads/img/201703/12223509_Hr2T.png "在这里输入图片标题")
472
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Hr2T.png "在这里输入图片标题")
444
 
473
 
445
     1,"调度中心OnLine”:display schedule center machine list,when task is scheduled it will callback schedule center for notify the execution result in failover mode, so that it can avoid a single point scheduler;
474
     1,"调度中心OnLine”:display schedule center machine list,when task is scheduled it will callback schedule center for notify the execution result in failover mode, so that it can avoid a single point scheduler;
446
     2,"执行器列表" :display all nodes under this executor group.
475
     2,"执行器列表" :display all nodes under this executor group.
447
 
476
 
448
 If you want to create a new executor,please click "+新增执行器" button: 
477
 If you want to create a new executor,please click "+新增执行器" button: 
449
-![输入图片说明](https://static.oschina.net/uploads/img/201703/12223617_g3Im.png "在这里输入图片标题")
478
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_V3vF.png "在这里输入图片标题")
450
 
479
 
451
 ### Description of executor attributes
480
 ### Description of executor attributes
452
 
481
 
473
 ### 4.4 pause/recover task
502
 ### 4.4 pause/recover task
474
 You can pause or recover task but it just fit to follow up schedule trigger and won’t affect scheduled tasks,if you want to stop tasks which has been triggered,please go and see “4.8 stop the running task”
503
 You can pause or recover task but it just fit to follow up schedule trigger and won’t affect scheduled tasks,if you want to stop tasks which has been triggered,please go and see “4.8 stop the running task”
475
 
504
 
476
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24130337_ZAhX.png "在这里输入图片标题")
505
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAhX.png "在这里输入图片标题")
477
 
506
 
478
 ### 4.5 manually trigger
507
 ### 4.5 manually trigger
479
 You can trigger a task manually by Click “执行”button,it won’t affect original scheduling rules.
508
 You can trigger a task manually by Click “执行”button,it won’t affect original scheduling rules.
480
 
509
 
481
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24133348_Z5wp.png "在这里输入图片标题")
510
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Z5wp.png "在这里输入图片标题")
482
 
511
 
483
 ### 4.6 view schedule log
512
 ### 4.6 view schedule log
484
 You can view task’s history schedule log by click “日志” button,on the history schedule log list page you can view every time of task’s schedule result,execution result and so on,click “执行日志” button can view the task’s full execute log.
513
 You can view task’s history schedule log by click “日志” button,on the history schedule log list page you can view every time of task’s schedule result,execution result and so on,click “执行日志” button can view the task’s full execute log.
485
 
514
 
486
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24133500_9235.png "在这里输入图片标题")
515
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_9235.png "在这里输入图片标题")
487
 
516
 
488
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27232850_inc8.png "在这里输入图片标题")
517
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_inc8.png "在这里输入图片标题")
489
 
518
 
490
     调度时间:schedule center trigger time when schedule and send execution signal to executor;
519
     调度时间:schedule center trigger time when schedule and send execution signal to executor;
491
     调度结果:schedule center trigger task’s result, 200 represent success,500 or other number stands for fail;
520
     调度结果:schedule center trigger task’s result, 200 represent success,500 or other number stands for fail;
503
 ### 4.7 view execution log
532
 ### 4.7 view execution log
504
 Click the “执行日志” button on the right side of the record,you can go to the execution log page,you can view the full execution log of the logic business code, shown as below:
533
 Click the “执行日志” button on the right side of the record,you can go to the execution log page,you can view the full execution log of the logic business code, shown as below:
505
 
534
 
506
-![输入图片说明](https://static.oschina.net/uploads/img/201703/25124816_tvGI.png "在这里输入图片标题")
535
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_tvGI.png "在这里输入图片标题")
507
 
536
 
508
 ### 4.8 stop running tasks
537
 ### 4.8 stop running tasks
509
 Just fit to running tasks,on the task log list page,click “终止任务” button on the right side of the record, it will send stop command to the executor where the task was executed,finally the task was killed and the task instance execute queue of this task will be clear.
538
 Just fit to running tasks,on the task log list page,click “终止任务” button on the right side of the record, it will send stop command to the executor where the task was executed,finally the task was killed and the task instance execute queue of this task will be clear.
510
 
539
 
511
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24140048_hIci.png "在这里输入图片标题")
540
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_hIci.png "在这里输入图片标题")
512
 
541
 
513
 It is implemented by interrupt execute thread, it will trigger InterruptedException.so if JobHandler catch this execuption and handle this exception this function is unavailable.
542
 It is implemented by interrupt execute thread, it will trigger InterruptedException.so if JobHandler catch this execuption and handle this exception this function is unavailable.
514
 
543
 
529
 
558
 
530
 ### 4.9 delete execution log
559
 ### 4.9 delete execution log
531
 On the task log list page, after you select executor and task, you can click"删除" button on the right side and it will pop-up "日志清理" window,on the pop-up window you can choose different log delete policy,choose the policy you want to execute and click "确定" button it will delele relative logs:
560
 On the task log list page, after you select executor and task, you can click"删除" button on the right side and it will pop-up "日志清理" window,on the pop-up window you can choose different log delete policy,choose the policy you want to execute and click "确定" button it will delele relative logs:
532
-![输入图片说明](https://static.oschina.net/uploads/img/201705/08210711_Ypik.png "在这里输入图片标题")
561
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Ypik.png "在这里输入图片标题")
533
 
562
 
534
-![输入图片说明](https://static.oschina.net/uploads/img/201705/08211152_EB65.png "在这里输入图片标题")
563
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_EB65.png "在这里输入图片标题")
535
 
564
 
536
 ### 4.10 delete task
565
 ### 4.10 delete task
537
 Click the delete button on the right side of the task,the task will be deteted.
566
 Click the delete button on the right side of the task,the task will be deteted.
538
 
567
 
539
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24140641_Z9Qr.png "在这里输入图片标题")
568
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Z9Qr.png "在这里输入图片标题")
540
 
569
 
541
 ## 5. Overall design
570
 ## 5. Overall design
542
 ### 5.1 Source directory introduction
571
 ### 5.1 Source directory introduction
551
 
580
 
552
 XXL-JOB custom Quartz table structure prefix(XXL_JOB_QRTZ_).
581
 XXL-JOB custom Quartz table structure prefix(XXL_JOB_QRTZ_).
553
 
582
 
554
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24143957_bNwm.png "在这里输入图片标题")
583
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_bNwm.png "在这里输入图片标题")
555
 
584
 
556
 The added tables as shown below:
585
 The added tables as shown below:
557
     - XXL_JOB_QRTZ_TRIGGER_GROUP:executor basic table, maintain the info about the executor;
586
     - XXL_JOB_QRTZ_TRIGGER_GROUP:executor basic table, maintain the info about the executor;
580
 
609
 
581
 #### 5.3.3 Architecture diagram
610
 #### 5.3.3 Architecture diagram
582
 
611
 
583
-![输入图片说明](https://static.oschina.net/uploads/img/201707/17190028_aEE2.png "在这里输入图片标题")
612
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Qohm.png "在这里输入图片标题")
584
 
613
 
585
 ### 5.4 Schedule module analysis
614
 ### 5.4 Schedule module analysis
586
 #### 5.4.1 Disadvantage of quartz
615
 #### 5.4.1 Disadvantage of quartz
661
 If executor project was deployed as cluster schedule center will known all online executor nodes,such as:“127.0.0.1:9997, 127.0.0.1:9998, 127.0.0.1:9999”.
690
 If executor project was deployed as cluster schedule center will known all online executor nodes,such as:“127.0.0.1:9997, 127.0.0.1:9998, 127.0.0.1:9999”.
662
 
691
 
663
 When "路由策略" select "故障转移(FAILOVER)",it will send heart beat check request in order while schedule center start schedule request.  The first alive checked executor node will be selected and send schedule request to it.
692
 When "路由策略" select "故障转移(FAILOVER)",it will send heart beat check request in order while schedule center start schedule request.  The first alive checked executor node will be selected and send schedule request to it.
664
-![输入图片说明](https://static.oschina.net/uploads/img/201705/11221144_P128.png "在这里输入图片标题")
665
 
693
 
666
 “调度备注” can be viewed on the monitor page when schedule success. As shown below: 
694
 “调度备注” can be viewed on the monitor page when schedule success. As shown below: 
667
-![输入图片说明](https://static.oschina.net/uploads/img/201703/12230733_jrdI.png "在这里输入图片标题")
695
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_jrdI.png "在这里输入图片标题")
668
 
696
 
669
 “调度备注” will display local schedule route path、executor’s "注册方式"、"地址列表" and task’s "路由策略"。Under "故障转移(FAILOVER)" policy, schedule center take first address to do heartbeat detection, heat beat fail will automatically skip, the second address heart beat fail…… until the third address “127.0.0.1:9999” heart beat success, it was selected as target executor, then send schedule request to target executor, now the schedule process is end wait for the executor’s callback execution result.
697
 “调度备注” will display local schedule route path、executor’s "注册方式"、"地址列表" and task’s "路由策略"。Under "故障转移(FAILOVER)" policy, schedule center take first address to do heartbeat detection, heat beat fail will automatically skip, the second address heart beat fail…… until the third address “127.0.0.1:9999” heart beat success, it was selected as target executor, then send schedule request to target executor, now the schedule process is end wait for the executor’s callback execution result.
670
 
698
 
675
 - 调度信息:include schedule time、schedule result and  schedule log  and so on,accord these parameters you can understand some task schedule info of schedule center.
703
 - 调度信息:include schedule time、schedule result and  schedule log  and so on,accord these parameters you can understand some task schedule info of schedule center.
676
 - 执行信息:include execute time、execute result and execute log and so on, accord these parameters you can understand the task execution info in the executor.
704
 - 执行信息:include execute time、execute result and execute log and so on, accord these parameters you can understand the task execution info in the executor.
677
 
705
 
678
-![输入图片说明](https://static.oschina.net/uploads/img/201703/12221436_c8Ru.png "在这里输入图片标题")
679
-
680
 Schedule log stands fo single task schedule, attribute description is as follows:
706
 Schedule log stands fo single task schedule, attribute description is as follows:
681
 - 执行器地址:machine addresses on which task will be executed.
707
 - 执行器地址:machine addresses on which task will be executed.
682
 - JobHandler:JobHandler name of task under Bean module.
708
 - JobHandler:JobHandler name of task under Bean module.
696
 
722
 
697
 On the task log page ,you can see matched child task and triggered child task’s log info when you “查看”button of “执行备注”,otherwise the child task didin’t execute, as shown beleow:
723
 On the task log page ,you can see matched child task and triggered child task’s log info when you “查看”button of “执行备注”,otherwise the child task didin’t execute, as shown beleow:
698
 
724
 
699
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24194134_Wb2o.png "在这里输入图片标题")
725
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Wb2o.png "在这里输入图片标题")
700
 
726
 
701
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24194212_jOAU.png "在这里输入图片标题")
727
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_jOAU.png "在这里输入图片标题")
702
 
728
 
703
 ### 5.5 Task "run mode" analysis
729
 ### 5.5 Task "run mode" analysis
704
 #### 5.5.1 "Bean模式" task
730
 #### 5.5.1 "Bean模式" task
722
 #### 5.5.4 executor
748
 #### 5.5.4 executor
723
 Executor is actually an embedded Jetty server with default port 9999, as shown below(parameter:xxl.job.executor.port).
749
 Executor is actually an embedded Jetty server with default port 9999, as shown below(parameter:xxl.job.executor.port).
724
 
750
 
725
-![输入图片说明](https://static.oschina.net/uploads/img/201703/10174923_TgNO.png "在这里输入图片标题")
726
-
727
 Executor will identify Bean mode task in spring container through @JobHandler When project start, it will be managed use the value of annotation as key. 
751
 Executor will identify Bean mode task in spring container through @JobHandler When project start, it will be managed use the value of annotation as key. 
728
 
752
 
729
 When executor received schedule request from schedule center, if task type is “Bean模式” it will match bean mode task in Spring container and call it’s execute() method and execute task logic. if task type is “GLUE模式”, it will load Glue code, instantiate a Java object and inject other spring service(notice: the spring service injected in Glue code must exist in the same executor project), then call execute() method and execute task logic. 
753
 When executor received schedule request from schedule center, if task type is “Bean模式” it will match bean mode task in Spring container and call it’s execute() method and execute task logic. if task type is “GLUE模式”, it will load Glue code, instantiate a Java object and inject other spring service(notice: the spring service injected in Glue code must exist in the same executor project), then call execute() method and execute task logic. 
797
 
821
 
798
 The scheduling center API service location: com.xxl.job.core.biz.AdminBiz.java
822
 The scheduling center API service location: com.xxl.job.core.biz.AdminBiz.java
799
 
823
 
800
-The scheduling center API service requests reference code:com.xxl.job.dao.impl.AdminBizTest.java
824
+The scheduling center API service requests reference code:com.xxl.job.adminbiz.AdminBizTest.java
801
 
825
 
802
 
826
 
803
 ## 6 Version update log
827
 ## 6 Version update log

+ 111 - 39
doc/XXL-JOB官方文档.md View File

134
     - 65、厦门瓷禧网络有限公司
134
     - 65、厦门瓷禧网络有限公司
135
     - 66、北京递蓝科软件股份有限公司
135
     - 66、北京递蓝科软件股份有限公司
136
     - 67、郑州创海软件科技公司
136
     - 67、郑州创海软件科技公司
137
+    - 68、北京国槐信息科技有限公司
138
+    - 69、浪潮软件集团
139
+    - 70、多立恒(北京)信息技术有限公司
140
+    - 71、广州极迅客信息科技有限公司
141
+    - 72、赫基(中国)集团股份有限公司
142
+    - 73、海投汇
143
+    - 74、上海润益创业孵化器管理股份有限公司
144
+    - 75、汉纳森(厦门)数据股份有限公司
145
+    - 76、安信信托
146
+    - 77、岚儒财富
147
+    - 78、捷道软件
148
+    - 79、湖北享七网络科技有限公司
149
+    - 80、湖南创发科技责任有限公司
150
+    - 81、深圳小安时代互联网金融服务有限公司
151
+    - 82、湖北享七网络科技有限公司
152
+    - 83、钱包行云(北京)科技有限公司
153
+    - 84、360金融 (360)
154
+    - 85、易企秀
155
+    - 86、摩贝(上海)生物科技有限公司
156
+    - 87、广东芯智慧科技有限公司
157
+    - 88、联想集团 (联想)
158
+    - 89、怪兽充电
159
+    - 90、行圆汽车
160
+    - 91、深圳店店通科技邮箱公司
161
+    - 92、京东 (京东)
162
+    - 93、米庄理财
163
+    - 94、咖啡易融
164
+    - 95、梧桐诚选
165
+    - 96、恒大地产 (恒大)
137
 	- ……
166
 	- ……
138
 
167
 
139
 > 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
168
 > 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
227
     ### 报警邮箱
256
     ### 报警邮箱
228
     xxl.job.mail.host=smtp.163.com
257
     xxl.job.mail.host=smtp.163.com
229
     xxl.job.mail.port=25
258
     xxl.job.mail.port=25
259
+    xxl.job.mail.ssl=false
230
     xxl.job.mail.username=ovono802302@163.com
260
     xxl.job.mail.username=ovono802302@163.com
231
     xxl.job.mail.password=asdfzxcv
261
     xxl.job.mail.password=asdfzxcv
232
     xxl.job.mail.sendFrom=ovono802302@163.com
262
     xxl.job.mail.sendFrom=ovono802302@163.com
246
 如果已经正确进行上述配置,可将项目编译打war包并部署到tomcat中。
276
 如果已经正确进行上述配置,可将项目编译打war包并部署到tomcat中。
247
 调度中心访问地址:http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址),登录后运行界面如下图所示
277
 调度中心访问地址:http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址),登录后运行界面如下图所示
248
 
278
 
249
-![输入图片说明](https://static.oschina.net/uploads/img/201705/08194505_6yC0.png "在这里输入图片标题")
279
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_6yC0.png "在这里输入图片标题")
250
 
280
 
251
 至此“调度中心”项目已经部署成功。
281
 至此“调度中心”项目已经部署成功。
252
 
282
 
351
 #### 步骤一:新建任务:
381
 #### 步骤一:新建任务:
352
 登录调度中心,点击下图所示“新建任务”按钮,新建示例任务。然后,参考下面截图中任务的参数配置,点击保存。
382
 登录调度中心,点击下图所示“新建任务”按钮,新建示例任务。然后,参考下面截图中任务的参数配置,点击保存。
353
 
383
 
354
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27205910_o8HQ.png "在这里输入图片标题")
384
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_o8HQ.png "在这里输入图片标题")
355
 
385
 
356
-![输入图片说明](https://static.oschina.net/uploads/img/201712/25183654_ZAsz.png "在这里输入图片标题")
386
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAsz.png "在这里输入图片标题")
357
 
387
 
358
 
388
 
359
 #### 步骤二:“GLUE模式(Java)” 任务开发:
389
 #### 步骤二:“GLUE模式(Java)” 任务开发:
360
 请点击任务右侧 “GLUE” 按钮,进入 “GLUE编辑器开发界面” ,见下图。“GLUE模式(Java)” 运行模式的任务默认已经初始化了示例任务代码,即打印Hello World。
390
 请点击任务右侧 “GLUE” 按钮,进入 “GLUE编辑器开发界面” ,见下图。“GLUE模式(Java)” 运行模式的任务默认已经初始化了示例任务代码,即打印Hello World。
361
 ( “GLUE模式(Java)” 运行模式的任务实际上是一段继承自IJobHandler的Java类代码,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务,详细介绍请查看第三章节)
391
 ( “GLUE模式(Java)” 运行模式的任务实际上是一段继承自IJobHandler的Java类代码,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务,详细介绍请查看第三章节)
362
 
392
 
363
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27210307_Fgql.png "在这里输入图片标题")
393
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Fgql.png "在这里输入图片标题")
364
 
394
 
365
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27210314_dNUJ.png "在这里输入图片标题")
395
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_dNUJ.png "在这里输入图片标题")
366
 
396
 
367
 #### 步骤三:触发执行:
397
 #### 步骤三:触发执行:
368
 请点击任务右侧 “执行” 按钮,可手动触发一次任务执行(通常情况下,通过配置Cron表达式进行任务调度出发)。
398
 请点击任务右侧 “执行” 按钮,可手动触发一次任务执行(通常情况下,通过配置Cron表达式进行任务调度出发)。
371
 请点击任务右侧 “日志” 按钮,可前往任务日志界面查看任务日志。
401
 请点击任务右侧 “日志” 按钮,可前往任务日志界面查看任务日志。
372
 在任务日志界面中,可查看该任务的历史调度记录以及每一次调度的任务调度信息、执行参数和执行信息。运行中的任务点击右侧的“执行日志”按钮,可进入日志控制台查看实时执行日志。
402
 在任务日志界面中,可查看该任务的历史调度记录以及每一次调度的任务调度信息、执行参数和执行信息。运行中的任务点击右侧的“执行日志”按钮,可进入日志控制台查看实时执行日志。
373
 
403
 
374
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27232850_inc8.png "在这里输入图片标题")
404
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_inc8.png "在这里输入图片标题")
375
 
405
 
376
 在日志控制台,可以Rolling方式实时查看任务在执行器一侧运行输出的日志信息,实时监控任务进度;
406
 在日志控制台,可以Rolling方式实时查看任务在执行器一侧运行输出的日志信息,实时监控任务进度;
377
 
407
 
378
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27211631_eYrv.png "在这里输入图片标题")
408
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_eYrv.png "在这里输入图片标题")
379
 
409
 
380
 ## 三、任务详解
410
 ## 三、任务详解
381
 
411
 
426
      - 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
456
      - 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
427
     (可参考Sample示例执行器中的DemoJobHandler,见下图)
457
     (可参考Sample示例执行器中的DemoJobHandler,见下图)
428
 
458
 
429
-![输入图片说明](https://static.oschina.net/uploads/img/201607/23232347_oLlM.png "在这里输入图片标题")
459
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_oLlM.png "在这里输入图片标题")
430
 
460
 
431
 #### 步骤二:调度中心,新建调度任务
461
 #### 步骤二:调度中心,新建调度任务
432
 参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "BEAN模式",JobHandler属性填写任务注解“@JobHandler”中定义的值;
462
 参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "BEAN模式",JobHandler属性填写任务注解“@JobHandler”中定义的值;
433
 
463
 
434
-![输入图片说明](https://static.oschina.net/uploads/img/201712/25183654_ZAsz.png "在这里输入图片标题")
464
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAsz.png "在这里输入图片标题")
435
 
465
 
436
 ### 3.2 GLUE模式(Java)
466
 ### 3.2 GLUE模式(Java)
437
 任务以源码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler。开发流程如下:
467
 任务以源码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler。开发流程如下:
439
 #### 步骤一:调度中心,新建调度任务:
469
 #### 步骤一:调度中心,新建调度任务:
440
 参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "GLUE模式(Java)";
470
 参考上文“配置属性详细说明”对新建的任务进行参数配置,运行模式选中 "GLUE模式(Java)";
441
 
471
 
442
-![输入图片说明](https://static.oschina.net/uploads/img/201712/25183837_tJOq.png "在这里输入图片标题")
472
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_tJOq.png "在这里输入图片标题")
443
 
473
 
444
 #### 步骤二:开发任务代码:
474
 #### 步骤二:开发任务代码:
445
 选中指定任务,点击该任务右侧“GLUE”按钮,将会前往GLUE任务的Web IDE界面,在该界面支持对任务代码进行开发(也可以在IDE中开发完成后,复制粘贴到编辑中)。
475
 选中指定任务,点击该任务右侧“GLUE”按钮,将会前往GLUE任务的Web IDE界面,在该界面支持对任务代码进行开发(也可以在IDE中开发完成后,复制粘贴到编辑中)。
446
 
476
 
447
 版本回溯功能(支持30个版本的版本回溯):在GLUE任务的Web IDE界面,选择右上角下拉框“版本回溯”,会列出该GLUE的更新历史,选择相应版本即可显示该版本代码,保存后GLUE代码即回退到对应的历史版本;
477
 版本回溯功能(支持30个版本的版本回溯):在GLUE任务的Web IDE界面,选择右上角下拉框“版本回溯”,会列出该GLUE的更新历史,选择相应版本即可显示该版本代码,保存后GLUE代码即回退到对应的历史版本;
448
 
478
 
449
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27210314_dNUJ.png "在这里输入图片标题")
479
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_dNUJ.png "在这里输入图片标题")
450
 
480
 
451
 ### 3.3 GLUE模式(Shell)
481
 ### 3.3 GLUE模式(Shell)
452
 
482
 
458
 
488
 
459
 该模式的任务实际上是一段 "shell" 脚本;
489
 该模式的任务实际上是一段 "shell" 脚本;
460
 
490
 
461
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27232259_iUw0.png "在这里输入图片标题")
491
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_iUw0.png "在这里输入图片标题")
462
 
492
 
463
 ### 3.4 GLUE模式(Python)
493
 ### 3.4 GLUE模式(Python)
464
 
494
 
470
 
500
 
471
 该模式的任务实际上是一段 "python" 脚本;
501
 该模式的任务实际上是一段 "python" 脚本;
472
 
502
 
473
-![输入图片说明](https://static.oschina.net/uploads/img/201704/27232305_BPLG.png "在这里输入图片标题")
503
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_BPLG.png "在这里输入图片标题")
474
 
504
 
475
 ### 3.5 GLUE模式(NodeJS)
505
 ### 3.5 GLUE模式(NodeJS)
476
 
506
 
487
 
517
 
488
 ### 4.0 配置执行器  
518
 ### 4.0 配置执行器  
489
 点击进入"执行器管理"界面, 如下图:
519
 点击进入"执行器管理"界面, 如下图:
490
-![输入图片说明](https://static.oschina.net/uploads/img/201703/12223509_Hr2T.png "在这里输入图片标题")
520
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Hr2T.png "在这里输入图片标题")
491
 
521
 
492
     1、"调度中心OnLine:"右侧显示在线的"调度中心"列表, 任务执行结束后, 将会以failover的模式进行回调调度中心通知执行结果, 避免回调的单点风险;
522
     1、"调度中心OnLine:"右侧显示在线的"调度中心"列表, 任务执行结束后, 将会以failover的模式进行回调调度中心通知执行结果, 避免回调的单点风险;
493
     2、"执行器列表" 中显示在线的执行器列表, 可通过"OnLine 机器"查看对应执行器的集群机器。
523
     2、"执行器列表" 中显示在线的执行器列表, 可通过"OnLine 机器"查看对应执行器的集群机器。
494
 
524
 
495
 点击按钮 "+新增执行器" 弹框如下图, 可新增执行器配置:
525
 点击按钮 "+新增执行器" 弹框如下图, 可新增执行器配置:
496
 
526
 
497
-![输入图片说明](https://static.oschina.net/uploads/img/201712/25183958_V3vF.png "在这里输入图片标题")
527
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_V3vF.png "在这里输入图片标题")
498
 
528
 
499
 ### 执行器属性说明
529
 ### 执行器属性说明
500
 
530
 
522
 可对任务进行“暂停”和“恢复”操作。
552
 可对任务进行“暂停”和“恢复”操作。
523
 需要注意的是,此处的暂停/恢复仅针对任务的后续调度触发行为,不会影响到已经触发的调度任务,如需终止已经触发的调度任务,可查看“4.8 终止运行中的任务”
553
 需要注意的是,此处的暂停/恢复仅针对任务的后续调度触发行为,不会影响到已经触发的调度任务,如需终止已经触发的调度任务,可查看“4.8 终止运行中的任务”
524
 
554
 
525
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24130337_ZAhX.png "在这里输入图片标题")
555
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_ZAhX.png "在这里输入图片标题")
526
 
556
 
527
 ### 4.5 手动触发一次调度
557
 ### 4.5 手动触发一次调度
528
 点击“执行”按钮,可手动触发一次任务调度,不影响原有调度规则。
558
 点击“执行”按钮,可手动触发一次任务调度,不影响原有调度规则。
529
 
559
 
530
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24133348_Z5wp.png "在这里输入图片标题")
560
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Z5wp.png "在这里输入图片标题")
531
 
561
 
532
 ### 4.6 查看调度日志
562
 ### 4.6 查看调度日志
533
 点击“日志”按钮,可以查看任务历史调度日志。在历史调入日志界面可查看每次任务调度的调度结果、执行结果等,点击“执行日志”按钮可查看执行器完整日志。
563
 点击“日志”按钮,可以查看任务历史调度日志。在历史调入日志界面可查看每次任务调度的调度结果、执行结果等,点击“执行日志”按钮可查看执行器完整日志。
534
 
564
 
535
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24133500_9235.png "在这里输入图片标题")
565
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_9235.png "在这里输入图片标题")
536
 
566
 
537
-![输入图片说明](https://static.oschina.net/uploads/img/201712/25184206_UDSo.png "在这里输入图片标题")
567
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_UDSo.png "在这里输入图片标题")
538
 
568
 
539
     调度时间:"调度中心"触发本次调度并向"执行器"发送任务执行信号的时间;
569
     调度时间:"调度中心"触发本次调度并向"执行器"发送任务执行信号的时间;
540
     调度结果:"调度中心"触发本次调度的结果,200表示成功,500或其他表示失败;
570
     调度结果:"调度中心"触发本次调度的结果,200表示成功,500或其他表示失败;
552
 ### 4.7 查看执行日志
582
 ### 4.7 查看执行日志
553
 点击执行日志右侧的 “执行日志” 按钮,可跳转至执行日志界面,可以查看业务代码中打印的完整日志,如下图;
583
 点击执行日志右侧的 “执行日志” 按钮,可跳转至执行日志界面,可以查看业务代码中打印的完整日志,如下图;
554
 
584
 
555
-![输入图片说明](https://static.oschina.net/uploads/img/201703/25124816_tvGI.png "在这里输入图片标题")
585
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_tvGI.png "在这里输入图片标题")
556
 
586
 
557
 ### 4.8 终止运行中的任务
587
 ### 4.8 终止运行中的任务
558
 仅针对执行中的任务。
588
 仅针对执行中的任务。
559
 在任务日志界面,点击右侧的“终止任务”按钮,将会向本次任务对应的执行器发送任务终止请求,将会终止掉本次任务,同时会清空掉整个任务执行队列。
589
 在任务日志界面,点击右侧的“终止任务”按钮,将会向本次任务对应的执行器发送任务终止请求,将会终止掉本次任务,同时会清空掉整个任务执行队列。
560
 
590
 
561
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24140048_hIci.png "在这里输入图片标题")
591
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_hIci.png "在这里输入图片标题")
562
 
592
 
563
 任务终止时通过 "interrupt" 执行线程的方式实现, 将会触发 "InterruptedException" 异常。因此如果JobHandler内部catch到了该异常并消化掉的话, 任务终止功能将不可用。
593
 任务终止时通过 "interrupt" 执行线程的方式实现, 将会触发 "InterruptedException" 异常。因此如果JobHandler内部catch到了该异常并消化掉的话, 任务终止功能将不可用。
564
 
594
 
579
 
609
 
580
 ### 4.9 删除执行日志
610
 ### 4.9 删除执行日志
581
 在任务日志界面,选中执行器和任务之后,点击右侧的"删除"按钮将会出现"日志清理"弹框,弹框中支持选择不同类型的日志清理策略,选中后点击"确定"按钮即可进行日志清理操作;
611
 在任务日志界面,选中执行器和任务之后,点击右侧的"删除"按钮将会出现"日志清理"弹框,弹框中支持选择不同类型的日志清理策略,选中后点击"确定"按钮即可进行日志清理操作;
582
-![输入图片说明](https://static.oschina.net/uploads/img/201705/08210711_Ypik.png "在这里输入图片标题")
612
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Ypik.png "在这里输入图片标题")
583
 
613
 
584
-![输入图片说明](https://static.oschina.net/uploads/img/201705/08211152_EB65.png "在这里输入图片标题")
614
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_EB65.png "在这里输入图片标题")
585
 
615
 
586
 ### 4.10 删除任务
616
 ### 4.10 删除任务
587
 点击删除按钮,可以删除对应任务。
617
 点击删除按钮,可以删除对应任务。
588
 
618
 
589
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24140641_Z9Qr.png "在这里输入图片标题")
619
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Z9Qr.png "在这里输入图片标题")
590
 
620
 
591
 
621
 
592
 ## 五、总体设计
622
 ## 五、总体设计
602
 
632
 
603
 XXL-JOB首先定制了Quartz原生表结构前缀(XXL_JOB_QRTZ_)。
633
 XXL-JOB首先定制了Quartz原生表结构前缀(XXL_JOB_QRTZ_)。
604
 
634
 
605
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24143957_bNwm.png "在这里输入图片标题")
635
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_bNwm.png "在这里输入图片标题")
606
 
636
 
607
 然后,在此基础上新增了几张张扩展表,如下:
637
 然后,在此基础上新增了几张张扩展表,如下:
608
     - XXL_JOB_QRTZ_TRIGGER_GROUP:执行器信息表,维护任务执行器信息;
638
     - XXL_JOB_QRTZ_TRIGGER_GROUP:执行器信息表,维护任务执行器信息;
631
 
661
 
632
 #### 5.3.3 架构图
662
 #### 5.3.3 架构图
633
 
663
 
634
-![输入图片说明](https://static.oschina.net/uploads/img/201801/03103007_Qohm.png "在这里输入图片标题")
664
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Qohm.png "在这里输入图片标题")
635
 
665
 
636
 ### 5.4 调度模块剖析
666
 ### 5.4 调度模块剖析
637
 #### 5.4.1 quartz的不足
667
 #### 5.4.1 quartz的不足
638
 Quartz作为开源作业调度中的佼佼者,是作业调度的首选。但是集群环境中Quartz采用API的方式对任务进行管理,从而可以避免上述问题,但是同样存在以下问题:
668
 Quartz作为开源作业调度中的佼佼者,是作业调度的首选。但是集群环境中Quartz采用API的方式对任务进行管理,从而可以避免上述问题,但是同样存在以下问题:
639
-    - 问题一:调用API的的方式操作任务,不人性化;
640
-    - 问题二:需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重。
641
-    - 问题三:调度逻辑和QuartzJobBean耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多,同时调度任务逻辑逐渐加重的情况加,此时调度系统的性能将大大受限于业务;
669
+   
670
+- 问题一:调用API的的方式操作任务,不人性化;
671
+- 问题二:需要持久化业务QuartzJobBean到底层数据表中,系统侵入性相当严重。
672
+- 问题三:调度逻辑和QuartzJobBean耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多,同时调度任务逻辑逐渐加重的情况加,此时调度系统的性能将大大受限于业务;
673
+- 问题四:quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,会导致节点负载悬殊非常大;而XXL-JOB通过执行器实现“协同分配式”运行任务,充分发挥集群优势,负载各节点均衡。
674
+
642
 XXL-JOB弥补了quartz的上述不足之处。
675
 XXL-JOB弥补了quartz的上述不足之处。
643
 
676
 
644
 #### 5.4.2 RemoteHttpJobBean
677
 #### 5.4.2 RemoteHttpJobBean
727
 当任务"路由策略"选择"故障转移(FAILOVER)"时,当调度中心每次发起调度请求时,会按照顺序对执行器发出心跳检测请求,第一个检测为存活状态的执行器将会被选定并发送调度请求。
760
 当任务"路由策略"选择"故障转移(FAILOVER)"时,当调度中心每次发起调度请求时,会按照顺序对执行器发出心跳检测请求,第一个检测为存活状态的执行器将会被选定并发送调度请求。
728
 
761
 
729
 调度成功后,可在日志监控界面查看“调度备注”,如下;
762
 调度成功后,可在日志监控界面查看“调度备注”,如下;
730
-![输入图片说明](https://static.oschina.net/uploads/img/201703/12230733_jrdI.png "在这里输入图片标题")
763
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_jrdI.png "在这里输入图片标题")
731
 
764
 
732
 “调度备注”可以看出本地调度运行轨迹,执行器的"注册方式"、"地址列表"和任务的"路由策略"。"故障转移(FAILOVER)"路由策略下,调度中心首先对第一个地址进行心跳检测,心跳失败因此自动跳过,第二个依然心跳检测失败……
765
 “调度备注”可以看出本地调度运行轨迹,执行器的"注册方式"、"地址列表"和任务的"路由策略"。"故障转移(FAILOVER)"路由策略下,调度中心首先对第一个地址进行心跳检测,心跳失败因此自动跳过,第二个依然心跳检测失败……
733
 直至心跳检测第三个地址“127.0.0.1:9999”成功,选定为“目标执行器”;然后对“目标执行器”发送调度请求,调度流程结束,等待执行器回调执行结果。
766
 直至心跳检测第三个地址“127.0.0.1:9999”成功,选定为“目标执行器”;然后对“目标执行器”发送调度请求,调度流程结束,等待执行器回调执行结果。
758
 
791
 
759
 在任务日志界面,点击任务的“执行备注”的“查看”按钮,可以看到匹配子任务以及触发子任务执行的日志信息,如无信息则表示未触发子任务执行,可参考下图。
792
 在任务日志界面,点击任务的“执行备注”的“查看”按钮,可以看到匹配子任务以及触发子任务执行的日志信息,如无信息则表示未触发子任务执行,可参考下图。
760
 
793
 
761
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24194134_Wb2o.png "在这里输入图片标题")
794
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_Wb2o.png "在这里输入图片标题")
762
 
795
 
763
-![输入图片说明](https://static.oschina.net/uploads/img/201607/24194212_jOAU.png "在这里输入图片标题")
796
+![输入图片说明](https://raw.githubusercontent.com/xuxueli/xxl-job/master/doc/images/img_jOAU.png "在这里输入图片标题")
764
 
797
 
765
 ### 5.5 任务 "运行模式" 剖析
798
 ### 5.5 任务 "运行模式" 剖析
766
 #### 5.5.1 "Bean模式" 任务
799
 #### 5.5.1 "Bean模式" 任务
773
 
806
 
774
 #### 5.5.3 GLUE模式(Shell) + GLUE模式(Python) + GLUE模式(NodeJS)
807
 #### 5.5.3 GLUE模式(Shell) + GLUE模式(Python) + GLUE模式(NodeJS)
775
 开发步骤:可参考 "章节三" ;
808
 开发步骤:可参考 "章节三" ;
776
-原理:脚本任务的源码托管在调度中心,脚本逻辑在执行器运行。当触发脚本任务时,执行器会加载脚本源码在执行器机器上生成一份脚本文件,然后通过Java代码调用该脚本;并且实时将脚本输出日志写到任务日志文件中,从而在调度中心可以实时监控脚本运行情况;脚本返回码为0时表示执行成功,其他标示执行失败。
809
+原理:脚本任务的源码托管在调度中心,脚本逻辑在执行器运行。当触发脚本任务时,执行器会加载脚本源码在执行器机器上生成一份脚本文件,然后通过Java代码调用该脚本;并且实时将脚本输出日志写到任务日志文件中,从而在调度中心可以实时监控脚本运行情况;
777
 
810
 
778
 目前支持的脚本类型如下:
811
 目前支持的脚本类型如下:
779
 
812
 
780
     - shell脚本:任务运行模式选择为 "GLUE模式(Shell)"时支持 "shell" 脚本任务;
813
     - shell脚本:任务运行模式选择为 "GLUE模式(Shell)"时支持 "shell" 脚本任务;
781
     - python脚本:任务运行模式选择为 "GLUE模式(Python)"时支持 "python" 脚本任务;
814
     - python脚本:任务运行模式选择为 "GLUE模式(Python)"时支持 "python" 脚本任务;
782
     - nodejs脚本:务运行模式选择为 "GLUE模式(NodeJS)"时支持 "nodejs" 脚本任务;
815
     - nodejs脚本:务运行模式选择为 "GLUE模式(NodeJS)"时支持 "nodejs" 脚本任务;
783
-    
816
+
817
+脚本任务通过 Exit Code 判断任务执行结果,状态码可参考章节 "5.15 任务执行结果说明";
784
 
818
 
785
 #### 5.5.4 执行器
819
 #### 5.5.4 执行器
786
 执行器实际上是一个内嵌的Jetty服务器,默认端口9999(配置项:xxl.job.executor.port)。
820
 执行器实际上是一个内嵌的Jetty服务器,默认端口9999(配置项:xxl.job.executor.port)。
895
     - 调度中心调度失败时,任务失败处理策略选择"失败重试",将会自动重试一次;
929
     - 调度中心调度失败时,任务失败处理策略选择"失败重试",将会自动重试一次;
896
     - 执行器运行失败时,任务执行结果返回"失败重试(IJobHandler.FAIL_RETRY)"回调,将会自动重试一次;
930
     - 执行器运行失败时,任务执行结果返回"失败重试(IJobHandler.FAIL_RETRY)"回调,将会自动重试一次;
897
 
931
 
932
+### 5.14 执行器灰度上线
933
+调度中心与业务解耦,只需部署一次后常年不需要维护。但是,执行器中托管运行着业务作业,作业上线和变更需要重启执行器,尤其是Bean模式任务。
934
+执行器重启可能会中断运行中的任务。但是,XXL-JOB得益于自建执行器与自建注册中心,可以通过灰度上线的方式,避免因重启导致的任务中断的问题。
935
+
936
+步骤如下:
937
+- 1、执行器改为手动注册,下线一半机器列表(A组),线上运行另一半机器列表(B组);
938
+- 2、等待A组机器任务运行结束并编译上线;执行器注册地址替换为A组;
939
+- 3、等待B组机器任务运行结束并编译上线;执行器注册地址替换为A组+B组;
940
+操作结束;
941
+
942
+### 5.15 任务执行结果说明
943
+系统根据以下标准判断任务执行结果,可参考之。
944
+
945
+-- | Bean/Glue(Java) | Glue(Shell) 等脚本任务
946
+--- | --- | ---
947
+成功 | IJobHandler.SUCCESS | 0
948
+失败 | IJobHandler.FAIL | -1(其他)
949
+失败重试 | IJobHandler.FAIL_RETRY | 101
950
+
898
 
951
 
899
 ## 六、版本更新日志
952
 ## 六、版本更新日志
900
 ### 6.1 版本 V1.1.x,新特性[2015-12-05]
953
 ### 6.1 版本 V1.1.x,新特性[2015-12-05]
1154
 - 8、项目依赖全量升级至较新稳定版本,如spring、jackson等等;
1207
 - 8、项目依赖全量升级至较新稳定版本,如spring、jackson等等;
1155
 
1208
 
1156
 ### 6.22 版本 V1.9.2 特性[迭代中]
1209
 ### 6.22 版本 V1.9.2 特性[迭代中]
1210
+- 1、[迭代中]支持通过API服务操作任务信息;
1211
+- 2、[迭代中]任务告警逻辑调整:任务调度,以及任务回调失败时,均推送监控队列。后期考虑通过任务Log字段控制告警状态;
1212
+- 3、[迭代中]任务超时设置,超时任务主动终止;
1213
+- 4、任务属性枚举 "任务模式、阻塞策略" 国际化优化;
1214
+- 5、任务日志表状态字段类型优化;
1215
+- 6、Glue(Shell) 等脚本任务支持失败重试;
1216
+- 7、告警邮箱支持SSL配置;
1217
+- 8、Window机器下File.separator不兼容问题修复;
1218
+- 9、任务日志查询速度优化,百万级别日志量搜索速度提升1000倍;
1219
+- 10、底层LocalCache组件兼容性优化,支持jdk、jdk10编译部署;
1220
+- 11、任务回调结果优化,支持展示在Rolling log中,方便问题排查;
1221
+- 12、脚本任务异常Log输出优化;
1222
+- 13、任务线程停止变量修饰符优化;
1223
+- 14、脚本任务Log文件流关闭优化;
1224
+- 15、任务报表成功、失败和进行中统计问题修复;
1225
+- 16、自研Log组件参数占位符改为"{}",并修复打印有参日志时参数不匹配导致报错的问题;
1157
 
1226
 
1158
 
1227
 
1159
 ### TODO LIST
1228
 ### TODO LIST
1165
 - 6、调度任务优先级;
1234
 - 6、调度任务优先级;
1166
 - 7、移除quartz依赖,重写调度模块:新增或恢复任务时将下次执行记录插入delayqueue,调度中心集群竞争分布式锁,成功节点批量加载到期delayqueue数据,批量执行。
1235
 - 7、移除quartz依赖,重写调度模块:新增或恢复任务时将下次执行记录插入delayqueue,调度中心集群竞争分布式锁,成功节点批量加载到期delayqueue数据,批量执行。
1167
 - 8、springboot 和 docker镜像,并且推送docker镜像到中央仓库,更进一步实现产品开箱即用;
1236
 - 8、springboot 和 docker镜像,并且推送docker镜像到中央仓库,更进一步实现产品开箱即用;
1168
-- 9、任务告警逻辑调整:任务调度,以及任务回调失败时,均推送监控队列。后期考虑通过任务Log字段控制告警状态
1237
+- 9、多数据库支持
1169
 - 10、执行器Log清理功能:调度中心Log删除时同步删除执行器中的Log文件;
1238
 - 10、执行器Log清理功能:调度中心Log删除时同步删除执行器中的Log文件;
1170
 - 11、Bean模式任务,JobHandler自动从执行器中查询展示为下拉框,选择后自动填充任务名称等属性;
1239
 - 11、Bean模式任务,JobHandler自动从执行器中查询展示为下拉框,选择后自动填充任务名称等属性;
1171
 - 12、API事件触发类型任务(更类似MQ消息)支持"动态传参、延时消费";该类型任务不走Quartz,单独建立MQ消息表,调度中心竞争触发;
1240
 - 12、API事件触发类型任务(更类似MQ消息)支持"动态传参、延时消费";该类型任务不走Quartz,单独建立MQ消息表,调度中心竞争触发;
1175
 - 16、新增API服务 "XxlJobService" ,支持通过API服务来维护管理任务信息;
1244
 - 16、新增API服务 "XxlJobService" ,支持通过API服务来维护管理任务信息;
1176
 - 17、新增任务默认运行状态,任务更新时运行状态保持不变;
1245
 - 17、新增任务默认运行状态,任务更新时运行状态保持不变;
1177
 - 18、告警邮件中展示失败告警信息;
1246
 - 18、告警邮件中展示失败告警信息;
1178
-- 19、多数据库支持;
1179
-- 20、提供多版本执行器:不依赖容器版本、不内嵌Jetty版本等;
1180
-- 21、支持通过API服务操作任务信息;
1181
-- 22、任务超时设置,超时任务主动终止;
1247
+- 19、提供多版本执行器:不依赖容器版本、不内嵌Jetty版本(通过配置executoraddress替换jetty通讯)等;
1248
+- 20、注册中心支持扩展,除默认基于DB之外,支持扩展接入第三方注册中心如zk、eureka等;
1249
+- 21、依赖Core内部国际化处理;
1250
+- 22、故障转移、失败重试等策略,规范化合并归类;
1251
+- 23、流程任务,支持参数传递;
1252
+- 24、SimpleTrigger 支持;
1253
+- 25、springboot热部署支持;
1182
 
1254
 
1183
 
1255
 
1184
 ## 七、其他
1256
 ## 七、其他

+ 4 - 3
doc/db/tables_xxl_job.sql View File

181
   `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
181
   `executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
182
   `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
182
   `executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
183
   `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
183
   `trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
184
-  `trigger_code` varchar(255) NOT NULL DEFAULT '0' COMMENT '调度-结果',
184
+  `trigger_code` int(11) NOT NULL COMMENT '调度-结果',
185
   `trigger_msg` varchar(2048) DEFAULT NULL COMMENT '调度-日志',
185
   `trigger_msg` varchar(2048) DEFAULT NULL COMMENT '调度-日志',
186
   `handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
186
   `handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
187
-  `handle_code` varchar(255) NOT NULL DEFAULT '0' COMMENT '执行-状态',
187
+  `handle_code` int(11) NOT NULL COMMENT '执行-状态',
188
   `handle_msg` varchar(2048) DEFAULT NULL COMMENT '执行-日志',
188
   `handle_msg` varchar(2048) DEFAULT NULL COMMENT '执行-日志',
189
-  PRIMARY KEY (`id`)
189
+  PRIMARY KEY (`id`),
190
+  KEY `I_trigger_time` (`trigger_time`)
190
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
191
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
191
 
192
 
192
 CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOGGLUE` (
193
 CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOGGLUE` (

BIN
doc/images/img_6yC0.png View File


BIN
doc/images/img_9235.png View File


BIN
doc/images/img_BPLG.png View File


BIN
doc/images/img_EB65.png View File


BIN
doc/images/img_Fgql.png View File


BIN
doc/images/img_Hr2T.png View File


BIN
doc/images/img_Qohm.png View File


BIN
doc/images/img_UDSo.png View File


BIN
doc/images/img_V3vF.png View File


BIN
doc/images/img_Wb2o.png View File


BIN
doc/images/img_Ypik.png View File


BIN
doc/images/img_Z5wp.png View File


BIN
doc/images/img_Z9Qr.png View File


BIN
doc/images/img_ZAhX.png View File


BIN
doc/images/img_ZAsz.png View File


BIN
doc/images/img_bNwm.png View File


BIN
doc/images/img_dNUJ.png View File


BIN
doc/images/img_eYrv.png View File


BIN
doc/images/img_hIci.png View File


BIN
doc/images/img_iUw0.png View File


BIN
doc/images/img_inc8.png View File


BIN
doc/images/img_jOAU.png View File


BIN
doc/images/img_jrdI.png View File


BIN
doc/images/img_o8HQ.png View File


BIN
doc/images/img_oLlM.png View File


BIN
doc/images/img_tJOq.png View File


BIN
doc/images/img_tvGI.png View File


+ 7 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/conf/XxlJobAdminConfig.java View File

27
     @Value("${xxl.job.mail.port}")
27
     @Value("${xxl.job.mail.port}")
28
     private String mailPort;
28
     private String mailPort;
29
 
29
 
30
+    @Value("${xxl.job.mail.ssl}")
31
+    private boolean mailSSL;
32
+
30
     @Value("${xxl.job.mail.username}")
33
     @Value("${xxl.job.mail.username}")
31
     private String mailUsername;
34
     private String mailUsername;
32
 
35
 
54
         return mailPort;
57
         return mailPort;
55
     }
58
     }
56
 
59
 
60
+    public boolean isMailSSL() {
61
+        return mailSSL;
62
+    }
63
+
57
     public String getMailUsername() {
64
     public String getMailUsername() {
58
         return mailUsername;
65
         return mailUsername;
59
     }
66
     }

+ 11 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/schedule/XxlJobDynamicScheduler.java View File

4
 import com.xxl.job.admin.core.model.XxlJobInfo;
4
 import com.xxl.job.admin.core.model.XxlJobInfo;
5
 import com.xxl.job.admin.core.thread.JobFailMonitorHelper;
5
 import com.xxl.job.admin.core.thread.JobFailMonitorHelper;
6
 import com.xxl.job.admin.core.thread.JobRegistryMonitorHelper;
6
 import com.xxl.job.admin.core.thread.JobRegistryMonitorHelper;
7
+import com.xxl.job.admin.core.util.I18nUtil;
7
 import com.xxl.job.admin.dao.XxlJobGroupDao;
8
 import com.xxl.job.admin.dao.XxlJobGroupDao;
8
 import com.xxl.job.admin.dao.XxlJobInfoDao;
9
 import com.xxl.job.admin.dao.XxlJobInfoDao;
9
 import com.xxl.job.admin.dao.XxlJobLogDao;
10
 import com.xxl.job.admin.dao.XxlJobLogDao;
10
 import com.xxl.job.admin.dao.XxlJobRegistryDao;
11
 import com.xxl.job.admin.dao.XxlJobRegistryDao;
11
 import com.xxl.job.core.biz.AdminBiz;
12
 import com.xxl.job.core.biz.AdminBiz;
12
 import com.xxl.job.core.biz.ExecutorBiz;
13
 import com.xxl.job.core.biz.ExecutorBiz;
14
+import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
13
 import com.xxl.job.core.rpc.netcom.NetComClientProxy;
15
 import com.xxl.job.core.rpc.netcom.NetComClientProxy;
14
 import com.xxl.job.core.rpc.netcom.NetComServerFactory;
16
 import com.xxl.job.core.rpc.netcom.NetComServerFactory;
15
 import org.quartz.*;
17
 import org.quartz.*;
76
         NetComServerFactory.putService(AdminBiz.class, XxlJobDynamicScheduler.adminBiz);
78
         NetComServerFactory.putService(AdminBiz.class, XxlJobDynamicScheduler.adminBiz);
77
         NetComServerFactory.setAccessToken(accessToken);
79
         NetComServerFactory.setAccessToken(accessToken);
78
 
80
 
81
+        // init i18n
82
+        initI18n();
83
+
79
         // valid
84
         // valid
80
         Assert.notNull(scheduler, "quartz scheduler is null");
85
         Assert.notNull(scheduler, "quartz scheduler is null");
81
         logger.info(">>>>>>>>> init xxl-job admin success.");
86
         logger.info(">>>>>>>>> init xxl-job admin success.");
82
     }
87
     }
83
 
88
 
89
+    private void initI18n(){
90
+        for (ExecutorBlockStrategyEnum item:ExecutorBlockStrategyEnum.values()) {
91
+            item.setTitle(I18nUtil.getString("jobconf_block_".concat(item.name())));
92
+        }
93
+    }
94
+
84
     public void destroy(){
95
     public void destroy(){
85
         // admin registry stop
96
         // admin registry stop
86
         JobRegistryMonitorHelper.getInstance().toStop();
97
         JobRegistryMonitorHelper.getInstance().toStop();

+ 5 - 5
xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobFailMonitorHelper.java View File

56
 									continue;
56
 									continue;
57
 								}
57
 								}
58
 								if (IJobHandler.SUCCESS.getCode() == log.getTriggerCode() && log.getHandleCode() == 0) {
58
 								if (IJobHandler.SUCCESS.getCode() == log.getTriggerCode() && log.getHandleCode() == 0) {
59
+									// job running
59
 									JobFailMonitorHelper.monitor(jobLogId);
60
 									JobFailMonitorHelper.monitor(jobLogId);
60
 									logger.info(">>>>>>>>>>> job monitor, job running, JobLogId:{}", jobLogId);
61
 									logger.info(">>>>>>>>>>> job monitor, job running, JobLogId:{}", jobLogId);
61
 								} else if (IJobHandler.SUCCESS.getCode() == log.getHandleCode()) {
62
 								} else if (IJobHandler.SUCCESS.getCode() == log.getHandleCode()) {
62
 									// job success, pass
63
 									// job success, pass
63
 									logger.info(">>>>>>>>>>> job monitor, job success, JobLogId:{}", jobLogId);
64
 									logger.info(">>>>>>>>>>> job monitor, job success, JobLogId:{}", jobLogId);
64
-								} else if (IJobHandler.FAIL.getCode() == log.getTriggerCode()
65
+								} else /*if (IJobHandler.FAIL.getCode() == log.getTriggerCode()
65
 										|| IJobHandler.FAIL.getCode() == log.getHandleCode()
66
 										|| IJobHandler.FAIL.getCode() == log.getHandleCode()
66
-										|| IJobHandler.TIMEOUT.getCode() == log.getHandleCode()
67
-										|| IJobHandler.FAIL_RETRY.getCode() == log.getHandleCode() ) {
67
+										|| IJobHandler.FAIL_RETRY.getCode() == log.getHandleCode() )*/ {
68
 									// job fail,
68
 									// job fail,
69
 									failAlarm(log);
69
 									failAlarm(log);
70
 									logger.info(">>>>>>>>>>> job monitor, job fail, JobLogId:{}", jobLogId);
70
 									logger.info(">>>>>>>>>>> job monitor, job fail, JobLogId:{}", jobLogId);
71
-								} else {
71
+								}/* else {
72
 									JobFailMonitorHelper.monitor(jobLogId);
72
 									JobFailMonitorHelper.monitor(jobLogId);
73
 									logger.info(">>>>>>>>>>> job monitor, job status unknown, JobLogId:{}", jobLogId);
73
 									logger.info(">>>>>>>>>>> job monitor, job status unknown, JobLogId:{}", jobLogId);
74
-								}
74
+								}*/
75
 							}
75
 							}
76
 						}
76
 						}
77
 
77
 

+ 1 - 1
xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/I18nUtil.java View File

30
             return prop;
30
             return prop;
31
         }
31
         }
32
         try {
32
         try {
33
-            // bild i18n prop
33
+            // build i18n prop
34
             String i18n = XxlJobAdminConfig.getAdminConfig().getI18n();
34
             String i18n = XxlJobAdminConfig.getAdminConfig().getI18n();
35
             i18n = StringUtils.isNotBlank(i18n)?("_"+i18n):i18n;
35
             i18n = StringUtils.isNotBlank(i18n)?("_"+i18n):i18n;
36
             String i18nFile = MessageFormat.format("i18n/message{0}.properties", i18n);
36
             String i18nFile = MessageFormat.format("i18n/message{0}.properties", i18n);

+ 2 - 1
xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/LocalCacheUtil.java View File

3
 import org.apache.commons.lang3.StringUtils;
3
 import org.apache.commons.lang3.StringUtils;
4
 
4
 
5
 import java.util.concurrent.ConcurrentHashMap;
5
 import java.util.concurrent.ConcurrentHashMap;
6
+import java.util.concurrent.ConcurrentMap;
6
 
7
 
7
 /**
8
 /**
8
  * local cache tool
9
  * local cache tool
11
  */
12
  */
12
 public class LocalCacheUtil {
13
 public class LocalCacheUtil {
13
 
14
 
14
-    private static ConcurrentHashMap<String, LocalCacheData> cacheRepository = new ConcurrentHashMap<>();
15
+    private static ConcurrentMap<String, LocalCacheData> cacheRepository = new ConcurrentHashMap<String, LocalCacheData>();   // 类型建议用抽象父类,兼容性更好;
15
     private static class LocalCacheData{
16
     private static class LocalCacheData{
16
         private String key;
17
         private String key;
17
         private Object val;
18
         private Object val;

+ 8 - 2
xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/MailUtil.java View File

35
 			//email.setSSL(true);
35
 			//email.setSSL(true);
36
 
36
 
37
 			email.setHostName(XxlJobAdminConfig.getAdminConfig().getMailHost());
37
 			email.setHostName(XxlJobAdminConfig.getAdminConfig().getMailHost());
38
-			email.setSmtpPort(Integer.valueOf(XxlJobAdminConfig.getAdminConfig().getMailPort()));
39
-			//email.setSslSmtpPort(port);
38
+
39
+			if (XxlJobAdminConfig.getAdminConfig().isMailSSL()) {
40
+				email.setSslSmtpPort(XxlJobAdminConfig.getAdminConfig().getMailPort());
41
+				email.setSSLOnConnect(true);
42
+			} else {
43
+				email.setSmtpPort(Integer.valueOf(XxlJobAdminConfig.getAdminConfig().getMailPort()));
44
+			}
45
+
40
 			email.setAuthenticator(new DefaultAuthenticator(XxlJobAdminConfig.getAdminConfig().getMailUsername(), XxlJobAdminConfig.getAdminConfig().getMailPassword()));
46
 			email.setAuthenticator(new DefaultAuthenticator(XxlJobAdminConfig.getAdminConfig().getMailUsername(), XxlJobAdminConfig.getAdminConfig().getMailPassword()));
41
 			email.setCharset(Charset.defaultCharset().name());
47
 			email.setCharset(Charset.defaultCharset().name());
42
 
48
 

+ 4 - 5
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java View File

6
 import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
6
 import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
7
 import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
7
 import com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler;
8
 import com.xxl.job.admin.core.util.I18nUtil;
8
 import com.xxl.job.admin.core.util.I18nUtil;
9
-import com.xxl.job.admin.core.util.LocalCacheUtil;
10
 import com.xxl.job.admin.dao.XxlJobGroupDao;
9
 import com.xxl.job.admin.dao.XxlJobGroupDao;
11
 import com.xxl.job.admin.dao.XxlJobInfoDao;
10
 import com.xxl.job.admin.dao.XxlJobInfoDao;
12
 import com.xxl.job.admin.dao.XxlJobLogDao;
11
 import com.xxl.job.admin.dao.XxlJobLogDao;
324
 	private static final String TRIGGER_CHART_DATA_CACHE = "trigger_chart_data_cache";
323
 	private static final String TRIGGER_CHART_DATA_CACHE = "trigger_chart_data_cache";
325
 	@Override
324
 	@Override
326
 	public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
325
 	public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
327
-		// get cache
326
+		/*// get cache
328
 		String cacheKey = TRIGGER_CHART_DATA_CACHE + "_" + startDate.getTime() + "_" + endDate.getTime();
327
 		String cacheKey = TRIGGER_CHART_DATA_CACHE + "_" + startDate.getTime() + "_" + endDate.getTime();
329
 		Map<String, Object> chartInfo = (Map<String, Object>) LocalCacheUtil.get(cacheKey);
328
 		Map<String, Object> chartInfo = (Map<String, Object>) LocalCacheUtil.get(cacheKey);
330
 		if (chartInfo != null) {
329
 		if (chartInfo != null) {
331
 			return new ReturnT<Map<String, Object>>(chartInfo);
330
 			return new ReturnT<Map<String, Object>>(chartInfo);
332
-		}
331
+		}*/
333
 
332
 
334
 		// process
333
 		// process
335
 		List<String> triggerDayList = new ArrayList<String>();
334
 		List<String> triggerDayList = new ArrayList<String>();
376
 		result.put("triggerCountSucTotal", triggerCountSucTotal);
375
 		result.put("triggerCountSucTotal", triggerCountSucTotal);
377
 		result.put("triggerCountFailTotal", triggerCountFailTotal);
376
 		result.put("triggerCountFailTotal", triggerCountFailTotal);
378
 
377
 
379
-		// set cache
380
-		LocalCacheUtil.set(cacheKey, result, 60*1000);     // cache 60s
378
+		/*// set cache
379
+		LocalCacheUtil.set(cacheKey, result, 60*1000);     // cache 60s*/
381
 
380
 
382
 		return new ReturnT<Map<String, Object>>(result);
381
 		return new ReturnT<Map<String, Object>>(result);
383
 	}
382
 	}

+ 3 - 0
xxl-job-admin/src/main/resources/i18n/message.properties View File

193
 jobgroup_del_limit_1=拒绝删除, 系统至少保留一个执行器
193
 jobgroup_del_limit_1=拒绝删除, 系统至少保留一个执行器
194
 
194
 
195
 ## job conf
195
 ## job conf
196
+jobconf_block_SERIAL_EXECUTION=单机串行
197
+jobconf_block_DISCARD_LATER=丢弃后续调度
198
+jobconf_block_COVER_EARLY=覆盖之前调度
196
 jobconf_fail_alarm=失败告警
199
 jobconf_fail_alarm=失败告警
197
 jobconf_fail_retry=失败重试
200
 jobconf_fail_retry=失败重试
198
 jobconf_route_first=第一个
201
 jobconf_route_first=第一个

+ 3 - 0
xxl-job-admin/src/main/resources/i18n/message_en.properties View File

193
 jobgroup_del_limit_1=Refuses to delete, the system retains at least one executor
193
 jobgroup_del_limit_1=Refuses to delete, the system retains at least one executor
194
 
194
 
195
 ## job conf
195
 ## job conf
196
+jobconf_block_SERIAL_EXECUTION=Serial execution
197
+jobconf_block_DISCARD_LATER=Discard Later
198
+jobconf_block_COVER_EARLY=Cover Early
196
 jobconf_fail_alarm=Fail Alarm
199
 jobconf_fail_alarm=Fail Alarm
197
 jobconf_fail_retry=Fail Retry
200
 jobconf_fail_retry=Fail Retry
198
 jobconf_route_first=First
201
 jobconf_route_first=First

+ 17 - 11
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml View File

45
 		SELECT <include refid="Base_Column_List" />
45
 		SELECT <include refid="Base_Column_List" />
46
 		FROM XXL_JOB_QRTZ_TRIGGER_LOG AS t
46
 		FROM XXL_JOB_QRTZ_TRIGGER_LOG AS t
47
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
47
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
48
-			<if test="jobGroup != null and jobGroup != ''">
48
+			<if test="jobGroup gt 0">
49
 				AND t.job_group = #{jobGroup}
49
 				AND t.job_group = #{jobGroup}
50
 			</if>
50
 			</if>
51
 			<if test="jobId gt 0">
51
 			<if test="jobId gt 0">
62
 			</if>
62
 			</if>
63
 			<if test="logStatus == 2" >
63
 			<if test="logStatus == 2" >
64
 				AND (
64
 				AND (
65
-					(t.trigger_code <![CDATA[ > ]]> 0 AND t.trigger_code!=200) ||
66
-					(t.handle_code <![CDATA[ > ]]> 0 AND t.handle_code!=200)
65
+					t.trigger_code NOT IN (0, 200) OR
66
+					t.handle_code NOT IN (0, 200)
67
 				)
67
 				)
68
 			</if>
68
 			</if>
69
 			<if test="logStatus == 3" >
69
 			<if test="logStatus == 3" >
70
-				AND (t.trigger_code = 200 AND t.handle_code=0)
70
+				AND t.trigger_code = 200
71
+				AND t.handle_code = 0
71
 			</if>
72
 			</if>
72
 		</trim>
73
 		</trim>
73
 		ORDER BY id DESC
74
 		ORDER BY id DESC
78
 		SELECT count(1)
79
 		SELECT count(1)
79
 		FROM XXL_JOB_QRTZ_TRIGGER_LOG AS t
80
 		FROM XXL_JOB_QRTZ_TRIGGER_LOG AS t
80
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
81
 		<trim prefix="WHERE" prefixOverrides="AND | OR" >
81
-			<if test="jobGroup != null and jobGroup != ''">
82
+			<if test="jobGroup gt 0">
82
 				AND t.job_group = #{jobGroup}
83
 				AND t.job_group = #{jobGroup}
83
 			</if>
84
 			</if>
84
 			<if test="jobId gt 0">
85
 			<if test="jobId gt 0">
95
 			</if>
96
 			</if>
96
 			<if test="logStatus == 2" >
97
 			<if test="logStatus == 2" >
97
 				AND (
98
 				AND (
98
-				(t.trigger_code <![CDATA[ > ]]> 0 AND t.trigger_code!=200) ||
99
-				(t.handle_code <![CDATA[ > ]]> 0 AND t.handle_code!=200)
99
+					t.trigger_code NOT IN (0, 200) OR
100
+					t.handle_code NOT IN (0, 200)
100
 				)
101
 				)
101
 			</if>
102
 			</if>
102
 			<if test="logStatus == 3" >
103
 			<if test="logStatus == 3" >
103
-				AND (t.trigger_code = 200 AND t.handle_code=0)
104
+				AND t.trigger_code = 200
105
+				AND t.handle_code = 0
104
 			</if>
106
 			</if>
105
 		</trim>
107
 		</trim>
106
 	</select>
108
 	</select>
115
 	<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobLog" useGeneratedKeys="true" keyProperty="id" >
117
 	<insert id="save" parameterType="com.xxl.job.admin.core.model.XxlJobLog" useGeneratedKeys="true" keyProperty="id" >
116
 		INSERT INTO XXL_JOB_QRTZ_TRIGGER_LOG (
118
 		INSERT INTO XXL_JOB_QRTZ_TRIGGER_LOG (
117
 			`job_group`,
119
 			`job_group`,
118
-			`job_id`
120
+			`job_id`,
121
+			`trigger_code`,
122
+			`handle_code`
119
 		) VALUES (
123
 		) VALUES (
120
 			#{jobGroup},
124
 			#{jobGroup},
121
-			#{jobId}
125
+			#{jobId},
126
+			#{triggerCode},
127
+			#{handleCode}
122
 		);
128
 		);
123
 		<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
129
 		<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
124
 			SELECT LAST_INSERT_ID() 
130
 			SELECT LAST_INSERT_ID() 
166
 		SELECT
172
 		SELECT
167
 			DATE_FORMAT(trigger_time,'%Y-%m-%d') triggerDay,
173
 			DATE_FORMAT(trigger_time,'%Y-%m-%d') triggerDay,
168
 			COUNT(handle_code) triggerDayCount,
174
 			COUNT(handle_code) triggerDayCount,
169
-			SUM(CASE WHEN handle_code = 0 then 1 else 0 end) as triggerDayCountRunning,
175
+			SUM(CASE WHEN (trigger_code = 200 and handle_code = 0) then 1 else 0 end) as triggerDayCountRunning,
170
 			SUM(CASE WHEN handle_code = 200 then 1 else 0 end) as triggerDayCountSuc
176
 			SUM(CASE WHEN handle_code = 200 then 1 else 0 end) as triggerDayCountSuc
171
 		FROM XXL_JOB_QRTZ_TRIGGER_LOG
177
 		FROM XXL_JOB_QRTZ_TRIGGER_LOG
172
 		WHERE trigger_time BETWEEN #{from} and #{to}
178
 		WHERE trigger_time BETWEEN #{from} and #{to}

+ 1 - 0
xxl-job-admin/src/main/resources/xxl-job-admin.properties View File

7
 ### xxl-job email
7
 ### xxl-job email
8
 xxl.job.mail.host=smtp.163.com
8
 xxl.job.mail.host=smtp.163.com
9
 xxl.job.mail.port=25
9
 xxl.job.mail.port=25
10
+xxl.job.mail.ssl=false
10
 xxl.job.mail.username=ovono802302@163.com
11
 xxl.job.mail.username=ovono802302@163.com
11
 xxl.job.mail.password=asdfzxcv
12
 xxl.job.mail.password=asdfzxcv
12
 xxl.job.mail.sendNick=《任务调度平台XXL-JOB》
13
 xxl.job.mail.sendNick=《任务调度平台XXL-JOB》

+ 2 - 2
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl View File

135
 								</#list>
135
 								</#list>
136
                             </select>
136
                             </select>
137
                         </div>
137
                         </div>
138
-                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="black">*</font></label>
138
+                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
139
                         <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
139
                         <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
140
                     </div>
140
                     </div>
141
                     <div class="form-group">
141
                     <div class="form-group">
308
 							</#list>
308
 							</#list>
309
                             </select>
309
                             </select>
310
                         </div>
310
                         </div>
311
-                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="black">*</font></label>
311
+                        <label for="firstname" class="col-sm-2 control-label">JobHandler<font color="red">*</font></label>
312
                         <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
312
                         <div class="col-sm-4"><input type="text" class="form-control" name="executorHandler" placeholder="${I18n.system_please_input}JobHandler" maxlength="100" ></div>
313
                     </div>
313
                     </div>
314
                     <div class="form-group">
314
                     <div class="form-group">

+ 1 - 1
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js View File

229
 							end: function(layero, index){
229
 							end: function(layero, index){
230
 								if (needFresh) {
230
 								if (needFresh) {
231
 									//window.location.reload();
231
 									//window.location.reload();
232
-									jobTable.fnDraw();
232
+									jobTable.fnDraw(false);
233
 								}
233
 								}
234
 							}
234
 							}
235
 						});
235
 						});

+ 1 - 1
xxl-job-admin/src/test/java/com/xxl/job/admin/util/MailUtilTest.java View File

18
 public class MailUtilTest {
18
 public class MailUtilTest {
19
 
19
 
20
     @Test
20
     @Test
21
-    public void registryTest() throws Exception {
21
+    public void mailTest() throws Exception {
22
 
22
 
23
         String mailBodyTemplate = "<h5>监控告警明细:</span>" +
23
         String mailBodyTemplate = "<h5>监控告警明细:</span>" +
24
                 "<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n" +
24
                 "<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n" +

+ 8 - 0
xxl-job-core/src/main/java/com/xxl/job/core/biz/AdminBiz.java View File

13
 
13
 
14
     public static final String MAPPING = "/api";
14
     public static final String MAPPING = "/api";
15
 
15
 
16
+
17
+    // ---------------------- callback ----------------------
18
+
16
     /**
19
     /**
17
      * callback
20
      * callback
18
      *
21
      *
21
      */
24
      */
22
     public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList);
25
     public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList);
23
 
26
 
27
+
28
+    // ---------------------- registry ----------------------
29
+
24
     /**
30
     /**
25
      * registry
31
      * registry
26
      *
32
      *
38
     public ReturnT<String> registryRemove(RegistryParam registryParam);
44
     public ReturnT<String> registryRemove(RegistryParam registryParam);
39
 
45
 
40
 
46
 
47
+    // ---------------------- job opt ----------------------
48
+
41
     /**
49
     /**
42
      * trigger job for once
50
      * trigger job for once
43
      *
51
      *

+ 14 - 1
xxl-job-core/src/main/java/com/xxl/job/core/biz/model/HandleCallbackParam.java View File

9
     private static final long serialVersionUID = 42L;
9
     private static final long serialVersionUID = 42L;
10
 
10
 
11
     private int logId;
11
     private int logId;
12
+    private long logDateTim;
13
+
12
     private ReturnT<String> executeResult;
14
     private ReturnT<String> executeResult;
13
 
15
 
14
     public HandleCallbackParam(){}
16
     public HandleCallbackParam(){}
15
-    public HandleCallbackParam(int logId, ReturnT<String> executeResult) {
17
+    public HandleCallbackParam(int logId, long logDateTim, ReturnT<String> executeResult) {
16
         this.logId = logId;
18
         this.logId = logId;
19
+        this.logDateTim = logDateTim;
17
         this.executeResult = executeResult;
20
         this.executeResult = executeResult;
18
     }
21
     }
19
 
22
 
25
         this.logId = logId;
28
         this.logId = logId;
26
     }
29
     }
27
 
30
 
31
+    public long getLogDateTim() {
32
+        return logDateTim;
33
+    }
34
+
35
+    public void setLogDateTim(long logDateTim) {
36
+        this.logDateTim = logDateTim;
37
+    }
38
+
28
     public ReturnT<String> getExecuteResult() {
39
     public ReturnT<String> getExecuteResult() {
29
         return executeResult;
40
         return executeResult;
30
     }
41
     }
37
     public String toString() {
48
     public String toString() {
38
         return "HandleCallbackParam{" +
49
         return "HandleCallbackParam{" +
39
                 "logId=" + logId +
50
                 "logId=" + logId +
51
+                ", logDateTim=" + logDateTim +
40
                 ", executeResult=" + executeResult +
52
                 ", executeResult=" + executeResult +
41
                 '}';
53
                 '}';
42
     }
54
     }
55
+
43
 }
56
 }

+ 8 - 4
xxl-job-core/src/main/java/com/xxl/job/core/enums/ExecutorBlockStrategyEnum.java View File

5
  */
5
  */
6
 public enum ExecutorBlockStrategyEnum {
6
 public enum ExecutorBlockStrategyEnum {
7
 
7
 
8
-    SERIAL_EXECUTION("单机串行"),
8
+    SERIAL_EXECUTION("Serial execution"),
9
     /*CONCURRENT_EXECUTION("并行"),*/
9
     /*CONCURRENT_EXECUTION("并行"),*/
10
-    DISCARD_LATER("丢弃后续调度"),
11
-    COVER_EARLY("覆盖之前调度");
10
+    DISCARD_LATER("Discard Later"),
11
+    COVER_EARLY("Cover Early");
12
 
12
 
13
-    private final String title;
13
+    private String title;
14
     private ExecutorBlockStrategyEnum (String title) {
14
     private ExecutorBlockStrategyEnum (String title) {
15
         this.title = title;
15
         this.title = title;
16
     }
16
     }
17
+
18
+    public void setTitle(String title) {
19
+        this.title = title;
20
+    }
17
     public String getTitle() {
21
     public String getTitle() {
18
         return title;
22
         return title;
19
     }
23
     }

+ 5 - 5
xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java View File

5
  */
5
  */
6
 public enum GlueTypeEnum {
6
 public enum GlueTypeEnum {
7
 
7
 
8
-    BEAN("BEAN模式", false, null, null),
9
-    GLUE_GROOVY("GLUE模式(Java)", false, null, null),
10
-    GLUE_SHELL("GLUE模式(Shell)", true, "bash", ".sh"),
11
-    GLUE_PYTHON("GLUE模式(Python)", true, "python", ".py"),
12
-    GLUE_NODEJS("GLUE模式(Nodejs)", true, "node", ".js");
8
+    BEAN("BEAN", false, null, null),
9
+    GLUE_GROOVY("GLUE(Java)", false, null, null),
10
+    GLUE_SHELL("GLUE(Shell)", true, "bash", ".sh"),
11
+    GLUE_PYTHON("GLUE(Python)", true, "python", ".py"),
12
+    GLUE_NODEJS("GLUE(Nodejs)", true, "node", ".js");
13
 
13
 
14
     private String desc;
14
     private String desc;
15
     private boolean isScript;
15
     private boolean isScript;

+ 12 - 3
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java View File

8
 import com.xxl.job.core.util.ScriptUtil;
8
 import com.xxl.job.core.util.ScriptUtil;
9
 import com.xxl.job.core.util.ShardingUtil;
9
 import com.xxl.job.core.util.ShardingUtil;
10
 
10
 
11
+import java.io.File;
12
+
11
 /**
13
 /**
12
  * Created by xuxueli on 17/4/27.
14
  * Created by xuxueli on 17/4/27.
13
  */
15
  */
41
 
43
 
42
         // make script file
44
         // make script file
43
         String scriptFileName = XxlJobFileAppender.getGlueSrcPath()
45
         String scriptFileName = XxlJobFileAppender.getGlueSrcPath()
44
-                .concat("/")
46
+                .concat(File.separator)
45
                 .concat(String.valueOf(jobId))
47
                 .concat(String.valueOf(jobId))
46
                 .concat("_")
48
                 .concat("_")
47
                 .concat(String.valueOf(glueUpdatetime))
49
                 .concat(String.valueOf(glueUpdatetime))
61
         // invoke
63
         // invoke
62
         XxlJobLogger.log("----------- script file:"+ scriptFileName +" -----------");
64
         XxlJobLogger.log("----------- script file:"+ scriptFileName +" -----------");
63
         int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, scriptParams);
65
         int exitValue = ScriptUtil.execToFile(cmd, scriptFileName, logFileName, scriptParams);
64
-        ReturnT<String> result = (exitValue==0)?IJobHandler.SUCCESS:new ReturnT<String>(IJobHandler.FAIL.getCode(), "script exit value("+exitValue+") is failed");
65
-        return result;
66
+
67
+        if (exitValue == 0) {
68
+            return IJobHandler.SUCCESS;
69
+        } else if (exitValue == 101) {
70
+            return IJobHandler.FAIL_RETRY;
71
+        } else {
72
+            return new ReturnT<String>(IJobHandler.FAIL.getCode(), "script exit value("+exitValue+") is failed");
73
+        }
74
+
66
     }
75
     }
67
 
76
 
68
 }
77
 }

+ 13 - 15
xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java View File

79
 
79
 
80
 		// filePath/yyyy-MM-dd/9999.log
80
 		// filePath/yyyy-MM-dd/9999.log
81
 		String logFileName = logFilePath.getPath()
81
 		String logFileName = logFilePath.getPath()
82
-				.concat("/")
82
+				.concat(File.separator)
83
 				.concat(String.valueOf(logId))
83
 				.concat(String.valueOf(logId))
84
 				.concat(".log");
84
 				.concat(".log");
85
 		return logFileName;
85
 		return logFileName;
115
 		appendLog += "\r\n";
115
 		appendLog += "\r\n";
116
 		
116
 		
117
 		// append file content
117
 		// append file content
118
+		FileOutputStream fos = null;
118
 		try {
119
 		try {
119
-			FileOutputStream fos = null;
120
-			try {
121
-				fos = new FileOutputStream(logFile, true);
122
-				fos.write(appendLog.getBytes("utf-8"));
123
-				fos.flush();
124
-			} finally {
125
-				if (fos != null) {
126
-					try {
127
-						fos.close();
128
-					} catch (IOException e) {
129
-						logger.error(e.getMessage(), e);
130
-					}
131
-				}
132
-			} 
120
+			fos = new FileOutputStream(logFile, true);
121
+			fos.write(appendLog.getBytes("utf-8"));
122
+			fos.flush();
133
 		} catch (Exception e) {
123
 		} catch (Exception e) {
134
 			logger.error(e.getMessage(), e);
124
 			logger.error(e.getMessage(), e);
125
+		} finally {
126
+			if (fos != null) {
127
+				try {
128
+					fos.close();
129
+				} catch (IOException e) {
130
+					logger.error(e.getMessage(), e);
131
+				}
132
+			}
135
 		}
133
 		}
136
 		
134
 		
137
 	}
135
 	}

+ 8 - 4
xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobLogger.java View File

2
 
2
 
3
 import org.slf4j.Logger;
3
 import org.slf4j.Logger;
4
 import org.slf4j.LoggerFactory;
4
 import org.slf4j.LoggerFactory;
5
+import org.slf4j.helpers.FormattingTuple;
6
+import org.slf4j.helpers.MessageFormatter;
5
 
7
 
6
 import java.io.PrintWriter;
8
 import java.io.PrintWriter;
7
 import java.io.StringWriter;
9
 import java.io.StringWriter;
8
-import java.text.MessageFormat;
9
 import java.text.SimpleDateFormat;
10
 import java.text.SimpleDateFormat;
10
 import java.util.Date;
11
 import java.util.Date;
11
 
12
 
49
     /**
50
     /**
50
      * append log with pattern
51
      * append log with pattern
51
      *
52
      *
52
-     * @param appendLogPattern  like "aaa {0} bbb {1} ccc"
53
+     * @param appendLogPattern  like "aaa {} bbb {} ccc"
53
      * @param appendLogArguments    like "111, true"
54
      * @param appendLogArguments    like "111, true"
54
      */
55
      */
55
     public static void log(String appendLogPattern, Object ... appendLogArguments) {
56
     public static void log(String appendLogPattern, Object ... appendLogArguments) {
56
 
57
 
57
-        String appendLog = appendLogPattern;
58
+    	FormattingTuple ft = MessageFormatter.format(appendLogPattern, appendLogArguments);
59
+        String appendLog = ft.getMessage();
60
+
61
+        /*appendLog = appendLogPattern;
58
         if (appendLogArguments!=null && appendLogArguments.length>0) {
62
         if (appendLogArguments!=null && appendLogArguments.length>0) {
59
             appendLog = MessageFormat.format(appendLogPattern, appendLogArguments);
63
             appendLog = MessageFormat.format(appendLogPattern, appendLogArguments);
60
-        }
64
+        }*/
61
 
65
 
62
         StackTraceElement callInfo = new Throwable().getStackTrace()[1];
66
         StackTraceElement callInfo = new Throwable().getStackTrace()[1];
63
         logDetail(callInfo, appendLog);
67
         logDetail(callInfo, appendLog);

+ 1 - 2
xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/NetComClientProxy.java View File

58
 	                    
58
 	                    
59
 	                    // valid response
59
 	                    // valid response
60
 						if (response == null) {
60
 						if (response == null) {
61
-							logger.error(">>>>>>>>>>> xxl-rpc netty response not found.");
62
-							throw new Exception(">>>>>>>>>>> xxl-rpc netty response not found.");
61
+							throw new Exception("Network request fail, response not found.");
63
 						}
62
 						}
64
 	                    if (response.isError()) {
63
 	                    if (response.isError()) {
65
 	                        throw new RuntimeException(response.getError());
64
 	                        throw new RuntimeException(response.getError());

+ 2 - 2
xxl-job-core/src/main/java/com/xxl/job/core/rpc/netcom/jetty/client/JettyClient.java View File

29
 			byte[] responseBytes = HttpClientUtil.postRequest(reqURL, requestBytes);
29
 			byte[] responseBytes = HttpClientUtil.postRequest(reqURL, requestBytes);
30
 			if (responseBytes == null || responseBytes.length==0) {
30
 			if (responseBytes == null || responseBytes.length==0) {
31
 				RpcResponse rpcResponse = new RpcResponse();
31
 				RpcResponse rpcResponse = new RpcResponse();
32
-				rpcResponse.setError("RpcResponse byte[] is null");
32
+				rpcResponse.setError("Network request fail, RpcResponse byte[] is null");
33
 				return rpcResponse;
33
 				return rpcResponse;
34
             }
34
             }
35
 
35
 
40
 			logger.error(e.getMessage(), e);
40
 			logger.error(e.getMessage(), e);
41
 
41
 
42
 			RpcResponse rpcResponse = new RpcResponse();
42
 			RpcResponse rpcResponse = new RpcResponse();
43
-			rpcResponse.setError("Client-error:" + e.getMessage());
43
+			rpcResponse.setError("Network request error: " + e.getMessage());
44
 			return rpcResponse;
44
 			return rpcResponse;
45
 		}
45
 		}
46
 	}
46
 	}

+ 14 - 8
xxl-job-core/src/main/java/com/xxl/job/core/thread/JobThread.java View File

8
 import com.xxl.job.core.log.XxlJobFileAppender;
8
 import com.xxl.job.core.log.XxlJobFileAppender;
9
 import com.xxl.job.core.log.XxlJobLogger;
9
 import com.xxl.job.core.log.XxlJobLogger;
10
 import com.xxl.job.core.util.ShardingUtil;
10
 import com.xxl.job.core.util.ShardingUtil;
11
-import org.eclipse.jetty.util.ConcurrentHashSet;
12
 import org.slf4j.Logger;
11
 import org.slf4j.Logger;
13
 import org.slf4j.LoggerFactory;
12
 import org.slf4j.LoggerFactory;
14
 
13
 
15
 import java.io.PrintWriter;
14
 import java.io.PrintWriter;
16
 import java.io.StringWriter;
15
 import java.io.StringWriter;
17
-import java.util.Arrays;
16
+import java.util.Collections;
18
 import java.util.Date;
17
 import java.util.Date;
18
+
19
 import java.util.concurrent.*;
19
 import java.util.concurrent.*;
20
 
20
 
21
+import java.util.HashSet;
22
+import java.util.Set;
23
+import java.util.concurrent.LinkedBlockingQueue;
24
+import java.util.concurrent.TimeUnit;
25
+
26
+
21
 /**
27
 /**
22
  * handler thread
28
  * handler thread
23
  * @author xuxueli 2016-1-16 19:52:47
29
  * @author xuxueli 2016-1-16 19:52:47
28
 	private int jobId;
34
 	private int jobId;
29
 	private IJobHandler handler;
35
 	private IJobHandler handler;
30
 	private LinkedBlockingQueue<TriggerParam> triggerQueue;
36
 	private LinkedBlockingQueue<TriggerParam> triggerQueue;
31
-	private ConcurrentHashSet<Integer> triggerLogIdSet;		// avoid repeat trigger for the same TRIGGER_LOG_ID
37
+	private Set<Integer> triggerLogIdSet;		// avoid repeat trigger for the same TRIGGER_LOG_ID
32
 
38
 
33
-	private boolean toStop = false;
39
+	private volatile boolean toStop = false;
34
 	private String stopReason;
40
 	private String stopReason;
35
 
41
 
36
     private boolean running = false;    // if running job
42
     private boolean running = false;    // if running job
41
 		this.jobId = jobId;
47
 		this.jobId = jobId;
42
 		this.handler = handler;
48
 		this.handler = handler;
43
 		this.triggerQueue = new LinkedBlockingQueue<TriggerParam>();
49
 		this.triggerQueue = new LinkedBlockingQueue<TriggerParam>();
44
-		this.triggerLogIdSet = new ConcurrentHashSet<Integer>();
50
+		this.triggerLogIdSet = Collections.synchronizedSet(new HashSet<Integer>());
45
 	}
51
 	}
46
 	public IJobHandler getHandler() {
52
 	public IJobHandler getHandler() {
47
 		return handler;
53
 		return handler;
171
                     // callback handler info
177
                     // callback handler info
172
                     if (!toStop) {
178
                     if (!toStop) {
173
                         // commonm
179
                         // commonm
174
-                        TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), executeResult));
180
+                        TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), triggerParam.getLogDateTim(), executeResult));
175
                     } else {
181
                     } else {
176
                         // is killed
182
                         // is killed
177
                         ReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + " [业务运行中,被强制终止]");
183
                         ReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + " [业务运行中,被强制终止]");
178
-                        TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult));
184
+                        TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), triggerParam.getLogDateTim(), stopResult));
179
                     }
185
                     }
180
                 }
186
                 }
181
             }
187
             }
187
 			if (triggerParam!=null) {
193
 			if (triggerParam!=null) {
188
 				// is killed
194
 				// is killed
189
 				ReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + " [任务尚未执行,在调度队列中被终止]");
195
 				ReturnT<String> stopResult = new ReturnT<String>(ReturnT.FAIL_CODE, stopReason + " [任务尚未执行,在调度队列中被终止]");
190
-				TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), stopResult));
196
+				TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), triggerParam.getLogDateTim(), stopResult));
191
 			}
197
 			}
192
 		}
198
 		}
193
 
199
 

+ 17 - 4
xxl-job-core/src/main/java/com/xxl/job/core/thread/TriggerCallbackThread.java View File

4
 import com.xxl.job.core.biz.model.HandleCallbackParam;
4
 import com.xxl.job.core.biz.model.HandleCallbackParam;
5
 import com.xxl.job.core.biz.model.ReturnT;
5
 import com.xxl.job.core.biz.model.ReturnT;
6
 import com.xxl.job.core.executor.XxlJobExecutor;
6
 import com.xxl.job.core.executor.XxlJobExecutor;
7
+import com.xxl.job.core.log.XxlJobFileAppender;
8
+import com.xxl.job.core.log.XxlJobLogger;
7
 import org.slf4j.Logger;
9
 import org.slf4j.Logger;
8
 import org.slf4j.LoggerFactory;
10
 import org.slf4j.LoggerFactory;
9
 
11
 
10
 import java.util.ArrayList;
12
 import java.util.ArrayList;
13
+import java.util.Date;
11
 import java.util.List;
14
 import java.util.List;
12
 import java.util.concurrent.LinkedBlockingQueue;
15
 import java.util.concurrent.LinkedBlockingQueue;
13
 
16
 
108
             try {
111
             try {
109
                 ReturnT<String> callbackResult = adminBiz.callback(callbackParamList);
112
                 ReturnT<String> callbackResult = adminBiz.callback(callbackParamList);
110
                 if (callbackResult!=null && ReturnT.SUCCESS_CODE == callbackResult.getCode()) {
113
                 if (callbackResult!=null && ReturnT.SUCCESS_CODE == callbackResult.getCode()) {
111
-                    callbackResult = ReturnT.SUCCESS;
112
-                    logger.info(">>>>>>>>>>> xxl-job callback success, callbackParamList:{}, callbackResult:{}", new Object[]{callbackParamList, callbackResult});
114
+                    callbackLog(callbackParamList, "<br>----------- xxl-job callback success");
113
                     break;
115
                     break;
114
                 } else {
116
                 } else {
115
-                    logger.info(">>>>>>>>>>> xxl-job callback fail, callbackParamList:{}, callbackResult:{}", new Object[]{callbackParamList, callbackResult});
117
+                    callbackLog(callbackParamList, "<br>----------- xxl-job callback fail, callbackResult:" + callbackResult);
116
                 }
118
                 }
117
             } catch (Exception e) {
119
             } catch (Exception e) {
118
-                logger.error(">>>>>>>>>>> xxl-job callback error, callbackParamList:{}", callbackParamList, e);
120
+                callbackLog(callbackParamList, "<br>----------- xxl-job callback error, errorMsg:" + e.getMessage());
119
                 //getInstance().callBackQueue.addAll(callbackParamList);
121
                 //getInstance().callBackQueue.addAll(callbackParamList);
120
             }
122
             }
121
         }
123
         }
122
     }
124
     }
123
 
125
 
126
+    /**
127
+     * callback log
128
+     */
129
+    private void callbackLog(List<HandleCallbackParam> callbackParamList, String logContent){
130
+        for (HandleCallbackParam callbackParam: callbackParamList) {
131
+            String logFileName = XxlJobFileAppender.makeLogFileName(new Date(callbackParam.getLogDateTim()), callbackParam.getLogId());
132
+            XxlJobFileAppender.contextHolder.set(logFileName);
133
+            XxlJobLogger.log(logContent);
134
+        }
135
+    }
136
+
124
 }
137
 }

+ 3 - 4
xxl-job-core/src/main/java/com/xxl/job/core/util/HttpClientUtil.java View File

26
 	/**
26
 	/**
27
 	 * post request
27
 	 * post request
28
 	 */
28
 	 */
29
-	public static byte[] postRequest(String reqURL, byte[] date) throws Exception {
29
+	public static byte[] postRequest(String reqURL, byte[] data) throws Exception {
30
 		byte[] responseBytes = null;
30
 		byte[] responseBytes = null;
31
 		
31
 		
32
 		HttpPost httpPost = new HttpPost(reqURL);
32
 		HttpPost httpPost = new HttpPost(reqURL);
53
 			httpPost.setConfig(requestConfig);
53
 			httpPost.setConfig(requestConfig);
54
 
54
 
55
 			// data
55
 			// data
56
-			if (date != null) {
57
-				httpPost.setEntity(new ByteArrayEntity(date, ContentType.DEFAULT_BINARY));
56
+			if (data != null) {
57
+				httpPost.setEntity(new ByteArrayEntity(data, ContentType.DEFAULT_BINARY));
58
 			}
58
 			}
59
 			// do post
59
 			// do post
60
 			HttpResponse response = httpClient.execute(httpPost);
60
 			HttpResponse response = httpClient.execute(httpPost);
64
 				EntityUtils.consume(entity);
64
 				EntityUtils.consume(entity);
65
 			}
65
 			}
66
 		} catch (Exception e) {
66
 		} catch (Exception e) {
67
-			logger.error(e.getMessage(), e);
68
 			throw e;
67
 			throw e;
69
 		} finally {
68
 		} finally {
70
 			httpPost.releaseConnection();
69
 			httpPost.releaseConnection();

+ 17 - 1
xxl-job-core/src/main/java/com/xxl/job/core/util/ScriptUtil.java View File

1
 package com.xxl.job.core.util;
1
 package com.xxl.job.core.util;
2
 
2
 
3
+import com.xxl.job.core.log.XxlJobLogger;
3
 import org.apache.commons.exec.CommandLine;
4
 import org.apache.commons.exec.CommandLine;
4
 import org.apache.commons.exec.DefaultExecutor;
5
 import org.apache.commons.exec.DefaultExecutor;
5
 import org.apache.commons.exec.PumpStreamHandler;
6
 import org.apache.commons.exec.PumpStreamHandler;
59
         // 标准输出:print (null if watchdog timeout)
60
         // 标准输出:print (null if watchdog timeout)
60
         // 错误输出:logging + 异常 (still exists if watchdog timeout)
61
         // 错误输出:logging + 异常 (still exists if watchdog timeout)
61
         // 标准输入
62
         // 标准输入
62
-        try (FileOutputStream fileOutputStream = new FileOutputStream(logFile, true)) {
63
+
64
+        FileOutputStream fileOutputStream = null;   //
65
+        try {
66
+            fileOutputStream = new FileOutputStream(logFile, true);
63
             PumpStreamHandler streamHandler = new PumpStreamHandler(fileOutputStream, fileOutputStream, null);
67
             PumpStreamHandler streamHandler = new PumpStreamHandler(fileOutputStream, fileOutputStream, null);
64
 
68
 
65
             // command
69
             // command
75
             exec.setStreamHandler(streamHandler);
79
             exec.setStreamHandler(streamHandler);
76
             int exitValue = exec.execute(commandline);  // exit code: 0=success, 1=error
80
             int exitValue = exec.execute(commandline);  // exit code: 0=success, 1=error
77
             return exitValue;
81
             return exitValue;
82
+        } catch (Exception e) {
83
+            XxlJobLogger.log(e);
84
+            return -1;
85
+        } finally {
86
+            if (fileOutputStream != null) {
87
+                try {
88
+                    fileOutputStream.close();
89
+                } catch (IOException e) {
90
+                    XxlJobLogger.log(e);
91
+                }
92
+
93
+            }
78
         }
94
         }
79
     }
95
     }
80
 
96
 

+ 1 - 0
xxl-job-executor-samples/xxl-job-executor-sample-springboot/pom.xml View File

84
             <plugin>
84
             <plugin>
85
                 <groupId>org.springframework.boot</groupId>
85
                 <groupId>org.springframework.boot</groupId>
86
                 <artifactId>spring-boot-maven-plugin</artifactId>
86
                 <artifactId>spring-boot-maven-plugin</artifactId>
87
+                <version>${spring-boot.version}</version>
87
                 <executions>
88
                 <executions>
88
                     <execution>
89
                     <execution>
89
                         <goals>
90
                         <goals>