Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
X
XXL-JOB
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
靳帅
XXL-JOB
Commits
8ed4d055
Unverified
提交
8ed4d055
authored
12月 26, 2017
作者:
thinking_fioa
提交者:
GitHub
12月 26, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1 from xuxueli/master
pull xuxueli/xxl-job
上级
d9af1883
4ce20c10
全部展开
显示空白字符变更
内嵌
并排
正在显示
83 个修改的文件
包含
1134 行增加
和
620 行删除
+1134
-620
README.md
README.md
+28
-23
XXL-JOB官方文档.md
doc/XXL-JOB官方文档.md
+0
-0
tables_xxl_job.sql
doc/db/tables_xxl_job.sql
+6
-4
pom.xml
pom.xml
+15
-15
pom.xml
xxl-job-admin/pom.xml
+33
-37
IndexController.java
...in/java/com/xxl/job/admin/controller/IndexController.java
+14
-12
JobGroupController.java
...java/com/xxl/job/admin/controller/JobGroupController.java
+1
-1
JobLogController.java
...n/java/com/xxl/job/admin/controller/JobLogController.java
+2
-2
CookieInterceptor.java
...l/job/admin/controller/interceptor/CookieInterceptor.java
+5
-5
PermissionInterceptor.java
...b/admin/controller/interceptor/PermissionInterceptor.java
+25
-4
XxlJobGroup.java
...c/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java
+1
-1
XxlJobInfo.java
...rc/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java
+5
-5
JobFailMonitorHelper.java
...a/com/xxl/job/admin/core/thread/JobFailMonitorHelper.java
+54
-23
JobRegistryMonitorHelper.java
...m/xxl/job/admin/core/thread/JobRegistryMonitorHelper.java
+2
-2
XxlJobTrigger.java
...in/java/com/xxl/job/admin/core/trigger/XxlJobTrigger.java
+15
-12
CookieUtil.java
...src/main/java/com/xxl/job/admin/core/util/CookieUtil.java
+17
-18
MailUtil.java
...n/src/main/java/com/xxl/job/admin/core/util/MailUtil.java
+28
-143
PropertiesUtil.java
...main/java/com/xxl/job/admin/core/util/PropertiesUtil.java
+1
-4
AdminBizImpl.java
...ain/java/com/xxl/job/admin/service/impl/AdminBizImpl.java
+30
-22
XxlJobServiceImpl.java
...ava/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java
+31
-25
XxlJobInfoMapper.xml
...in/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml
+5
-5
applicationcontext-base.xml
...min/src/main/resources/spring/applicationcontext-base.xml
+2
-2
applicationcontext-xxl-job-admin.xml
...ain/resources/spring/applicationcontext-xxl-job-admin.xml
+2
-2
springmvc-context.xml
...job-admin/src/main/resources/spring/springmvc-context.xml
+3
-3
jobgroup.index.ftl
.../main/webapp/WEB-INF/template/jobgroup/jobgroup.index.ftl
+20
-3
jobinfo.index.ftl
...rc/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl
+27
-17
joblog.index.ftl
.../src/main/webapp/WEB-INF/template/joblog/joblog.index.ftl
+1
-3
common.1.js
xxl-job-admin/src/main/webapp/static/js/common.1.js
+6
-2
jobgroup.index.1.js
xxl-job-admin/src/main/webapp/static/js/jobgroup.index.1.js
+5
-3
jobinfo.index.1.js
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
+2
-11
joblog.index.1.js
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js
+23
-28
login.1.js
xxl-job-admin/src/main/webapp/static/js/login.1.js
+6
-2
AbstractSpringMvcTest.java
...a/com/xxl/job/admin/controller/AbstractSpringMvcTest.java
+27
-0
JobInfoControllerTest.java
...a/com/xxl/job/admin/controller/JobInfoControllerTest.java
+47
-0
XxlJobGroupDaoTest.java
...c/test/java/com/xxl/job/admin/dao/XxlJobGroupDaoTest.java
+1
-1
XxlJobInfoDaoTest.java
...rc/test/java/com/xxl/job/admin/dao/XxlJobInfoDaoTest.java
+4
-4
XxlJobLogDaoTest.java
...src/test/java/com/xxl/job/admin/dao/XxlJobLogDaoTest.java
+2
-2
XxlJobLogGlueDaoTest.java
...test/java/com/xxl/job/admin/dao/XxlJobLogGlueDaoTest.java
+1
-1
XxlJobRegistryDaoTest.java
...est/java/com/xxl/job/admin/dao/XxlJobRegistryDaoTest.java
+1
-1
MailUtilTest.java
...in/src/test/java/com/xxl/job/admin/util/MailUtilTest.java
+45
-0
PropertiesUtilTest.java
.../test/java/com/xxl/job/admin/util/PropertiesUtilTest.java
+18
-0
AdminBizTest.java
...dmin/src/test/java/com/xxl/job/adminbiz/AdminBizTest.java
+1
-1
pom.xml
xxl-job-core/pom.xml
+3
-3
ExecutorBizImpl.java
.../main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java
+5
-6
XxlJobExecutor.java
...c/main/java/com/xxl/job/core/executor/XxlJobExecutor.java
+5
-5
GlueTypeEnum.java
...ore/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java
+27
-6
IJobHandler.java
...e/src/main/java/com/xxl/job/core/handler/IJobHandler.java
+32
-4
GlueJobHandler.java
...in/java/com/xxl/job/core/handler/impl/GlueJobHandler.java
+2
-2
ScriptJobHandler.java
.../java/com/xxl/job/core/handler/impl/ScriptJobHandler.java
+24
-17
XxlJobFileAppender.java
...rc/main/java/com/xxl/job/core/log/XxlJobFileAppender.java
+43
-23
XxlJobLogger.java
...core/src/main/java/com/xxl/job/core/log/XxlJobLogger.java
+35
-16
JobThread.java
...core/src/main/java/com/xxl/job/core/thread/JobThread.java
+19
-9
JacksonUtil.java
...core/src/main/java/com/xxl/job/core/util/JacksonUtil.java
+5
-6
ScriptUtil.java
...-core/src/main/java/com/xxl/job/core/util/ScriptUtil.java
+0
-14
pom.xml
xxl-job-executor-samples/pom.xml
+2
-0
pom.xml
...b-executor-samples/xxl-job-executor-sample-jfinal/pom.xml
+1
-1
JFinalCoreConfig.java
...xueli/executor/sample/jfinal/config/JFinalCoreConfig.java
+2
-1
IndexController.java
...li/executor/sample/jfinal/controller/IndexController.java
+1
-0
DemoJobHandler.java
...eli/executor/sample/jfinal/jobhandler/DemoJobHandler.java
+6
-7
ShardingJobHandler.java
...executor/sample/jfinal/jobhandler/ShardingJobHandler.java
+2
-2
xxl-job-executor.properties
...ple-jfinal/src/main/resources/xxl-job-executor.properties
+3
-2
web.xml
...ob-executor-sample-jfinal/src/main/webapp/WEB-INF/web.xml
+7
-0
index.html
...xxl-job-executor-sample-jfinal/src/main/webapp/index.html
+2
-0
pom.xml
...job-executor-samples/xxl-job-executor-sample-nutz/pom.xml
+39
-0
MainModule.java
...ain/java/com/xuxueli/executor/sample/nutz/MainModule.java
+23
-0
NutzSetup.java
...va/com/xuxueli/executor/sample/nutz/config/NutzSetup.java
+64
-0
DemoJobHandler.java
...xueli/executor/sample/nutz/jobhandler/DemoJobHandler.java
+38
-0
ShardingJobHandler.java
...i/executor/sample/nutz/jobhandler/ShardingJobHandler.java
+39
-0
IndexModule.java
.../com/xuxueli/executor/sample/nutz/module/IndexModule.java
+16
-0
log4j.xml
...xxl-job-executor-sample-nutz/src/main/resources/log4j.xml
+28
-0
xxl-job-executor.properties
...ample-nutz/src/main/resources/xxl-job-executor.properties
+14
-0
web.xml
...-job-executor-sample-nutz/src/main/webapp/WEB-INF/web.xml
+32
-0
index.html
...s/xxl-job-executor-sample-nutz/src/main/webapp/index.html
+2
-0
DemoJobHandler.java
...m/xxl/job/executor/service/jobhandler/DemoJobHandler.java
+6
-6
ShardingJobHandler.java
...l/job/executor/service/jobhandler/ShardingJobHandler.java
+2
-2
applicationcontext-xxl-job.xml
...-spring/src/main/resources/applicationcontext-xxl-job.xml
+5
-5
xxl-job-executor.properties
...ple-spring/src/main/resources/xxl-job-executor.properties
+2
-1
web.xml
...ob-executor-sample-spring/src/main/webapp/WEB-INF/web.xml
+3
-0
index.html
...xxl-job-executor-sample-spring/src/main/webapp/index.html
+2
-2
IndexController.java
.../com/xxl/job/executor/mvc/controller/IndexController.java
+19
-19
DemoJobHandler.java
...m/xxl/job/executor/service/jobhandler/DemoJobHandler.java
+8
-8
ShardingJobHandler.java
...l/job/executor/service/jobhandler/ShardingJobHandler.java
+2
-2
application.properties
...mple-springboot/src/main/resources/application.properties
+2
-2
没有找到文件。
README.md
浏览文件 @
8ed4d055
...
...
@@ -47,29 +47,30 @@ XXL-JOB是一个轻量级分布式任务调度框架,其核心设计目标是
## Features
-
1、简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手;
-
2、动态:支持动态修改任务状态、暂停/恢复任务,以及终止运行中任务,即时生效;
-
3、调度中心HA(中心式):调度采用中心式设计,“调度中心”基于集群Quartz实现,可保证调度中心HA;
-
3、调度中心HA(中心式):调度采用中心式设计,“调度中心”基于集群Quartz实现
并支持集群部署
,可保证调度中心HA;
-
4、执行器HA(分布式):任务分布式执行,任务"执行器"支持集群部署,可保证任务执行HA;
-
5、任务Failover:执行器集群部署时,任务路由策略选择"故障转移"情况下调度失败时将会平滑切换执行器进行Failover;
-
6、一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
-
7、自定义任务参数:支持在线配置调度任务入参,即时生效;
-
8、调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
-
9、弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
-
10、邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
-
11、状态监控:支持实时监控任务进度;
-
12、Rolling执行日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;
-
13、GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯。
-
14、数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
-
15、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
-
16、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
-
17、任务注册: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
-
18、路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;
-
19、运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
-
20、脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python等类型脚本;
-
21、阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
-
22、失败处理策略;调度失败时的处理策略,策略包括:失败告警(默认)、失败重试;
-
23、分片广播任务:执行器集群部署时,任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发对应集群中所有执行器执行一次任务,同时传递分片参数;可根据分片参数开发分片任务;
-
24、动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度。
-
25、事件触发:除了"Cron方式"和"任务依赖方式"触发任务执行之外,支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务,可根据业务事件灵活触发。
-
5、注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
-
6、弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
-
7、路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;
-
8、故障转移:任务路由策略选择"故障转移"情况下,如果执行器集群中某一台机器故障,将会自动Failover切换到一台正常的执行器发送调度请求。
-
9、失败处理策略;调度失败时的处理策略,策略包括:失败告警(默认)、失败重试;
-
10、失败重试:调度中心调度失败且启用"失败重试"策略时,将会自动重试一次;执行器执行失败且回调失败重试状态时,也将会自动重试一次;
-
11、阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
-
12、分片广播任务:执行器集群部署时,任务路由策略选择"分片广播"情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务;
-
13、动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度。
-
14、事件触发:除了"Cron方式"和"任务依赖方式"触发任务执行之外,支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务,可根据业务事件灵活触发。
-
15、任务进度监控:支持实时监控任务进度;
-
16、Rolling实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;
-
17、GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯。
-
18、脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS等类型脚本;
-
19、任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
-
20、一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
-
21、自定义任务参数:支持在线配置调度任务入参,即时生效;
-
22、调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
-
23、数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
-
24、邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
-
25、推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
-
26、运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
## Development
...
...
@@ -83,8 +84,10 @@ XXL-JOB是一个轻量级分布式任务调度框架,其核心设计目标是
于2017-05-13,在上海举办的 "
[
第62期开源中国源创会
](
https://www.oschina.net/event/2236961
)
" 的 "放码过来" 环节,我登台对XXL-JOB做了演讲,台下五百位在场观众反响热烈(
[
图文回顾
](
https://www.oschina.net/question/2686220_2242120
)
)。
于2017-12-11,XXL-JOB有幸参会《
[
InfoQ ArchSummit全球架构师峰会
](
http://bj2017.archsummit.com/
)
》,并被拍拍贷架构总监"杨波老师"在专题 "
[
微服务原理、基础架构和开源实践
](
http://bj2017.archsummit.com/training/2
)
" 中现场介绍。
> 我司大众点评目前已接入XXL-JOB,内部别名《Ferrari》(Ferrari基于XXL-JOB的V1.1版本定制而成,新接入应用推荐升级最新版本)。**
据最新统计, 自2016-01-21接入至2017-
07-07期间,该系统已调度约60万余
次,表现优异。新接入应用推荐使用最新版本,因为经过数个大版本的更新,系统的任务模型、UI交互模型以及底层调度通讯模型都有了较大的优化和提升,核心功能更加稳定高效。
据最新统计, 自2016-01-21接入至2017-
12-01期间,该系统已调度约100万
次,表现优异。新接入应用推荐使用最新版本,因为经过数个大版本的更新,系统的任务模型、UI交互模型以及底层调度通讯模型都有了较大的优化和提升,核心功能更加稳定高效。
至今,XXL-JOB已接入多家公司的线上产品线,接入场景如电商业务,O2O业务和大数据作业等,截止2016-07-19为止,XXL-JOB已接入的公司包括不限于:
...
...
@@ -145,6 +148,8 @@ XXL-JOB是一个轻量级分布式任务调度框架,其核心设计目标是
-
55、中商惠民(北京)电子商务有限公司
-
56、凯京集团
-
57、华夏票联(北京)科技有限公司
-
58、拍拍贷
-
59、北京尚德机构在线教育有限公司
-
……
> 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
...
...
doc/XXL-JOB官方文档.md
浏览文件 @
8ed4d055
差异被折叠。
点击展开。
doc/db/tables_xxl_job.sql
浏览文件 @
8ed4d055
CREATE
database
if
NOT
EXISTS
`xxl-job`
default
character
set
utf8
collate
utf8_general_ci
;
use
`xxl-job`
;
CREATE
TABLE
XXL_JOB_QRTZ_JOB_DETAILS
(
SCHED_NAME
VARCHAR
(
120
)
NOT
NULL
,
...
...
@@ -158,14 +160,14 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_INFO` (
`alarm_email`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'报警邮件'
,
`executor_route_strategy`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'执行器路由策略'
,
`executor_handler`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'执行器任务handler'
,
`executor_param`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'执行器任务参数'
,
`executor_param`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'执行器任务参数'
,
`executor_block_strategy`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'阻塞处理策略'
,
`executor_fail_strategy`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'失败处理策略'
,
`glue_type`
varchar
(
50
)
NOT
NULL
COMMENT
'GLUE类型'
,
`glue_source`
text
COMMENT
'GLUE源代码'
,
`glue_remark`
varchar
(
128
)
DEFAULT
NULL
COMMENT
'GLUE备注'
,
`glue_updatetime`
datetime
DEFAULT
NULL
COMMENT
'GLUE更新时间'
,
`child_job
key`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'子任务Key
'
,
`child_job
id`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'子任务ID,多个逗号分隔
'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8
;
...
...
@@ -176,7 +178,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_LOG` (
`glue_type`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'GLUE类型'
,
`executor_address`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'执行器地址,本次执行的地址'
,
`executor_handler`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'执行器任务handler'
,
`executor_param`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'executor_param
'
,
`executor_param`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'执行器任务参数
'
,
`trigger_time`
datetime
DEFAULT
NULL
COMMENT
'调度-时间'
,
`trigger_code`
varchar
(
255
)
NOT
NULL
DEFAULT
'0'
COMMENT
'调度-结果'
,
`trigger_msg`
varchar
(
2048
)
DEFAULT
NULL
COMMENT
'调度-日志'
,
...
...
@@ -212,7 +214,7 @@ CREATE TABLE `XXL_JOB_QRTZ_TRIGGER_GROUP` (
`title`
varchar
(
12
)
NOT
NULL
COMMENT
'执行器名称'
,
`order`
tinyint
(
4
)
NOT
NULL
DEFAULT
'0'
COMMENT
'排序'
,
`address_type`
tinyint
(
4
)
NOT
NULL
DEFAULT
'0'
COMMENT
'执行器地址类型:0=自动注册、1=手动录入'
,
`address_list`
varchar
(
200
)
DEFAULT
NULL
COMMENT
'执行器地址列表,多地址逗号分隔'
,
`address_list`
varchar
(
512
)
DEFAULT
NULL
COMMENT
'执行器地址列表,多地址逗号分隔'
,
PRIMARY
KEY
(
`id`
)
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8
;
...
...
pom.xml
浏览文件 @
8ed4d055
...
...
@@ -20,31 +20,31 @@
<javax.servlet-api.version>
3.0.1
</javax.servlet-api.version>
<jsp-api.version>
2.2
</jsp-api.version>
<spring.version>
3.2.18
.RELEASE
</spring.version>
<jackson
-mapper-asl.version>
1.9.13
</jackson-mapper-asl
.version>
<aspectjweaver.version>
1.8.
7
</aspectjweaver.version>
<spring.version>
4.3.13
.RELEASE
</spring.version>
<jackson
.version>
2.9.3
</jackson
.version>
<aspectjweaver.version>
1.8.
13
</aspectjweaver.version>
<slf4j-api.version>
1.7.25
</slf4j-api.version>
<freemarker.version>
2.3.2
0
</freemarker.version>
<junit.version>
4.1
1
</junit.version>
<freemarker.version>
2.3.2
3
</freemarker.version>
<junit.version>
4.1
2
</junit.version>
<jetty-server.version>
9.2.22.v20170606
</jetty-server.version>
<hessian.version>
4.0.
38
</hessian.version>
<httpclient.version>
4.
3.6
</httpclient.version>
<hessian.version>
4.0.
51
</hessian.version>
<httpclient.version>
4.
5.4
</httpclient.version>
<commons-exec.version>
1.3
</commons-exec.version>
<commons-beanutils.version>
1.9.2
</commons-beanutils.version>
<commons-lang.version>
2.6
</commons-lang.version>
<commons-collections4.version>
4.1
</commons-collections4.version>
<commons-lang3.version>
3.7
</commons-lang3.version>
<commons-email.version>
1.5
</commons-email.version>
<c3p0.version>
0.9.5.2
</c3p0.version>
<mysql-connector-java.version>
5.1.
29
</mysql-connector-java.version>
<mybatis-spring.version>
1.
2.2
</mybatis-spring.version>
<mybatis.version>
3.
2.8
</mybatis.version>
<mysql-connector-java.version>
5.1.
45
</mysql-connector-java.version>
<mybatis-spring.version>
1.
3.1
</mybatis-spring.version>
<mybatis.version>
3.
4.5
</mybatis.version>
<groovy-all.version>
2.4.5
</groovy-all.version>
<mail.version>
1.4.6
</mail.version>
<groovy-all.version>
2.4.13
</groovy-all.version>
<quartz.version>
2.3.0
</quartz.version>
<spring-boot.version>
1.5.
6
.RELEASE
</spring-boot.version>
<spring-boot.version>
1.5.
9
.RELEASE
</spring-boot.version>
</properties>
<build>
...
...
xxl-job-admin/pom.xml
浏览文件 @
8ed4d055
...
...
@@ -40,18 +40,22 @@
</dependency>
<!-- jackson (support spring json) -->
<dependency>
<groupId>
org.codehaus.jackson
</groupId>
<artifactId>
jackson-
mapper-asl
</artifactId>
<version>
${jackson
-mapper-asl
.version}
</version>
<groupId>
com.fasterxml.jackson.core
</groupId>
<artifactId>
jackson-
databind
</artifactId>
<version>
${jackson.version}
</version>
</dependency>
<!-- s
lf4j
-->
<!-- s
ervlet
-->
<dependency>
<groupId>
org.slf4j
</groupId>
<artifactId>
slf4j-log4j12
</artifactId>
<version>
${slf4j-api.version}
</version>
<groupId>
javax.servlet
</groupId>
<artifactId>
javax.servlet-api
</artifactId>
<version>
${javax.servlet-api.version}
</version>
</dependency>
<dependency>
<groupId>
javax.servlet.jsp
</groupId>
<artifactId>
jsp-api
</artifactId>
<version>
${jsp-api.version}
</version>
</dependency>
<!-- freemarker -->
<dependency>
<groupId>
org.freemarker
</groupId>
...
...
@@ -59,37 +63,37 @@
<version>
${freemarker.version}
</version>
</dependency>
<!--
commons-beanutils
-->
<!--
slf4j
-->
<dependency>
<groupId>
commons-beanutils
</groupId>
<artifactId>
commons-beanutils
</artifactId>
<version>
${
commons-beanutils
.version}
</version>
<groupId>
org.slf4j
</groupId>
<artifactId>
slf4j-log4j12
</artifactId>
<version>
${
slf4j-api
.version}
</version>
</dependency>
<!--
commons-lang
-->
<!--
junit
-->
<dependency>
<groupId>
commons-lang
</groupId>
<artifactId>
commons-lang
</artifactId>
<version>
${commons-lang.version}
</version>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<version>
${junit.version}
</version>
<scope>
test
</scope>
</dependency>
<!--
servlet
-->
<!--
commons-collections4
-->
<dependency>
<groupId>
javax.servlet
</groupId>
<artifactId>
javax.servlet-api
</artifactId>
<version>
${
javax.servlet-api
.version}
</version>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-collections4
</artifactId>
<version>
${
commons-collections4
.version}
</version>
</dependency>
<!-- commons-lang3 -->
<dependency>
<groupId>
javax.servlet.jsp
</groupId>
<artifactId>
jsp-api
</artifactId>
<version>
${
jsp-api
.version}
</version>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
<version>
${
commons-lang3
.version}
</version>
</dependency>
<!-- junit -->
<!-- commons-email -->
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<version>
${junit.version}
</version>
<scope>
test
</scope>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-email
</artifactId>
<version>
${commons-email.version}
</version>
</dependency>
<!-- c3p0 -->
...
...
@@ -116,7 +120,6 @@
<version>
${mybatis.version}
</version>
</dependency>
<!-- httpclient -->
<dependency>
<groupId>
org.apache.httpcomponents
</groupId>
...
...
@@ -124,13 +127,6 @@
<version>
${httpclient.version}
</version>
</dependency>
<!-- javax.mail -->
<dependency>
<groupId>
javax.mail
</groupId>
<artifactId>
mail
</artifactId>
<version>
${mail.version}
</version>
</dependency>
<!-- quartz :quartz-2.2.3/c3p0-0.9.1.1/slf4j-api-1.6.6 -->
<dependency>
<groupId>
org.quartz-scheduler
</groupId>
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/IndexController.java
浏览文件 @
8ed4d055
...
...
@@ -2,10 +2,9 @@ package com.xxl.job.admin.controller;
import
com.xxl.job.admin.controller.annotation.PermessionLimit
;
import
com.xxl.job.admin.controller.interceptor.PermissionInterceptor
;
import
com.xxl.job.admin.core.util.PropertiesUtil
;
import
com.xxl.job.admin.service.XxlJobService
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.commons.lang
3
.StringUtils
;
import
org.springframework.beans.propertyeditors.CustomDateEditor
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.ui.Model
;
...
...
@@ -61,18 +60,21 @@ public class IndexController {
@ResponseBody
@PermessionLimit
(
limit
=
false
)
public
ReturnT
<
String
>
loginDo
(
HttpServletRequest
request
,
HttpServletResponse
response
,
String
userName
,
String
password
,
String
ifRemember
){
if
(!
PermissionInterceptor
.
ifLogin
(
request
))
{
if
(
StringUtils
.
isNotBlank
(
userName
)
&&
StringUtils
.
isNotBlank
(
password
)
&&
PropertiesUtil
.
getString
(
"xxl.job.login.username"
).
equals
(
userName
)
&&
PropertiesUtil
.
getString
(
"xxl.job.login.password"
).
equals
(
password
))
{
boolean
ifRem
=
false
;
if
(
StringUtils
.
isNotBlank
(
ifRemember
)
&&
"on"
.
equals
(
ifRemember
))
{
ifRem
=
true
;
// valid
if
(
PermissionInterceptor
.
ifLogin
(
request
))
{
return
ReturnT
.
SUCCESS
;
}
PermissionInterceptor
.
login
(
response
,
ifRem
);
}
else
{
return
new
ReturnT
<
String
>(
500
,
"账号或密码错误"
);
// param
if
(
StringUtils
.
isBlank
(
userName
)
||
StringUtils
.
isBlank
(
password
)){
return
new
ReturnT
<
String
>(
500
,
"账号或密码为空"
);
}
boolean
ifRem
=
(
StringUtils
.
isNotBlank
(
ifRemember
)
&&
"on"
.
equals
(
ifRemember
))?
true
:
false
;
// do login
boolean
loginRet
=
PermissionInterceptor
.
login
(
response
,
userName
,
password
,
ifRem
);
if
(!
loginRet
)
{
return
new
ReturnT
<
String
>(
500
,
"账号或密码错误"
);
}
return
ReturnT
.
SUCCESS
;
}
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobGroupController.java
浏览文件 @
8ed4d055
...
...
@@ -4,7 +4,7 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
import
com.xxl.job.admin.dao.XxlJobGroupDao
;
import
com.xxl.job.admin.dao.XxlJobInfoDao
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.commons.lang
3
.StringUtils
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.ui.Model
;
import
org.springframework.web.bind.annotation.RequestMapping
;
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/JobLogController.java
浏览文件 @
8ed4d055
...
...
@@ -11,8 +11,8 @@ import com.xxl.job.core.biz.ExecutorBiz;
import
com.xxl.job.core.biz.model.LogResult
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
com.xxl.job.core.rpc.netcom.NetComClientProxy
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.commons.lang.time.DateUtils
;
import
org.apache.commons.lang
3
.StringUtils
;
import
org.apache.commons.lang
3
.time.DateUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Controller
;
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/CookieInterceptor.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
controller
.
interceptor
;
import
java.util.HashMap
;
import
org.apache.commons.lang3.ArrayUtils
;
import
org.springframework.web.servlet.ModelAndView
;
import
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
;
import
javax.servlet.http.Cookie
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.apache.commons.lang.ArrayUtils
;
import
org.springframework.web.servlet.ModelAndView
;
import
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
;
import
java.util.HashMap
;
/**
* push cookies to model as cookieMap
*
* @author xuxueli 2015-12-12 18:09:04
*/
public
class
CookieInterceptor
extends
HandlerInterceptorAdapter
{
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/controller/interceptor/PermissionInterceptor.java
浏览文件 @
8ed4d055
...
...
@@ -3,6 +3,7 @@ package com.xxl.job.admin.controller.interceptor;
import
com.xxl.job.admin.controller.annotation.PermessionLimit
;
import
com.xxl.job.admin.core.util.CookieUtil
;
import
com.xxl.job.admin.core.util.PropertiesUtil
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.springframework.web.method.HandlerMethod
;
import
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
;
...
...
@@ -12,20 +13,38 @@ import java.math.BigInteger;
/**
* 权限拦截, 简易版
*
* @author xuxueli 2015-12-12 18:09:04
*/
public
class
PermissionInterceptor
extends
HandlerInterceptorAdapter
{
public
static
final
String
LOGIN_IDENTITY_KEY
=
"LOGIN_IDENTITY"
;
public
static
final
String
LOGIN_IDENTITY_KEY
=
"XXL_JOB_LOGIN_IDENTITY"
;
public
static
final
String
LOGIN_IDENTITY_TOKEN
;
static
{
String
username
=
PropertiesUtil
.
getString
(
"xxl.job.login.username"
);
String
password
=
PropertiesUtil
.
getString
(
"xxl.job.login.password"
);
String
temp
=
username
+
"_"
+
password
;
LOGIN_IDENTITY_TOKEN
=
new
BigInteger
(
1
,
temp
.
getBytes
()).
toString
(
16
);
// login token
String
tokenTmp
=
DigestUtils
.
md5Hex
(
username
+
"_"
+
password
);
tokenTmp
=
new
BigInteger
(
1
,
tokenTmp
.
getBytes
()).
toString
(
16
);
LOGIN_IDENTITY_TOKEN
=
tokenTmp
;
}
public
static
boolean
login
(
HttpServletResponse
response
,
String
username
,
String
password
,
boolean
ifRemember
){
// login token
String
tokenTmp
=
DigestUtils
.
md5Hex
(
username
+
"_"
+
password
);
tokenTmp
=
new
BigInteger
(
1
,
tokenTmp
.
getBytes
()).
toString
(
16
);
if
(!
LOGIN_IDENTITY_TOKEN
.
equals
(
tokenTmp
)){
return
false
;
}
public
static
boolean
login
(
HttpServletResponse
response
,
boolean
ifRemember
){
// do login
CookieUtil
.
set
(
response
,
LOGIN_IDENTITY_KEY
,
LOGIN_IDENTITY_TOKEN
,
ifRemember
);
return
true
;
}
...
...
@@ -40,6 +59,8 @@ public class PermissionInterceptor extends HandlerInterceptorAdapter {
return
true
;
}
@Override
public
boolean
preHandle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Object
handler
)
throws
Exception
{
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobGroup.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
core
.
model
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.commons.lang
3
.StringUtils
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobInfo.java
浏览文件 @
8ed4d055
...
...
@@ -31,7 +31,7 @@ public class XxlJobInfo {
private
String
glueRemark
;
// GLUE备注
private
Date
glueUpdatetime
;
// GLUE更新时间
private
String
childJob
Key
;
// 子任务Key
private
String
childJob
Id
;
// 子任务ID,多个逗号分隔
// copy from quartz
private
String
jobStatus
;
// 任务状态 【base on quartz】
...
...
@@ -172,12 +172,12 @@ public class XxlJobInfo {
this
.
glueUpdatetime
=
glueUpdatetime
;
}
public
String
getChildJob
Key
()
{
return
childJob
Key
;
public
String
getChildJob
Id
()
{
return
childJob
Id
;
}
public
void
setChildJob
Key
(
String
childJobKey
)
{
this
.
childJob
Key
=
childJobKey
;
public
void
setChildJob
Id
(
String
childJobId
)
{
this
.
childJob
Id
=
childJobId
;
}
public
String
getJobStatus
()
{
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobFailMonitorHelper.java
浏览文件 @
8ed4d055
...
...
@@ -6,7 +6,8 @@ import com.xxl.job.admin.core.model.XxlJobLog;
import
com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler
;
import
com.xxl.job.admin.core.util.MailUtil
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
org.apache.commons.collections.CollectionUtils
;
import
com.xxl.job.core.handler.IJobHandler
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -27,6 +28,8 @@ public class JobFailMonitorHelper {
return
instance
;
}
// ---------------------- monitor ----------------------
private
LinkedBlockingQueue
<
Integer
>
queue
=
new
LinkedBlockingQueue
<
Integer
>(
0xfff8
);
private
Thread
monitorThread
;
...
...
@@ -51,13 +54,15 @@ public class JobFailMonitorHelper {
if
(
log
==
null
)
{
continue
;
}
if
(
ReturnT
.
SUCCESS_CODE
==
log
.
getTriggerCode
()
&&
log
.
getHandleCode
()
==
0
)
{
if
(
IJobHandler
.
SUCCESS
.
getCode
()
==
log
.
getTriggerCode
()
&&
log
.
getHandleCode
()
==
0
)
{
JobFailMonitorHelper
.
monitor
(
jobLogId
);
logger
.
info
(
">>>>>>>>>>> job monitor, job running, JobLogId:{}"
,
jobLogId
);
}
else
if
(
ReturnT
.
SUCCESS_CODE
==
log
.
getTriggerCode
()
&&
ReturnT
.
SUCCESS_CODE
==
log
.
getHandleCode
())
{
}
else
if
(
IJobHandler
.
SUCCESS
.
getCode
()
==
log
.
getHandleCode
())
{
// job success, pass
logger
.
info
(
">>>>>>>>>>> job monitor, job success, JobLogId:{}"
,
jobLogId
);
}
else
if
(
ReturnT
.
FAIL_CODE
==
log
.
getTriggerCode
()
||
ReturnT
.
FAIL_CODE
==
log
.
getHandleCode
())
{
}
else
if
(
IJobHandler
.
FAIL
.
getCode
()
==
log
.
getTriggerCode
()
||
IJobHandler
.
FAIL
.
getCode
()
==
log
.
getHandleCode
()
||
IJobHandler
.
FAIL_RETRY
.
getCode
()
==
log
.
getHandleCode
()
)
{
// job fail,
failAlarm
(
log
);
logger
.
info
(
">>>>>>>>>>> job monitor, job fail, JobLogId:{}"
,
jobLogId
);
...
...
@@ -94,6 +99,46 @@ public class JobFailMonitorHelper {
monitorThread
.
start
();
}
public
void
toStop
(){
toStop
=
true
;
// interrupt and wait
monitorThread
.
interrupt
();
try
{
monitorThread
.
join
();
}
catch
(
InterruptedException
e
)
{
logger
.
error
(
e
.
getMessage
(),
e
);
}
}
// producer
public
static
void
monitor
(
int
jobLogId
){
getInstance
().
queue
.
offer
(
jobLogId
);
}
// ---------------------- alarm ----------------------
// email alarm template
private
static
final
String
mailBodyTemplate
=
"<h5>监控告警明细:</span>"
+
"<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n"
+
" <thead style=\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\" >"
+
" <tr>\n"
+
" <td>执行器</td>\n"
+
" <td>任务ID</td>\n"
+
" <td>任务描述</td>\n"
+
" <td>告警类型</td>\n"
+
" </tr>\n"
+
" <thead/>\n"
+
" <tbody>\n"
+
" <tr>\n"
+
" <td>{0}</td>\n"
+
" <td>{1}</td>\n"
+
" <td>{2}</td>\n"
+
" <td>调度失败</td>\n"
+
" </tr>\n"
+
" <tbody>\n"
+
"</table>"
;
/**
* fail alarm
*
...
...
@@ -107,31 +152,17 @@ public class JobFailMonitorHelper {
Set
<
String
>
emailSet
=
new
HashSet
<
String
>(
Arrays
.
asList
(
info
.
getAlarmEmail
().
split
(
","
)));
for
(
String
email:
emailSet
)
{
String
title
=
"《调度监控报警》(任务调度中心XXL-JOB)"
;
XxlJobGroup
group
=
XxlJobDynamicScheduler
.
xxlJobGroupDao
.
load
(
Integer
.
valueOf
(
info
.
getJobGroup
()));
String
content
=
MessageFormat
.
format
(
"任务调度失败, 执行器名称:{0}, 任务描述:{1}."
,
group
!=
null
?
group
.
getTitle
():
"null"
,
info
.
getJobDesc
());
MailUtil
.
sendMail
(
email
,
title
,
content
,
false
,
null
);
}
}
// TODO, custom alarm strategy, such as sms
}
String
title
=
"调度中心监控报警"
;
String
content
=
MessageFormat
.
format
(
mailBodyTemplate
,
group
!=
null
?
group
.
getTitle
():
"null"
,
info
.
getId
(),
info
.
getJobDesc
());
public
void
toStop
(){
toStop
=
true
;
// interrupt and wait
monitorThread
.
interrupt
();
try
{
monitorThread
.
join
();
}
catch
(
InterruptedException
e
)
{
logger
.
error
(
e
.
getMessage
(),
e
);
MailUtil
.
sendMail
(
email
,
title
,
content
);
}
}
// producer
public
static
void
monitor
(
int
jobLogId
){
getInstance
().
queue
.
offer
(
jobLogId
);
// TODO, custom alarm strategy, such as sms
}
}
xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobRegistryMonitorHelper.java
浏览文件 @
8ed4d055
...
...
@@ -4,8 +4,8 @@ import com.xxl.job.admin.core.model.XxlJobGroup;
import
com.xxl.job.admin.core.model.XxlJobRegistry
;
import
com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler
;
import
com.xxl.job.core.enums.RegistryConfig
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.commons.collections
4
.CollectionUtils
;
import
org.apache.commons.lang
3
.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/core/trigger/XxlJobTrigger.java
浏览文件 @
8ed4d055
...
...
@@ -11,7 +11,8 @@ import com.xxl.job.core.biz.ExecutorBiz;
import
com.xxl.job.core.biz.model.ReturnT
;
import
com.xxl.job.core.biz.model.TriggerParam
;
import
com.xxl.job.core.enums.ExecutorBlockStrategyEnum
;
import
org.apache.commons.collections.CollectionUtils
;
import
com.xxl.job.core.util.IpUtil
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -66,11 +67,12 @@ public class XxlJobTrigger {
ReturnT
<
String
>
triggerResult
=
new
ReturnT
<
String
>(
null
);
StringBuffer
triggerMsgSb
=
new
StringBuffer
();
triggerMsgSb
.
append
(
"注册方式:"
).
append
(
(
group
.
getAddressType
()
==
0
)?
"自动注册"
:
"手动录入"
);
triggerMsgSb
.
append
(
"调度机器:"
).
append
(
IpUtil
.
getIp
());
triggerMsgSb
.
append
(
"<br>执行器-注册方式:"
).
append
(
(
group
.
getAddressType
()
==
0
)?
"自动注册"
:
"手动录入"
);
triggerMsgSb
.
append
(
"<br>执行器-地址列表:"
).
append
(
group
.
getRegistryList
());
triggerMsgSb
.
append
(
"<br>路由策略:"
).
append
(
executorRouteStrategyEnum
.
getTitle
()).
append
(
"("
+
i
+
"/"
+
addressList
.
size
()+
")"
);
// update01
triggerMsgSb
.
append
(
"<br>阻塞处理策略:"
).
append
(
blockStrategy
.
getTitle
());
triggerMsgSb
.
append
(
"<br>失败处理策略:"
).
append
(
failStrategy
.
getTitle
());
triggerMsgSb
.
append
(
"<br>地址列表:"
).
append
(
group
.
getRegistryList
());
triggerMsgSb
.
append
(
"<br>路由策略:"
).
append
(
executorRouteStrategyEnum
.
getTitle
()).
append
(
"("
+
i
+
"/"
+
addressList
.
size
()+
")"
);
// update01
// 3、trigger-valid
if
(
triggerResult
.
getCode
()==
ReturnT
.
SUCCESS_CODE
&&
CollectionUtils
.
isEmpty
(
addressList
))
{
...
...
@@ -115,9 +117,7 @@ public class XxlJobTrigger {
logger
.
debug
(
">>>>>>>>>>> xxl-job trigger end, jobId:{}"
,
jobLog
.
getId
());
}
return
;
}
}
else
{
// 1、save log-id
XxlJobLog
jobLog
=
new
XxlJobLog
();
jobLog
.
setJobGroup
(
jobInfo
.
getJobGroup
());
...
...
@@ -134,11 +134,12 @@ public class XxlJobTrigger {
ReturnT
<
String
>
triggerResult
=
new
ReturnT
<
String
>(
null
);
StringBuffer
triggerMsgSb
=
new
StringBuffer
();
triggerMsgSb
.
append
(
"注册方式:"
).
append
(
(
group
.
getAddressType
()
==
0
)?
"自动注册"
:
"手动录入"
);
triggerMsgSb
.
append
(
"调度机器:"
).
append
(
IpUtil
.
getIp
());
triggerMsgSb
.
append
(
"<br>执行器-注册方式:"
).
append
(
(
group
.
getAddressType
()
==
0
)?
"自动注册"
:
"手动录入"
);
triggerMsgSb
.
append
(
"<br>执行器-地址列表:"
).
append
(
group
.
getRegistryList
());
triggerMsgSb
.
append
(
"<br>路由策略:"
).
append
(
executorRouteStrategyEnum
.
getTitle
());
triggerMsgSb
.
append
(
"<br>阻塞处理策略:"
).
append
(
blockStrategy
.
getTitle
());
triggerMsgSb
.
append
(
"<br>失败处理策略:"
).
append
(
failStrategy
.
getTitle
());
triggerMsgSb
.
append
(
"<br>地址列表:"
).
append
(
group
.
getRegistryList
());
triggerMsgSb
.
append
(
"<br>路由策略:"
).
append
(
executorRouteStrategyEnum
.
getTitle
());
// 3、trigger-valid
if
(
triggerResult
.
getCode
()==
ReturnT
.
SUCCESS_CODE
&&
CollectionUtils
.
isEmpty
(
addressList
))
{
...
...
@@ -168,7 +169,7 @@ public class XxlJobTrigger {
// 4.3、trigger (fail retry)
if
(
triggerResult
.
getCode
()!=
ReturnT
.
SUCCESS_CODE
&&
failStrategy
==
ExecutorFailStrategyEnum
.
FAIL_RETRY
)
{
triggerResult
=
executorRouteStrategyEnum
.
getRouter
().
routeRun
(
triggerParam
,
addressList
);
triggerMsgSb
.
append
(
"<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>
失败重试<<<<<<<<<<< </span><br>"
).
append
(
triggerResult
.
getMsg
());
triggerMsgSb
.
append
(
"<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>调度
失败重试<<<<<<<<<<< </span><br>"
).
append
(
triggerResult
.
getMsg
());
}
}
...
...
@@ -183,6 +184,8 @@ public class XxlJobTrigger {
logger
.
debug
(
">>>>>>>>>>> xxl-job trigger end, jobId:{}"
,
jobLog
.
getId
());
}
}
/**
* run executor
* @param triggerParam
...
...
@@ -195,7 +198,7 @@ public class XxlJobTrigger {
ExecutorBiz
executorBiz
=
XxlJobDynamicScheduler
.
getExecutorBiz
(
address
);
runResult
=
executorBiz
.
run
(
triggerParam
);
}
catch
(
Exception
e
)
{
logger
.
error
(
e
.
getMessage
()
,
e
);
logger
.
error
(
">>>>>>>>>>> xxl-job trigger error, please check if the executor[{}] is running."
,
address
,
e
);
runResult
=
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
""
+
e
);
}
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/CookieUtil.java
浏览文件 @
8ed4d055
...
...
@@ -6,9 +6,11 @@ import javax.servlet.http.HttpServletResponse;
/**
* Cookie.Util
*
* @author xuxueli 2015-12-12 18:01:06
*/
public
class
CookieUtil
{
// 默认缓存时间,单位/秒, 2H
private
static
final
int
COOKIE_MAX_AGE
=
60
*
60
*
2
;
// 保存路径,根路径
...
...
@@ -16,43 +18,39 @@ public class CookieUtil {
/**
* 保存
*
* @param response
* @param key
* @param value
* @param ifRemember
*/
public
static
void
set
(
HttpServletResponse
response
,
String
key
,
String
value
,
boolean
ifRemember
)
{
int
age
=
COOKIE_MAX_AGE
;
if
(
ifRemember
)
{
age
=
COOKIE_MAX_AGE
;
}
else
{
age
=
-
1
;
}
Cookie
cookie
=
new
Cookie
(
key
,
value
);
cookie
.
setMaxAge
(
age
);
// Cookie过期时间,单位/秒
cookie
.
setPath
(
COOKIE_PATH
);
// Cookie适用的路径
response
.
addCookie
(
cookie
);
int
age
=
ifRemember
?
COOKIE_MAX_AGE:
-
1
;
set
(
response
,
key
,
value
,
null
,
COOKIE_PATH
,
age
,
true
);
}
/**
* 保存
*
* @param response
* @param key
* @param value
* @param maxAge
*/
private
static
void
set
(
HttpServletResponse
response
,
String
key
,
String
value
,
int
maxAge
,
String
path
)
{
private
static
void
set
(
HttpServletResponse
response
,
String
key
,
String
value
,
String
domain
,
String
path
,
int
maxAge
,
boolean
isHttpOnly
)
{
Cookie
cookie
=
new
Cookie
(
key
,
value
);
cookie
.
setMaxAge
(
maxAge
);
// Cookie过期时间,单位/秒
cookie
.
setPath
(
path
);
// Cookie适用的路径
if
(
domain
!=
null
)
{
cookie
.
setDomain
(
domain
);
}
cookie
.
setPath
(
path
);
cookie
.
setMaxAge
(
maxAge
);
cookie
.
setHttpOnly
(
isHttpOnly
);
response
.
addCookie
(
cookie
);
}
/**
* 查询value
*
* @param request
* @param key
* @return
...
...
@@ -67,6 +65,7 @@ public class CookieUtil {
/**
* 查询Cookie
*
* @param request
* @param key
*/
...
...
@@ -84,15 +83,15 @@ public class CookieUtil {
/**
* 删除Cookie
*
* @param request
* @param response
* @param key
* @param domainName
*/
public
static
void
remove
(
HttpServletRequest
request
,
HttpServletResponse
response
,
String
key
)
{
Cookie
cookie
=
get
(
request
,
key
);
if
(
cookie
!=
null
)
{
set
(
response
,
key
,
""
,
0
,
COOKIE_PATH
);
set
(
response
,
key
,
""
,
null
,
COOKIE_PATH
,
0
,
true
);
}
}
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/MailUtil.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
core
.
util
;
import
org.apache.commons.lang.ArrayUtils
;
import
org.apache.commons.mail.DefaultAuthenticator
;
import
org.apache.commons.mail.EmailException
;
import
org.apache.commons.mail.HtmlEmail
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.mail.javamail.JavaMailSender
;
import
org.springframework.mail.javamail.JavaMailSenderImpl
;
import
org.springframework.mail.javamail.MimeMessageHelper
;
import
javax.mail.internet.MimeMessage
;
import
javax.mail.internet.MimeUtility
;
import
java.io.File
;
import
java.util.Properties
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.nio.charset.Charset
;
/**
* 邮件发送.Util
*
* @author xuxueli 2016-3-12 15:06:20
*/
public
class
MailUtil
{
...
...
@@ -35,152 +30,42 @@ public class MailUtil {
}
/**
<!-- spring mail sender -->
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" scope="singleton" >
<property name="host" value="${mail.host}" /> <!-- SMTP发送邮件的服务器的IP和端口 -->
<property name="port" value="${mail.port}" />
<property name="username" value="${mail.username}" /> <!-- 登录SMTP邮件发送服务器的用户名和密码 -->
<property name="password" value="${mail.password}" />
<property name="javaMailProperties"> <!-- 获得邮件会话属性,验证登录邮件服务器是否成功 -->
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="prop">true</prop>
<!-- <prop key="mail.smtp.timeout">25000</prop> -->
</props>
</property>
</bean>
*/
/**
* 发送邮件 (完整版)(结合Spring)
*
* //@param javaMailSender: 发送Bean
* //@param sendFrom : 发送人邮箱
* //@param sendNick : 发送人昵称
* @param toAddress : 收件人邮箱
* @param mailSubject : 邮件主题
* @param mailBody : 邮件正文
* @param mailBodyIsHtml: 邮件正文格式,true:HTML格式;false:文本格式
* @param attachments : 附件
* @param toAddress 收件人邮箱
* @param mailSubject 邮件主题
* @param mailBody 邮件正文
* @return
*/
@SuppressWarnings
(
"null"
)
public
static
boolean
sendMailSpring
(
String
toAddress
,
String
mailSubject
,
String
mailBody
,
boolean
mailBodyIsHtml
,
File
[]
attachments
)
{
JavaMailSender
javaMailSender
=
null
;
//ResourceBundle.getInstance().getJavaMailSender();
try
{
MimeMessage
mimeMessage
=
javaMailSender
.
createMimeMessage
();
MimeMessageHelper
helper
=
new
MimeMessageHelper
(
mimeMessage
,
ArrayUtils
.
isNotEmpty
(
attachments
),
"UTF-8"
);
// 设置utf-8或GBK编码,否则邮件会有乱码;multipart,true表示文件上传
helper
.
setFrom
(
username
,
sendNick
);
helper
.
setTo
(
toAddress
);
// 设置收件人抄送的名片和地址(相当于群发了)
//helper.setCc(InternetAddress.parse(MimeUtility.encodeText("邮箱001") + " <@163.com>," + MimeUtility.encodeText("邮箱002") + " <@foxmail.com>"));
helper
.
setSubject
(
mailSubject
);
helper
.
setText
(
mailBody
,
mailBodyIsHtml
);
// 添加附件
if
(
ArrayUtils
.
isNotEmpty
(
attachments
))
{
for
(
File
file
:
attachments
)
{
helper
.
addAttachment
(
MimeUtility
.
encodeText
(
file
.
getName
()),
file
);
}
}
// 群发
//MimeMessage[] mailMessages = { mimeMessage };
javaMailSender
.
send
(
mimeMessage
);
return
true
;
}
catch
(
Exception
e
)
{
logger
.
error
(
e
.
getMessage
(),
e
);
}
return
false
;
}
public
static
boolean
sendMail
(
String
toAddress
,
String
mailSubject
,
String
mailBody
){
/**
* 发送邮件 (完整版) (纯JavaMail)
*
* @param toAddress : 收件人邮箱
* @param mailSubject : 邮件主题
* @param mailBody : 邮件正文
* @param mailBodyIsHtml: 邮件正文格式,true:HTML格式;false:文本格式
* //@param inLineFile : 内嵌文件
* @param attachments : 附件
*/
public
static
boolean
sendMail
(
String
toAddress
,
String
mailSubject
,
String
mailBody
,
boolean
mailBodyIsHtml
,
File
[]
attachments
){
try
{
// 创建邮件发送类 JavaMailSender (用于发送多元化邮件,包括附件,图片,html 等)
JavaMailSenderImpl
mailSender
=
new
JavaMailSenderImpl
();
mailSender
.
setHost
(
host
);
// 设置邮件服务主机
mailSender
.
setUsername
(
username
);
// 发送者邮箱的用户名
mailSender
.
setPassword
(
password
);
// 发送者邮箱的密码
// 配置文件,用于实例化java.mail.session
Properties
pro
=
new
Properties
();
pro
.
put
(
"mail.transport.protocol"
,
"smtp"
);
pro
.
put
(
"mail.smtp.auth"
,
"true"
);
// 登录SMTP服务器,需要获得授权 (网易163邮箱新近注册的邮箱均不能授权,测试 sohu 的邮箱可以获得授权)
pro
.
put
(
"mail.smtp.socketFactory.port"
,
port
);
pro
.
put
(
"mail.smtp.socketFactory.fallback"
,
"false"
);
mailSender
.
setJavaMailProperties
(
pro
);
// Create the email message
HtmlEmail
email
=
new
HtmlEmail
();
//
创建多元化邮件 (创建 mimeMessage 帮助类,用于封装信息至 mimeMessage)
MimeMessage
mimeMessage
=
mailSender
.
createMimeMessage
();
MimeMessageHelper
helper
=
new
MimeMessageHelper
(
mimeMessage
,
ArrayUtils
.
isNotEmpty
(
attachments
),
"UTF-8"
);
//
email.setDebug(true); // 将会打印一些log
//email.setTLS(true); // 是否TLS校验,,某些邮箱需要TLS安全校验,同理有SSL校验
//email.setSSL(true
);
helper
.
setFrom
(
username
,
sendNick
);
helper
.
setTo
(
toAddress
);
email
.
setHostName
(
host
);
email
.
setSmtpPort
(
Integer
.
valueOf
(
port
));
//email.setSslSmtpPort(port);
email
.
setAuthenticator
(
new
DefaultAuthenticator
(
username
,
password
));
email
.
setCharset
(
Charset
.
defaultCharset
().
name
());
helper
.
setSubject
(
mailSubject
);
helper
.
setText
(
mailBody
,
mailBodyIsHtml
);
// 设置收件人抄送的名片和地址(相当于群发)
//helper.setCc(InternetAddress.parse(MimeUtility.encodeText("邮箱001") + " <@163.com>," + MimeUtility.encodeText("邮箱002") + " <@foxmail.com>"));
// 内嵌文件,第1个参数为cid标识这个文件,第2个参数为资源
//helper.addInline(MimeUtility.encodeText(inLineFile.getName()), inLineFile);
// 添加附件
/*if (ArrayUtils.isNotEmpty(attachments)) {
for (File file : attachments) {
helper.addAttachment(MimeUtility.encodeText(file.getName()), file);
}
}*/
email
.
setFrom
(
username
,
sendNick
);
email
.
addTo
(
toAddress
);
email
.
setSubject
(
mailSubject
);
email
.
setMsg
(
mailBody
);
// 群发
//MimeMessage[] mailMessages = { mimeMessage };
//email.attach(attachment); // add the attachment
mailSender
.
send
(
mimeMessage
);
email
.
send
();
// send the email
return
true
;
}
catch
(
Exception
e
)
{
}
catch
(
E
mailE
xception
e
)
{
logger
.
error
(
e
.
getMessage
(),
e
);
}
return
false
;
}
static
int
total
=
0
;
public
static
void
main
(
String
[]
args
)
{
ExecutorService
exec
=
Executors
.
newCachedThreadPool
();
for
(
int
i
=
0
;
i
<
1
;
i
++)
{
exec
.
execute
(
new
Thread
(
new
Runnable
()
{
@Override
public
void
run
()
{
while
(
total
<
1
){
String
mailBody
=
"<html><head><meta http-equiv="
+
"Content-Type"
+
" content="
+
"text/html; charset=gb2312"
+
"></head><body><h1>新书快递通知</h1>你的新书快递申请已推送新书,请到<a href=''>空间"
+
"</a>中查看</body></html>"
;
sendMail
(
"931591021@qq.com"
,
"测试邮件"
,
mailBody
,
true
,
null
);
System
.
out
.
println
(
total
);
total
++;
}
}
}));
}
return
false
;
}
}
xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/PropertiesUtil.java
浏览文件 @
8ed4d055
...
...
@@ -12,6 +12,7 @@ import java.util.Properties;
/**
* properties util
*
* @author xuxueli 2015-8-28 10:35:53
*/
public
class
PropertiesUtil
{
...
...
@@ -34,8 +35,4 @@ public class PropertiesUtil {
return
null
;
}
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
getString
(
"xxl.job.login.username"
));
}
}
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/AdminBizImpl.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
service
.
impl
;
import
com.xxl.job.admin.controller.JobApiController
;
import
com.xxl.job.admin.core.model.XxlJobInfo
;
import
com.xxl.job.admin.core.model.XxlJobLog
;
import
com.xxl.job.admin.core.schedule.XxlJobDynamicScheduler
;
import
com.xxl.job.admin.core.trigger.XxlJobTrigger
;
import
com.xxl.job.admin.dao.XxlJobInfoDao
;
import
com.xxl.job.admin.dao.XxlJobLogDao
;
import
com.xxl.job.admin.dao.XxlJobRegistryDao
;
...
...
@@ -13,8 +10,8 @@ import com.xxl.job.core.biz.AdminBiz;
import
com.xxl.job.core.biz.model.HandleCallbackParam
;
import
com.xxl.job.core.biz.model.RegistryParam
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
org.apache.commons.lang.StringUtils
;
import
org.
quartz.SchedulerException
;
import
com.xxl.job.core.handler.IJobHandler
;
import
org.
apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Service
;
...
...
@@ -46,7 +43,7 @@ public class AdminBizImpl implements AdminBiz {
for
(
HandleCallbackParam
handleCallbackParam:
callbackParamList
)
{
ReturnT
<
String
>
callbackResult
=
callback
(
handleCallbackParam
);
logger
.
info
(
">>>>>>>>> JobApiController.callback {}, handleCallbackParam={}, callbackResult={}"
,
(
callbackResult
.
getCode
()==
ReturnT
.
SUCCESS_CODE
?
"success"
:
"fail"
),
handleCallbackParam
,
callbackResult
);
(
callbackResult
.
getCode
()==
IJobHandler
.
SUCCESS
.
getCode
()
?
"success"
:
"fail"
),
handleCallbackParam
,
callbackResult
);
}
return
ReturnT
.
SUCCESS
;
...
...
@@ -58,28 +55,39 @@ public class AdminBizImpl implements AdminBiz {
if
(
log
==
null
)
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
"log item not found."
);
}
if
(
log
.
getHandleCode
()
>
0
)
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
"log repeate callback."
);
// avoid repeat callback, trigger child job etc
}
// trigger success, to trigger child job
, and avoid repeat trigger child job
String
c
hildTrigger
Msg
=
null
;
if
(
ReturnT
.
SUCCESS_CODE
==
handleCallbackParam
.
getExecuteResult
().
getCode
()
&&
ReturnT
.
SUCCESS_CODE
!=
log
.
getHandle
Code
())
{
// trigger success, to trigger child job
String
c
allback
Msg
=
null
;
if
(
IJobHandler
.
SUCCESS
.
getCode
()
==
handleCallbackParam
.
getExecuteResult
().
get
Code
())
{
XxlJobInfo
xxlJobInfo
=
xxlJobInfoDao
.
loadById
(
log
.
getJobId
());
if
(
xxlJobInfo
!=
null
&&
StringUtils
.
isNotBlank
(
xxlJobInfo
.
getChildJobKey
()))
{
childTriggerMsg
=
"<hr>"
;
String
[]
childJobKeys
=
xxlJobInfo
.
getChildJobKey
().
split
(
","
);
for
(
int
i
=
0
;
i
<
childJobKeys
.
length
;
i
++)
{
String
[]
jobKeyArr
=
childJobKeys
[
i
].
split
(
"_"
);
if
(
jobKeyArr
!=
null
&&
jobKeyArr
.
length
==
2
)
{
ReturnT
<
String
>
triggerChildResult
=
xxlJobService
.
triggerJob
(
Integer
.
valueOf
(
jobKeyArr
[
1
]));
if
(
xxlJobInfo
!=
null
&&
StringUtils
.
isNotBlank
(
xxlJobInfo
.
getChildJobId
()))
{
callbackMsg
=
"<br><br><span style=\"color:#00c0ef;\" > >>>>>>>>>>>触发子任务<<<<<<<<<<< </span><br>"
;
String
[]
childJobIds
=
xxlJobInfo
.
getChildJobId
().
split
(
","
);
for
(
int
i
=
0
;
i
<
childJobIds
.
length
;
i
++)
{
int
childJobId
=
(
StringUtils
.
isNotBlank
(
childJobIds
[
i
])
&&
StringUtils
.
isNumeric
(
childJobIds
[
i
]))?
Integer
.
valueOf
(
childJobIds
[
i
]):-
1
;
if
(
childJobId
>
0
)
{
ReturnT
<
String
>
triggerChildResult
=
xxlJobService
.
triggerJob
(
childJobId
);
// add msg
c
hildTriggerMsg
+=
MessageFormat
.
format
(
"<br> {0}/{1} 触发子任务{2}, 子任务Key: {3}, 子任务触发备注: {4}
"
,
(
i
+
1
),
childJob
Keys
.
length
,
(
triggerChildResult
.
getCode
()==
ReturnT
.
SUCCESS_CODE
?
"成功"
:
"失败"
),
childJobKeys
[
i
]
,
triggerChildResult
.
getMsg
());
c
allbackMsg
+=
MessageFormat
.
format
(
"{0}/{1} [任务ID={2}], 触发{3}, 触发备注: {4} <br>
"
,
(
i
+
1
),
childJob
Ids
.
length
,
childJobIds
[
i
],
(
triggerChildResult
.
getCode
()==
ReturnT
.
SUCCESS_CODE
?
"成功"
:
"失败"
)
,
triggerChildResult
.
getMsg
());
}
else
{
c
hildTriggerMsg
+=
MessageFormat
.
format
(
"<br> {0}/{1} 触发子任务失败, 子任务Key格式错误, 子任务Key: {2}
"
,
(
i
+
1
),
childJob
Keys
.
length
,
childJobKey
s
[
i
]);
c
allbackMsg
+=
MessageFormat
.
format
(
" {0}/{1} [任务ID={2}], 触发失败, 触发备注: 任务ID格式错误 <br>
"
,
(
i
+
1
),
childJob
Ids
.
length
,
childJobId
s
[
i
]);
}
}
}
}
else
if
(
IJobHandler
.
FAIL_RETRY
.
getCode
()
==
handleCallbackParam
.
getExecuteResult
().
getCode
()){
ReturnT
<
String
>
retryTriggerResult
=
xxlJobService
.
triggerJob
(
log
.
getJobId
());
callbackMsg
=
"<br><br><span style=\"color:#F39C12;\" > >>>>>>>>>>>执行失败重试<<<<<<<<<<< </span><br>"
;
callbackMsg
+=
MessageFormat
.
format
(
"触发{0}, 触发备注: {1}"
,
(
retryTriggerResult
.
getCode
()==
ReturnT
.
SUCCESS_CODE
?
"成功"
:
"失败"
),
retryTriggerResult
.
getMsg
());
}
// handle msg
...
...
@@ -90,8 +98,8 @@ public class AdminBizImpl implements AdminBiz {
if
(
handleCallbackParam
.
getExecuteResult
().
getMsg
()
!=
null
)
{
handleMsg
.
append
(
handleCallbackParam
.
getExecuteResult
().
getMsg
());
}
if
(
c
hildTriggerMsg
!=
null
)
{
handleMsg
.
append
(
"<br>子任务触发备注:"
).
append
(
childTrigger
Msg
);
if
(
c
allbackMsg
!=
null
)
{
handleMsg
.
append
(
callback
Msg
);
}
// success, save log
...
...
xxl-job-admin/src/main/java/com/xxl/job/admin/service/impl/XxlJobServiceImpl.java
浏览文件 @
8ed4d055
...
...
@@ -13,10 +13,10 @@ import com.xxl.job.admin.service.XxlJobService;
import
com.xxl.job.core.biz.model.ReturnT
;
import
com.xxl.job.core.enums.ExecutorBlockStrategyEnum
;
import
com.xxl.job.core.glue.GlueTypeEnum
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.commons.lang.StringUtils
;
import
org.apache.commons.lang.time.DateUtils
;
import
org.apache.commons.lang.time.FastDateFormat
;
import
org.apache.commons.collections
4
.CollectionUtils
;
import
org.apache.commons.lang
3
.StringUtils
;
import
org.apache.commons.lang
3
.time.DateUtils
;
import
org.apache.commons.lang
3
.time.FastDateFormat
;
import
org.quartz.CronExpression
;
import
org.quartz.SchedulerException
;
import
org.slf4j.Logger
;
...
...
@@ -103,19 +103,20 @@ public class XxlJobServiceImpl implements XxlJobService {
jobInfo
.
setGlueSource
(
jobInfo
.
getGlueSource
().
replaceAll
(
"\r"
,
""
));
}
// childJobKey valid
if
(
StringUtils
.
isNotBlank
(
jobInfo
.
getChildJobKey
()))
{
String
[]
childJobKeys
=
jobInfo
.
getChildJobKey
().
split
(
","
);
for
(
String
childJobKeyItem:
childJobKeys
)
{
String
[]
childJobKeyArr
=
childJobKeyItem
.
split
(
"_"
);
if
(
childJobKeyArr
.
length
!=
2
)
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务Key({0})格式错误"
,
childJobKeyItem
));
}
XxlJobInfo
childJobInfo
=
xxlJobInfoDao
.
loadById
(
Integer
.
valueOf
(
childJobKeyArr
[
1
]));
// ChildJobId valid
if
(
StringUtils
.
isNotBlank
(
jobInfo
.
getChildJobId
()))
{
String
[]
childJobIds
=
StringUtils
.
split
(
jobInfo
.
getChildJobId
(),
","
);
for
(
String
childJobIdItem:
childJobIds
)
{
if
(
StringUtils
.
isNotBlank
(
childJobIdItem
)
&&
StringUtils
.
isNumeric
(
childJobIdItem
))
{
XxlJobInfo
childJobInfo
=
xxlJobInfoDao
.
loadById
(
Integer
.
valueOf
(
childJobIdItem
));
if
(
childJobInfo
==
null
)
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务Key({0})无效"
,
childJobKeyItem
));
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务ID({0})无效"
,
childJobIdItem
));
}
}
else
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务ID({0})格式错误"
,
childJobIdItem
));
}
}
jobInfo
.
setChildJobId
(
StringUtils
.
join
(
childJobIds
,
","
));
}
// add in db
...
...
@@ -166,19 +167,24 @@ public class XxlJobServiceImpl implements XxlJobService {
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
"失败处理策略非法"
);
}
// childJobKey valid
if
(
StringUtils
.
isNotBlank
(
jobInfo
.
getChildJobKey
()))
{
String
[]
childJobKeys
=
jobInfo
.
getChildJobKey
().
split
(
","
);
for
(
String
childJobKeyItem:
childJobKeys
)
{
String
[]
childJobKeyArr
=
childJobKeyItem
.
split
(
"_"
);
if
(
childJobKeyArr
.
length
!=
2
)
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务Key({0})格式错误"
,
childJobKeyItem
));
}
XxlJobInfo
childJobInfo
=
xxlJobInfoDao
.
loadById
(
Integer
.
valueOf
(
childJobKeyArr
[
1
]));
// ChildJobId valid
if
(
StringUtils
.
isNotBlank
(
jobInfo
.
getChildJobId
()))
{
String
[]
childJobIds
=
StringUtils
.
split
(
jobInfo
.
getChildJobId
(),
","
);
for
(
String
childJobIdItem:
childJobIds
)
{
if
(
StringUtils
.
isNotBlank
(
childJobIdItem
)
&&
StringUtils
.
isNumeric
(
childJobIdItem
))
{
XxlJobInfo
childJobInfo
=
xxlJobInfoDao
.
loadById
(
Integer
.
valueOf
(
childJobIdItem
));
if
(
childJobInfo
==
null
)
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务Key({0})无效"
,
childJobKeyItem
));
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务ID({0})无效"
,
childJobIdItem
));
}
// avoid cycle relate
if
(
childJobInfo
.
getId
()
==
jobInfo
.
getId
())
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务ID({0})不可与父任务重复"
,
childJobIdItem
));
}
}
else
{
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
MessageFormat
.
format
(
"子任务ID({0})格式错误"
,
childJobIdItem
));
}
}
jobInfo
.
setChildJobId
(
StringUtils
.
join
(
childJobIds
,
","
));
}
// stage job info
...
...
@@ -197,7 +203,7 @@ public class XxlJobServiceImpl implements XxlJobService {
exists_jobInfo
.
setExecutorParam
(
jobInfo
.
getExecutorParam
());
exists_jobInfo
.
setExecutorBlockStrategy
(
jobInfo
.
getExecutorBlockStrategy
());
exists_jobInfo
.
setExecutorFailStrategy
(
jobInfo
.
getExecutorFailStrategy
());
exists_jobInfo
.
setChildJob
Key
(
jobInfo
.
getChildJobKey
());
exists_jobInfo
.
setChildJob
Id
(
jobInfo
.
getChildJobId
());
xxlJobInfoDao
.
update
(
exists_jobInfo
);
// fresh quartz
...
...
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobInfoMapper.xml
浏览文件 @
8ed4d055
...
...
@@ -27,7 +27,7 @@
<result
column=
"glue_remark"
property=
"glueRemark"
/>
<result
column=
"glue_updatetime"
property=
"glueUpdatetime"
/>
<result
column=
"child_job
key"
property=
"childJobKey
"
/>
<result
column=
"child_job
id"
property=
"childJobId
"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
...
...
@@ -48,7 +48,7 @@
t.glue_source,
t.glue_remark,
t.glue_updatetime,
t.child_job
key
t.child_job
id
</sql>
<select
id=
"pageList"
parameterType=
"java.util.HashMap"
resultMap=
"XxlJobInfo"
>
...
...
@@ -97,7 +97,7 @@
glue_source,
glue_remark,
glue_updatetime,
child_job
key
child_job
id
) VALUES (
#{jobGroup},
#{jobCron},
...
...
@@ -115,7 +115,7 @@
#{glueSource},
#{glueRemark},
NOW(),
#{childJob
Key
}
#{childJob
Id
}
);
<!--<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
...
...
@@ -146,7 +146,7 @@
glue_source = #{glueSource},
glue_remark = #{glueRemark},
glue_updatetime = #{glueUpdatetime},
child_job
key = #{childJobKey
}
child_job
id = #{childJobId
}
WHERE id = #{id}
</update>
...
...
xxl-job-admin/src/main/resources/spring/applicationcontext-base.xml
浏览文件 @
8ed4d055
...
...
@@ -3,9 +3,9 @@
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:context=
"http://www.springframework.org/schema/context"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans
-3.0
.xsd
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context
-3.0
.xsd"
>
http://www.springframework.org/schema/context/spring-context.xsd"
>
<context:component-scan
base-package=
"com.xxl.job.admin.service, com.xxl.job.admin.dao"
/>
...
...
xxl-job-admin/src/main/resources/spring/applicationcontext-xxl-job-admin.xml
浏览文件 @
8ed4d055
...
...
@@ -3,9 +3,9 @@
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx=
"http://www.springframework.org/schema/tx"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans
-3.0
.xsd
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx
-3.0
.xsd"
>
http://www.springframework.org/schema/tx/spring-tx.xsd"
>
<bean
id=
"propertyConfigurer"
class=
"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
>
...
...
xxl-job-admin/src/main/resources/spring/springmvc-context.xml
浏览文件 @
8ed4d055
...
...
@@ -4,11 +4,11 @@
xmlns:mvc=
"http://www.springframework.org/schema/mvc"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans
-3.0.xsd
http://www.springframework.org/schema/beans/spring-beans
.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context
-3.0
.xsd
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc
-3.0
.xsd"
>
http://www.springframework.org/schema/mvc/spring-mvc.xsd"
>
<mvc:annotation-driven
/>
<context:component-scan
base-package=
"com.xxl.job.admin.controller"
/>
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/jobgroup/jobgroup.index.ftl
浏览文件 @
8ed4d055
...
...
@@ -53,7 +53,20 @@
<td>
${group.appName}
</td>
<td>
${group.title}
</td>
<td><
#
if
group
.
addressType=
=0
>
自动注册
<
#
else
>
手动录入
</
#
if></td>
<td><
#
if
group
.
registryList
?
exists
><
#
list
group
.
registryList
as
item
><span
class=
"badge bg-green"
>
${item}
</span><br></
#
list></
#
if></td>
<td>
<
#
if
group
.
registryList
?
exists
>
<
#
list
group
.
registryList
as
item
>
<span
class=
"badge bg-green"
title=
"${item}"
>
<
#
if
item
?
length
gt
35
>
${item?substring(0, 35)}...
<
#
else
>
${item}
</
#
if>
</span>
<br>
</
#
list>
</
#
if>
</td>
<td>
<button
class=
"btn btn-warning btn-xs update"
id=
"${group.id}"
...
...
@@ -107,7 +120,9 @@
</div>
<div
class=
"form-group"
>
<label
for=
"lastname"
class=
"col-sm-2 control-label"
>
机器地址
<font
color=
"red"
>
*
</font></label>
<div
class=
"col-sm-10"
><input
type=
"text"
class=
"form-control"
name=
"addressList"
placeholder=
"请输入执行器地址列表,多地址逗号分隔"
maxlength=
"200"
readonly=
"readonly"
></div>
<div
class=
"col-sm-10"
>
<textarea
class=
"textarea"
name=
"addressList"
maxlength=
"512"
placeholder=
"请输入执行器地址列表,多地址逗号分隔"
readonly=
"readonly"
style=
"background-color:#eee; width: 100%; height: 100px; font-size: 14px; line-height: 10px; border: 1px solid #dddddd; padding: 10px;"
></textarea>
</div>
</div>
<hr>
<div
class=
"form-group"
>
...
...
@@ -153,7 +168,9 @@
</div>
<div
class=
"form-group"
>
<label
for=
"lastname"
class=
"col-sm-2 control-label"
>
机器地址
<font
color=
"red"
>
*
</font></label>
<div
class=
"col-sm-10"
><input
type=
"text"
class=
"form-control"
name=
"addressList"
placeholder=
"请输入执行器地址列表,多地址逗号分隔"
maxlength=
"200"
readonly=
"readonly"
></div>
<div
class=
"col-sm-10"
>
<textarea
class=
"textarea"
name=
"addressList"
maxlength=
"512"
placeholder=
"请输入执行器地址列表,多地址逗号分隔"
readonly=
"readonly"
style=
"background-color:#eee; width: 100%; height: 100px; font-size: 14px; line-height: 10px; border: 1px solid #dddddd; padding: 10px;"
></textarea>
</div>
</div>
<hr>
<div
class=
"form-group"
>
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl
浏览文件 @
8ed4d055
...
...
@@ -63,12 +63,11 @@
<h3
class=
"box-title"
>
调度列表
</h3>
</div>
<div
class=
"box-body"
>
<table
id=
"job_list"
class=
"table table-bordered table-striped"
>
<table
id=
"job_list"
class=
"table table-bordered table-striped"
width=
"100%"
>
<thead>
<tr>
<th
name=
"id"
>
id
</th>
<th
name=
"id"
>
任务ID
</th>
<th
name=
"jobGroup"
>
jobGroup
</th>
<th
name=
"childJobKey"
>
JobKey
</th>
<th
name=
"jobDesc"
>
描述
</th>
<th
name=
"glueType"
>
运行模式
</th>
<th
name=
"executorParam"
>
任务参数
</th>
...
...
@@ -143,9 +142,9 @@
</div>
<div
class=
"form-group"
>
<label
for=
"firstname"
class=
"col-sm-2 control-label"
>
执行参数
<font
color=
"black"
>
*
</font></label>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"executorParam"
placeholder=
"请输入“执行参数”"
maxlength=
"
100
"
></div>
<label
for=
"lastname"
class=
"col-sm-2 control-label"
>
子任务
Key
<font
color=
"black"
>
*
</font></label>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"childJob
Key"
placeholder=
"请输入子任务的任务Key
,如存在多个逗号分隔"
maxlength=
"100"
></div>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"executorParam"
placeholder=
"请输入“执行参数”"
maxlength=
"
512
"
></div>
<label
for=
"lastname"
class=
"col-sm-2 control-label"
>
子任务
ID
<font
color=
"black"
>
*
</font></label>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"childJob
Id"
placeholder=
"请输入子任务的任务ID
,如存在多个逗号分隔"
maxlength=
"100"
></div>
</div>
<div
class=
"form-group"
>
<label
for=
"firstname"
class=
"col-sm-2 control-label"
>
阻塞处理策略
<font
color=
"red"
>
*
</font></label>
...
...
@@ -192,7 +191,7 @@ import com.xxl.job.core.handler.IJobHandler;
public class DemoGlueJobHandler extends IJobHandler {
@Override
public ReturnT
<String>
execute(String
... params
) throws Exception {
public ReturnT
<String>
execute(String
param
) throws Exception {
XxlJobLogger.log("XXL-JOB, Hello World.");
return ReturnT.SUCCESS;
}
...
...
@@ -204,12 +203,15 @@ public class DemoGlueJobHandler extends IJobHandler {
echo "xxl-job: hello shell"
echo "脚本位置:$0"
echo "参数数量:$#"
echo "任务参数:$1"
echo "分片序号 = $2"
echo "分片总数 = $3"
<
#
--echo
"参数数量:$#"
for
param
in
$*
do
echo
"参数
:
$
param
"
sleep
1s
done
done
--
>
echo "Good bye!"
exit 0
...
...
@@ -221,13 +223,18 @@ import time
import sys
print "xxl-job: hello python"
print "脚本文件:", sys.argv[0]
for i in range(1, len(sys.argv)):
print "任务参数:", sys.argv[1]
print "分片序号:", sys.argv[2]
print "分片总数:", sys.argv[3]
<
#
--for
i
in
range
(
1
,
len
(
sys
.
argv
))
:
time
.
sleep
(
1
)
print "参数", i, sys.argv[i]
print
"参数",
i
,
sys
.
argv
[
i
]
--
>
print "Good bye!"
exit(0)
<
#
--
exit(0)
<
#
--
import
logging
logging
.
basicConfig
(
level=
logging.DEBUG)
logging
.
info
("脚本文件:"
+
sys
.
argv
[
0
])
...
...
@@ -240,9 +247,12 @@ console.log("xxl-job: hello nodejs")
var arguments = process.argv
console.log("脚本文件: " + arguments[1])
for (var i = 2; i
<
arguments
.
length
;
i
++){
console.log("任务参数: " + arguments[2])
console.log("分片序号: " + arguments[3])
console.log("分片总数: " + arguments[4])
<
#
--for
(
var
i =
2;
i
<
arguments
.
length
;
i
++){
console
.
log
("参数
%
s =
%s",
(
i-1
),
arguments
[
i
]);
}
}
--
>
console.log("Good bye!")
process.exit(0)
...
...
@@ -300,9 +310,9 @@ process.exit(0)
</div>
<div
class=
"form-group"
>
<label
for=
"firstname"
class=
"col-sm-2 control-label"
>
执行参数
<font
color=
"black"
>
*
</font></label>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"executorParam"
placeholder=
"请输入“执行参数”"
maxlength=
"
100
"
></div>
<label
for=
"lastname"
class=
"col-sm-2 control-label"
>
子任务
Key
<font
color=
"black"
>
*
</font></label>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"childJob
Key"
placeholder=
"请输入子任务的任务Key
,如存在多个逗号分隔"
maxlength=
"100"
></div>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"executorParam"
placeholder=
"请输入“执行参数”"
maxlength=
"
512
"
></div>
<label
for=
"lastname"
class=
"col-sm-2 control-label"
>
子任务
ID
<font
color=
"black"
>
*
</font></label>
<div
class=
"col-sm-4"
><input
type=
"text"
class=
"form-control"
name=
"childJob
Id"
placeholder=
"请输入子任务的任务ID
,如存在多个逗号分隔"
maxlength=
"100"
></div>
</div>
<div
class=
"form-group"
>
<label
for=
"firstname"
class=
"col-sm-2 control-label"
>
阻塞处理策略
<font
color=
"red"
>
*
</font></label>
...
...
xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/joblog.index.ftl
浏览文件 @
8ed4d055
...
...
@@ -90,10 +90,8 @@
<table
id=
"joblog_list"
class=
"table table-bordered table-striped display"
width=
"100%"
>
<thead>
<tr>
<th
name=
"id"
>
id
</th>
<th
name=
"jobGroup"
>
执行器ID
</th>
<th
name=
"jobId"
>
任务ID
</th>
<th
name=
"
JobKey"
>
JobKey
</th>
<th
name=
"
jobGroup"
>
执行器ID
</th>
<
#
--
<
th
name=
"executorAddress"
>
执行器地址
</th>
<th
name=
"glueType"
>
运行模式
</th>
<th
name=
"executorParam"
>
任务参数
</th>
-->
...
...
xxl-job-admin/src/main/webapp/static/js/common.1.js
浏览文件 @
8ed4d055
...
...
@@ -7,14 +7,18 @@ $(function(){
$
.
post
(
base_url
+
"/logout"
,
function
(
data
,
status
)
{
if
(
data
.
code
==
"200"
)
{
layer
.
open
({
layer
.
msg
(
'注销成功'
);
setTimeout
(
function
(){
window
.
location
.
href
=
base_url
+
"/"
;
},
500
);
/*layer.open({
title: '系统提示',
content: '注销成功',
icon: '1',
end: function(layero, index){
window.location.href = base_url + "/";
}
});
});
*/
}
else
{
layer
.
open
({
title
:
'系统提示'
,
...
...
xxl-job-admin/src/main/webapp/static/js/jobgroup.index.1.js
浏览文件 @
8ed4d055
...
...
@@ -122,11 +122,13 @@ $(function() {
// 注册方式,切换
$
(
"#addModal input[name=addressType], #updateModal input[name=addressType]"
).
click
(
function
(){
var
addressType
=
$
(
this
).
val
();
var
$addressList
=
$
(
this
).
parents
(
"form"
).
find
(
"
input
[name=addressList]"
);
var
$addressList
=
$
(
this
).
parents
(
"form"
).
find
(
"
textarea
[name=addressList]"
);
if
(
addressType
==
0
)
{
$addressList
.
val
(
""
);
$addressList
.
css
(
"background-color"
,
"#eee"
);
// 自动注册
$addressList
.
attr
(
"readonly"
,
"readonly"
);
$addressList
.
val
(
""
);
}
else
{
$addressList
.
css
(
"background-color"
,
"white"
);
$addressList
.
removeAttr
(
"readonly"
);
}
});
...
...
@@ -144,7 +146,7 @@ $(function() {
//$("#updateModal .form input[name='addressType'][value='"+ addressType +"']").attr('checked', 'true');
$
(
"#updateModal .form input[name='addressType'][value='"
+
addressType
+
"']"
).
click
();
// 机器地址
$
(
"#updateModal .form
input
[name='addressList']"
).
val
(
$
(
this
).
attr
(
"addressList"
));
$
(
"#updateModal .form
textarea
[name='addressList']"
).
val
(
$
(
this
).
attr
(
"addressList"
));
$
(
'#updateModal'
).
modal
({
backdrop
:
false
,
keyboard
:
false
}).
modal
(
'show'
);
});
...
...
xxl-job-admin/src/main/webapp/static/js/jobinfo.index.1.js
浏览文件 @
8ed4d055
...
...
@@ -20,7 +20,7 @@ $(function() {
"ordering"
:
false
,
//"scrollX": true, // X轴滚动条,取消自适应
"columns"
:
[
{
"data"
:
'id'
,
"bSortable"
:
false
,
"visible"
:
fals
e
},
{
"data"
:
'id'
,
"bSortable"
:
false
,
"visible"
:
tru
e
},
{
"data"
:
'jobGroup'
,
"visible"
:
false
,
...
...
@@ -34,15 +34,6 @@ $(function() {
return
data
;
}
},
{
"data"
:
'childJobKey'
,
"width"
:
'10%'
,
"visible"
:
true
,
"render"
:
function
(
data
,
type
,
row
)
{
var
jobKey
=
row
.
jobGroup
+
"_"
+
row
.
id
;
return
jobKey
;
}
},
{
"data"
:
'jobDesc'
,
"visible"
:
true
,
"width"
:
'20%'
},
{
"data"
:
'glueType'
,
...
...
@@ -372,7 +363,7 @@ $(function() {
$
(
'#updateModal .form select[name=executorRouteStrategy] option[value='
+
row
.
executorRouteStrategy
+
']'
).
prop
(
'selected'
,
true
);
$
(
"#updateModal .form input[name='executorHandler']"
).
val
(
row
.
executorHandler
);
$
(
"#updateModal .form input[name='executorParam']"
).
val
(
row
.
executorParam
);
$
(
"#updateModal .form input[name='childJob
Key']"
).
val
(
row
.
childJobKey
);
$
(
"#updateModal .form input[name='childJob
Id']"
).
val
(
row
.
childJobId
);
$
(
'#updateModal .form select[name=executorBlockStrategy] option[value='
+
row
.
executorBlockStrategy
+
']'
).
prop
(
'selected'
,
true
);
$
(
'#updateModal .form select[name=executorFailStrategy] option[value='
+
row
.
executorFailStrategy
+
']'
).
prop
(
'selected'
,
true
);
$
(
'#updateModal .form select[name=glueType] option[value='
+
row
.
glueType
+
']'
).
prop
(
'selected'
,
true
);
...
...
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js
浏览文件 @
8ed4d055
...
...
@@ -89,15 +89,10 @@ $(function() {
"ordering"
:
false
,
//"scrollX": false,
"columns"
:
[
{
"data"
:
'id'
,
"bSortable"
:
false
,
"visible"
:
false
},
{
"data"
:
'jobGroup'
,
"visible"
:
false
},
{
"data"
:
'jobId'
,
"visible"
:
false
},
{
"data"
:
'
JobKey
'
,
"data"
:
'
jobId
'
,
"visible"
:
true
,
"render"
:
function
(
data
,
type
,
row
)
{
var
jobKey
=
row
.
jobGroup
+
"_"
+
row
.
jobId
;
var
glueTypeTitle
=
row
.
glueType
;
if
(
'GLUE_GROOVY'
==
row
.
glueType
)
{
glueTypeTitle
=
"GLUE模式(Java)"
;
...
...
@@ -116,27 +111,10 @@ $(function() {
temp
+=
'<br>运行模式:'
+
glueTypeTitle
;
temp
+=
'<br>任务参数:'
+
row
.
executorParam
;
return
'<a class="logTips" href="javascript:;" >'
+
jobKey
+
'<span style="display:none;">'
+
temp
+
'</span></a>'
;
return
'<a class="logTips" href="javascript:;" >'
+
row
.
jobId
+
'<span style="display:none;">'
+
temp
+
'</span></a>'
;
}
},
// { "data": 'executorAddress', "visible" : true},
// {
// "data": 'glueType',
// "visible" : true,
// "render": function ( data, type, row ) {
// if ('GLUE_GROOVY'==row.glueType) {
// return "GLUE模式(Java)";
// } else if ('GLUE_SHELL'==row.glueType) {
// return "GLUE模式(Shell)";
// } else if ('GLUE_PYTHON'==row.glueType) {
// return "GLUE模式(Python)";
// } else if ('BEAN'==row.glueType) {
// return "BEAN模式:" + row.executorHandler;
// }
// return row.executorHandler;
// }
// },
// { "data": 'executorParam', "visible" : true},
{
"data"
:
'jobGroup'
,
"visible"
:
false
},
{
"data"
:
'triggerTime'
,
"render"
:
function
(
data
,
type
,
row
)
{
...
...
@@ -146,9 +124,16 @@ $(function() {
{
"data"
:
'triggerCode'
,
"render"
:
function
(
data
,
type
,
row
)
{
return
(
data
==
200
)?
'<span style="color: green">成功</span>'
:(
data
==
500
)?
'<span style="color: red">失败</span>'
:(
data
==
0
)?
''
:
data
;
var
html
=
data
;
if
(
data
==
200
)
{
html
=
'<span style="color: green">成功</span>'
;
}
else
if
(
data
==
500
)
{
html
=
'<span style="color: red">失败</span>'
;
}
else
if
(
data
==
0
)
{
html
=
''
;
}
return
html
;
}
},
{
"data"
:
'triggerMsg'
,
...
...
@@ -165,7 +150,17 @@ $(function() {
{
"data"
:
'handleCode'
,
"render"
:
function
(
data
,
type
,
row
)
{
return
(
data
==
200
)?
'<span style="color: green">成功</span>'
:(
data
==
500
)?
'<span style="color: red">失败</span>'
:(
data
==
0
)?
''
:
data
;
var
html
=
data
;
if
(
data
==
200
)
{
html
=
'<span style="color: green">成功</span>'
;
}
else
if
(
data
==
500
)
{
html
=
'<span style="color: red">失败</span>'
;
}
else
if
(
data
==
501
)
{
html
=
'<span style="color: red">失败重试</span>'
;
}
else
if
(
data
==
0
)
{
html
=
''
;
}
return
html
;
}
},
{
...
...
xxl-job-admin/src/main/webapp/static/js/login.1.js
浏览文件 @
8ed4d055
...
...
@@ -48,14 +48,18 @@ $(function(){
submitHandler
:
function
(
form
)
{
$
.
post
(
base_url
+
"/login"
,
$
(
"#loginForm"
).
serialize
(),
function
(
data
,
status
)
{
if
(
data
.
code
==
"200"
)
{
layer
.
open
({
layer
.
msg
(
'登录成功'
);
setTimeout
(
function
(){
window
.
location
.
href
=
base_url
;
},
500
);
/*layer.open({
title: '系统提示',
content: '登录成功',
icon: '1',
end: function(layero, index){
window.location.href = base_url;
}
});
});
*/
}
else
{
layer
.
open
({
title
:
'系统提示'
,
...
...
xxl-job-admin/src/test/java/com/xxl/job/admin/controller/AbstractSpringMvcTest.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
controller
;
import
org.junit.Before
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.test.context.ContextConfiguration
;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner
;
import
org.springframework.test.context.web.WebAppConfiguration
;
import
org.springframework.test.web.servlet.MockMvc
;
import
org.springframework.test.web.servlet.setup.MockMvcBuilders
;
import
org.springframework.web.context.WebApplicationContext
;
@WebAppConfiguration
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@ContextConfiguration
(
locations
=
{
"classpath*:spring/*.xml"
})
public
class
AbstractSpringMvcTest
{
@Autowired
private
WebApplicationContext
applicationContext
;
protected
MockMvc
mockMvc
;
@Before
public
void
setup
()
{
this
.
mockMvc
=
MockMvcBuilders
.
webAppContextSetup
(
this
.
applicationContext
).
build
();
}
}
xxl-job-admin/src/test/java/com/xxl/job/admin/controller/JobInfoControllerTest.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
controller
;
import
com.xxl.job.admin.controller.interceptor.PermissionInterceptor
;
import
com.xxl.job.admin.core.util.PropertiesUtil
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.springframework.http.MediaType
;
import
org.springframework.test.web.servlet.MvcResult
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
javax.servlet.http.Cookie
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
request
.
MockMvcRequestBuilders
.
post
;
public
class
JobInfoControllerTest
extends
AbstractSpringMvcTest
{
private
Cookie
cookie
;
@Before
public
void
login
()
throws
Exception
{
MvcResult
ret
=
mockMvc
.
perform
(
post
(
"/login"
)
.
contentType
(
MediaType
.
APPLICATION_FORM_URLENCODED
)
.
param
(
"userName"
,
PropertiesUtil
.
getString
(
"xxl.job.login.username"
))
.
param
(
"password"
,
PropertiesUtil
.
getString
(
"xxl.job.login.password"
))
).
andReturn
();
cookie
=
ret
.
getResponse
().
getCookie
(
PermissionInterceptor
.
LOGIN_IDENTITY_KEY
);
}
@Test
public
void
testAdd
()
throws
Exception
{
MultiValueMap
<
String
,
String
>
parameters
=
new
LinkedMultiValueMap
<
String
,
String
>();
parameters
.
add
(
"jobGroup"
,
"1"
);
MvcResult
ret
=
mockMvc
.
perform
(
post
(
"/jobinfo/pageList"
)
.
contentType
(
MediaType
.
APPLICATION_FORM_URLENCODED
)
//.content(paramsJson)
.
params
(
parameters
)
.
cookie
(
cookie
)
).
andReturn
();
System
.
out
.
println
(
ret
.
getResponse
().
getContentAsString
());
}
}
xxl-job-admin/src/test/java/com/xxl/job/
dao/impl
/XxlJobGroupDaoTest.java
→
xxl-job-admin/src/test/java/com/xxl/job/
admin/dao
/XxlJobGroupDaoTest.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
dao
.
impl
;
package
com
.
xxl
.
job
.
admin
.
dao
;
import
com.xxl.job.admin.core.model.XxlJobGroup
;
import
com.xxl.job.admin.dao.XxlJobGroupDao
;
...
...
xxl-job-admin/src/test/java/com/xxl/job/
dao/impl/XxlJobInf
oTest.java
→
xxl-job-admin/src/test/java/com/xxl/job/
admin/dao/XxlJobInfoDa
oTest.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
dao
.
impl
;
package
com
.
xxl
.
job
.
admin
.
dao
;
import
com.xxl.job.admin.core.model.XxlJobInfo
;
import
com.xxl.job.admin.dao.XxlJobInfoDao
;
...
...
@@ -13,7 +13,7 @@ import java.util.List;
@RunWith
(
SpringJUnit4ClassRunner
.
class
)
@ContextConfiguration
(
locations
=
"classpath*:spring/applicationcontext-*.xml"
)
public
class
XxlJobInfo
Test
{
public
class
XxlJobInfo
DaoTest
{
@Resource
private
XxlJobInfoDao
xxlJobInfoDao
;
...
...
@@ -45,7 +45,7 @@ public class XxlJobInfoTest {
info
.
setGlueType
(
"setGlueType"
);
info
.
setGlueSource
(
"setGlueSource"
);
info
.
setGlueRemark
(
"setGlueRemark"
);
info
.
setChildJob
Key
(
"setChildJobKey"
);
info
.
setChildJob
Id
(
"1"
);
int
count
=
xxlJobInfoDao
.
save
(
info
);
...
...
@@ -63,7 +63,7 @@ public class XxlJobInfoTest {
info2
.
setGlueSource
(
"setGlueSource2"
);
info2
.
setGlueRemark
(
"setGlueRemark2"
);
info2
.
setGlueUpdatetime
(
new
Date
());
info2
.
setChildJob
Key
(
"setChildJobKey2"
);
info2
.
setChildJob
Id
(
"1"
);
int
item2
=
xxlJobInfoDao
.
update
(
info2
);
...
...
xxl-job-admin/src/test/java/com/xxl/job/
dao/impl
/XxlJobLogDaoTest.java
→
xxl-job-admin/src/test/java/com/xxl/job/
admin/dao
/XxlJobLogDaoTest.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
dao
.
impl
;
package
com
.
xxl
.
job
.
admin
.
dao
;
import
com.xxl.job.admin.core.model.XxlJobLog
;
import
com.xxl.job.admin.dao.XxlJobLogDao
;
import
org.apache.commons.lang.time.DateUtils
;
import
org.apache.commons.lang
3
.time.DateUtils
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.test.context.ContextConfiguration
;
...
...
xxl-job-admin/src/test/java/com/xxl/job/
dao/impl
/XxlJobLogGlueDaoTest.java
→
xxl-job-admin/src/test/java/com/xxl/job/
admin/dao
/XxlJobLogGlueDaoTest.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
dao
.
impl
;
package
com
.
xxl
.
job
.
admin
.
dao
;
import
com.xxl.job.admin.core.model.XxlJobLogGlue
;
import
com.xxl.job.admin.dao.XxlJobLogGlueDao
;
...
...
xxl-job-admin/src/test/java/com/xxl/job/
dao/impl
/XxlJobRegistryDaoTest.java
→
xxl-job-admin/src/test/java/com/xxl/job/
admin/dao
/XxlJobRegistryDaoTest.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
dao
.
impl
;
package
com
.
xxl
.
job
.
admin
.
dao
;
import
com.xxl.job.admin.core.model.XxlJobRegistry
;
import
com.xxl.job.admin.dao.XxlJobRegistryDao
;
...
...
xxl-job-admin/src/test/java/com/xxl/job/admin/util/MailUtilTest.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
util
;
import
com.xxl.job.admin.core.util.MailUtil
;
import
org.junit.Test
;
import
java.text.MessageFormat
;
/**
* email util test
*
* @author xuxueli 2017-12-22 17:16:23
*/
public
class
MailUtilTest
{
@Test
public
void
registryTest
()
throws
Exception
{
String
mailBodyTemplate
=
"<h5>监控告警明细:</span>"
+
"<table border=\"1\" cellpadding=\"3\" style=\"border-collapse:collapse; width:80%;\" >\n"
+
" <thead style=\"font-weight: bold;color: #ffffff;background-color: #ff8c00;\" >"
+
" <tr>\n"
+
" <td>执行器</td>\n"
+
" <td>任务ID</td>\n"
+
" <td>任务描述</td>\n"
+
" <td>告警类型</td>\n"
+
" </tr>\n"
+
" <thead/>\n"
+
" <tbody>\n"
+
" <tr>\n"
+
" <td>{0}</td>\n"
+
" <td>{1}</td>\n"
+
" <td>{2}</td>\n"
+
" <td>调度失败</td>\n"
+
" </tr>\n"
+
" <tbody>\n"
+
"</table>"
;
String
title
=
"调度中心监控报警"
;
String
content
=
MessageFormat
.
format
(
mailBodyTemplate
,
"执行器A"
,
"01"
,
"任务A1"
);
boolean
ret
=
MailUtil
.
sendMail
(
"931591021@qq.com"
,
title
,
content
);
System
.
out
.
println
(
ret
);
}
}
xxl-job-admin/src/test/java/com/xxl/job/admin/util/PropertiesUtilTest.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
admin
.
util
;
import
com.xxl.job.admin.core.util.PropertiesUtil
;
import
org.junit.Test
;
/**
* prop util test
*
* @author xuxueli 2017-12-25 15:17:36
*/
public
class
PropertiesUtilTest
{
@Test
public
void
registryTest
()
throws
Exception
{
System
.
out
.
println
(
PropertiesUtil
.
getString
(
"xxl.job.login.username"
));
}
}
xxl-job-admin/src/test/java/com/xxl/job/
dao/impl
/AdminBizTest.java
→
xxl-job-admin/src/test/java/com/xxl/job/
adminbiz
/AdminBizTest.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
dao
.
impl
;
package
com
.
xxl
.
job
.
adminbiz
;
import
com.xxl.job.core.biz.AdminBiz
;
import
com.xxl.job.core.biz.model.RegistryParam
;
...
...
xxl-job-core/pom.xml
浏览文件 @
8ed4d055
...
...
@@ -49,9 +49,9 @@
<!-- jackson -->
<dependency>
<groupId>
org.codehaus.jackson
</groupId>
<artifactId>
jackson-
mapper-asl
</artifactId>
<version>
${jackson
-mapper-asl
.version}
</version>
<groupId>
com.fasterxml.jackson.core
</groupId>
<artifactId>
jackson-
databind
</artifactId>
<version>
${jackson.version}
</version>
</dependency>
<!-- httpclient -->
...
...
xxl-job-core/src/main/java/com/xxl/job/core/biz/impl/ExecutorBizImpl.java
浏览文件 @
8ed4d055
...
...
@@ -59,7 +59,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
@Override
public
ReturnT
<
LogResult
>
log
(
long
logDateTim
,
int
logId
,
int
fromLineNum
)
{
// log filename: yyyy-MM-dd/9999.log
// log filename:
logPath/
yyyy-MM-dd/9999.log
String
logFileName
=
XxlJobFileAppender
.
makeLogFileName
(
new
Date
(
logDateTim
),
logId
);
LogResult
logResult
=
XxlJobFileAppender
.
readLog
(
logFileName
,
fromLineNum
);
...
...
@@ -74,7 +74,8 @@ public class ExecutorBizImpl implements ExecutorBiz {
String
removeOldReason
=
null
;
// valid:jobHandler + jobThread
if
(
GlueTypeEnum
.
BEAN
==
GlueTypeEnum
.
match
(
triggerParam
.
getGlueType
()))
{
GlueTypeEnum
glueTypeEnum
=
GlueTypeEnum
.
match
(
triggerParam
.
getGlueType
());
if
(
GlueTypeEnum
.
BEAN
==
glueTypeEnum
)
{
// new jobhandler
IJobHandler
newJobHandler
=
XxlJobExecutor
.
loadJobHandler
(
triggerParam
.
getExecutorHandler
());
...
...
@@ -96,7 +97,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
}
}
}
else
if
(
GlueTypeEnum
.
GLUE_GROOVY
==
GlueTypeEnum
.
match
(
triggerParam
.
getGlueType
())
)
{
}
else
if
(
GlueTypeEnum
.
GLUE_GROOVY
==
glueTypeEnum
)
{
// valid old jobThread
if
(
jobThread
!=
null
&&
...
...
@@ -119,9 +120,7 @@ public class ExecutorBizImpl implements ExecutorBiz {
return
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
e
.
getMessage
());
}
}
}
else
if
(
GlueTypeEnum
.
GLUE_SHELL
==
GlueTypeEnum
.
match
(
triggerParam
.
getGlueType
())
||
GlueTypeEnum
.
GLUE_PYTHON
==
GlueTypeEnum
.
match
(
triggerParam
.
getGlueType
())
||
GlueTypeEnum
.
GLUE_NODEJS
==
GlueTypeEnum
.
match
(
triggerParam
.
getGlueType
()))
{
}
else
if
(
glueTypeEnum
!=
null
&&
glueTypeEnum
.
isScript
())
{
// valid old jobThread
if
(
jobThread
!=
null
&&
...
...
xxl-job-core/src/main/java/com/xxl/job/core/executor/XxlJobExecutor.java
浏览文件 @
8ed4d055
...
...
@@ -72,14 +72,10 @@ public class XxlJobExecutor implements ApplicationContextAware {
initAdminBizList
(
adminAddresses
,
accessToken
);
// init executor-jobHandlerRepository
if
(
applicationContext
!=
null
)
{
initJobHandlerRepository
(
applicationContext
);
}
// init logpath
if
(
logPath
!=
null
&&
logPath
.
trim
().
length
()>
0
)
{
XxlJobFileAppender
.
logPath
=
logPath
;
}
XxlJobFileAppender
.
initLogPath
(
logPath
);
// init executor-server
initExecutorServer
(
port
,
ip
,
appName
,
accessToken
);
...
...
@@ -145,6 +141,10 @@ public class XxlJobExecutor implements ApplicationContextAware {
return
jobHandlerRepository
.
get
(
name
);
}
private
static
void
initJobHandlerRepository
(
ApplicationContext
applicationContext
){
if
(
applicationContext
==
null
)
{
return
;
}
// init job handler action
Map
<
String
,
Object
>
serviceBeanMap
=
applicationContext
.
getBeansWithAnnotation
(
JobHandler
.
class
);
...
...
xxl-job-core/src/main/java/com/xxl/job/core/glue/GlueTypeEnum.java
浏览文件 @
8ed4d055
...
...
@@ -5,20 +5,40 @@ package com.xxl.job.core.glue;
*/
public
enum
GlueTypeEnum
{
BEAN
(
"BEAN模式"
),
GLUE_GROOVY
(
"GLUE模式(Java)"
),
GLUE_SHELL
(
"GLUE模式(Shell)"
),
GLUE_PYTHON
(
"GLUE模式(Python)"
),
GLUE_NODEJS
(
"GLUE模式(Nodejs)"
);
BEAN
(
"BEAN模式"
,
false
,
null
,
null
),
GLUE_GROOVY
(
"GLUE模式(Java)"
,
false
,
null
,
null
),
GLUE_SHELL
(
"GLUE模式(Shell)"
,
true
,
"bash"
,
".sh"
),
GLUE_PYTHON
(
"GLUE模式(Python)"
,
true
,
"python"
,
".py"
),
GLUE_NODEJS
(
"GLUE模式(Nodejs)"
,
true
,
"node"
,
".js"
);
private
String
desc
;
private
GlueTypeEnum
(
String
desc
)
{
private
boolean
isScript
;
private
String
cmd
;
private
String
suffix
;
private
GlueTypeEnum
(
String
desc
,
boolean
isScript
,
String
cmd
,
String
suffix
)
{
this
.
desc
=
desc
;
this
.
isScript
=
isScript
;
this
.
cmd
=
cmd
;
this
.
suffix
=
suffix
;
}
public
String
getDesc
()
{
return
desc
;
}
public
boolean
isScript
()
{
return
isScript
;
}
public
String
getCmd
()
{
return
cmd
;
}
public
String
getSuffix
()
{
return
suffix
;
}
public
static
GlueTypeEnum
match
(
String
name
){
for
(
GlueTypeEnum
item:
GlueTypeEnum
.
values
())
{
if
(
item
.
name
().
equals
(
name
))
{
...
...
@@ -27,4 +47,5 @@ public enum GlueTypeEnum {
}
return
null
;
}
}
xxl-job-core/src/main/java/com/xxl/job/core/handler/IJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -3,17 +3,45 @@ package com.xxl.job.core.handler;
import
com.xxl.job.core.biz.model.ReturnT
;
/**
* remote job handler
* job handler
*
* @author xuxueli 2015-12-19 19:06:38
*/
public
abstract
class
IJobHandler
{
/** success */
public
static
final
ReturnT
<
String
>
SUCCESS
=
new
ReturnT
<
String
>(
200
,
null
);
/** fail */
public
static
final
ReturnT
<
String
>
FAIL
=
new
ReturnT
<
String
>(
500
,
null
);
/** fail retry */
public
static
final
ReturnT
<
String
>
FAIL_RETRY
=
new
ReturnT
<
String
>(
501
,
null
);
/**
* job handler
* @param params
* execute handler, invoked when executor receives a scheduling request
*
* @param param
* @return
* @throws Exception
*/
public
abstract
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
;
public
abstract
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
;
/**
* init handler, invoked when JobThread init
*/
public
void
init
()
{
// TODO
}
/**
* destroy handler, invoked when JobThread destroy
*/
public
void
destroy
()
{
// TODO
}
}
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/GlueJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -21,9 +21,9 @@ public class GlueJobHandler extends IJobHandler {
}
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
XxlJobLogger
.
log
(
"----------- glue.version:"
+
glueUpdatetime
+
" -----------"
);
return
jobHandler
.
execute
(
param
s
);
return
jobHandler
.
execute
(
param
);
}
}
xxl-job-core/src/main/java/com/xxl/job/core/handler/impl/ScriptJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -6,6 +6,7 @@ import com.xxl.job.core.handler.IJobHandler;
import
com.xxl.job.core.log.XxlJobFileAppender
;
import
com.xxl.job.core.log.XxlJobLogger
;
import
com.xxl.job.core.util.ScriptUtil
;
import
com.xxl.job.core.util.ShardingUtil
;
/**
* Created by xuxueli on 17/4/27.
...
...
@@ -29,32 +30,38 @@ public class ScriptJobHandler extends IJobHandler {
}
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
// cmd + script-file-name
String
cmd
=
"bash"
;
String
scriptFileName
=
null
;
if
(
GlueTypeEnum
.
GLUE_SHELL
==
glueType
)
{
cmd
=
"bash"
;
scriptFileName
=
XxlJobFileAppender
.
logPath
.
concat
(
"gluesource/"
).
concat
(
String
.
valueOf
(
jobId
)).
concat
(
"_"
).
concat
(
String
.
valueOf
(
glueUpdatetime
)).
concat
(
".sh"
);
}
else
if
(
GlueTypeEnum
.
GLUE_PYTHON
==
glueType
)
{
cmd
=
"python"
;
scriptFileName
=
XxlJobFileAppender
.
logPath
.
concat
(
"gluesource/"
).
concat
(
String
.
valueOf
(
jobId
)).
concat
(
"_"
).
concat
(
String
.
valueOf
(
glueUpdatetime
)).
concat
(
".py"
);
}
else
if
(
GlueTypeEnum
.
GLUE_NODEJS
==
glueType
)
{
cmd
=
"node"
;
scriptFileName
=
XxlJobFileAppender
.
logPath
.
concat
(
"gluesource/"
).
concat
(
String
.
valueOf
(
jobId
)).
concat
(
"_"
).
concat
(
String
.
valueOf
(
glueUpdatetime
)).
concat
(
".js"
);
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
if
(!
glueType
.
isScript
())
{
return
new
ReturnT
<
String
>(
IJobHandler
.
FAIL
.
getCode
(),
"glueType["
+
glueType
+
"] invalid."
);
}
// cmd
String
cmd
=
glueType
.
getCmd
();
// make script file
String
scriptFileName
=
XxlJobFileAppender
.
getLogPath
()
.
concat
(
"/gluesource/"
)
.
concat
(
String
.
valueOf
(
jobId
))
.
concat
(
"_"
)
.
concat
(
String
.
valueOf
(
glueUpdatetime
))
.
concat
(
glueType
.
getSuffix
());
ScriptUtil
.
markScriptFile
(
scriptFileName
,
gluesource
);
// log file
String
logFileName
=
XxlJobFileAppender
.
logPath
.
concat
(
XxlJobFileAppender
.
contextHolder
.
get
());
String
logFileName
=
XxlJobFileAppender
.
contextHolder
.
get
();
// script params:0=param、1=分片序号、2=分片总数
ShardingUtil
.
ShardingVO
shardingVO
=
ShardingUtil
.
getShardingVo
();
String
[]
scriptParams
=
new
String
[
3
];
scriptParams
[
0
]
=
param
;
scriptParams
[
1
]
=
String
.
valueOf
(
shardingVO
.
getIndex
());
scriptParams
[
2
]
=
String
.
valueOf
(
shardingVO
.
getTotal
());
// invoke
XxlJobLogger
.
log
(
"----------- script file:"
+
scriptFileName
+
" -----------"
);
int
exitValue
=
ScriptUtil
.
execToFile
(
cmd
,
scriptFileName
,
logFileName
,
p
arams
);
ReturnT
<
String
>
result
=
(
exitValue
==
0
)?
ReturnT
.
SUCCESS
:
new
ReturnT
<
String
>(
ReturnT
.
FAIL_CODE
,
"script exit value("
+
exitValue
+
") is failed"
);
int
exitValue
=
ScriptUtil
.
execToFile
(
cmd
,
scriptFileName
,
logFileName
,
scriptP
arams
);
ReturnT
<
String
>
result
=
(
exitValue
==
0
)?
IJobHandler
.
SUCCESS
:
new
ReturnT
<
String
>(
IJobHandler
.
FAIL
.
getCode
()
,
"script exit value("
+
exitValue
+
") is failed"
);
return
result
;
}
...
...
xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobFileAppender.java
浏览文件 @
8ed4d055
...
...
@@ -18,10 +18,35 @@ public class XxlJobFileAppender {
// for JobThread (support log for child thread of job handler)
//public static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public
static
final
InheritableThreadLocal
<
String
>
contextHolder
=
new
InheritableThreadLocal
<
String
>();
public
static
String
logPath
=
"/data/applogs/xxl-job/jobhandler/"
;
// log base path
private
static
String
logBasePath
=
"/data/applogs/xxl-job/jobhandler"
;
public
static
void
initLogPath
(
String
logPath
){
// init
if
(
logPath
!=
null
&&
logPath
.
trim
().
length
()>
0
)
{
logBasePath
=
logPath
;
}
// mk base dir
File
logPathDir
=
new
File
(
logBasePath
);
if
(!
logPathDir
.
exists
())
{
logPathDir
.
mkdirs
();
}
logBasePath
=
logPathDir
.
getPath
();
// mk glue dir
File
glueBaseDir
=
new
File
(
logPathDir
,
"gluesource"
);
if
(!
glueBaseDir
.
exists
())
{
glueBaseDir
.
mkdirs
();
}
}
public
static
String
getLogPath
()
{
return
logBasePath
;
}
/**
* log filename
: yyyy-MM-dd/9999.log
* log filename
, like "logPath/yyyy-MM-dd/9999.log"
*
* @param triggerDate
* @param logId
...
...
@@ -29,23 +54,18 @@ public class XxlJobFileAppender {
*/
public
static
String
makeLogFileName
(
Date
triggerDate
,
int
logId
)
{
// filePath/
File
filePathDir
=
new
File
(
logPath
);
if
(!
filePathDir
.
exists
())
{
filePathDir
.
mkdirs
();
}
// filePath/yyyy-MM-dd/
// filePath/yyyy-MM-dd
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
);
// avoid concurrent problem, can not be static
String
nowFormat
=
sdf
.
format
(
new
Date
());
File
filePathDateDir
=
new
File
(
filePathDir
,
nowFormat
);
if
(!
filePathDateDir
.
exists
())
{
filePathDateDir
.
mkdirs
();
File
logFilePath
=
new
File
(
getLogPath
(),
sdf
.
format
(
triggerDate
));
if
(!
logFilePath
.
exists
())
{
logFilePath
.
mkdir
();
}
// filePath/yyyy-MM-dd/9999.log
String
logFileName
=
sdf
.
format
(
triggerDate
).
concat
(
"/"
).
concat
(
String
.
valueOf
(
logId
)).
concat
(
".log"
);
String
logFileName
=
logFilePath
.
getPath
()
.
concat
(
"/"
)
.
concat
(
String
.
valueOf
(
logId
))
.
concat
(
".log"
);
return
logFileName
;
}
...
...
@@ -57,17 +77,11 @@ public class XxlJobFileAppender {
*/
public
static
void
appendLog
(
String
logFileName
,
String
appendLog
)
{
// log
if
(
appendLog
==
null
)
{
appendLog
=
""
;
}
appendLog
+=
"\r\n"
;
// log file
if
(
logFileName
==
null
||
logFileName
.
trim
().
length
()==
0
)
{
return
;
}
File
logFile
=
new
File
(
log
Path
,
log
FileName
);
File
logFile
=
new
File
(
logFileName
);
if
(!
logFile
.
exists
())
{
try
{
...
...
@@ -78,6 +92,12 @@ public class XxlJobFileAppender {
}
}
// log
if
(
appendLog
==
null
)
{
appendLog
=
""
;
}
appendLog
+=
"\r\n"
;
// append file content
try
{
FileOutputStream
fos
=
null
;
...
...
@@ -112,7 +132,7 @@ public class XxlJobFileAppender {
if
(
logFileName
==
null
||
logFileName
.
trim
().
length
()==
0
)
{
return
new
LogResult
(
fromLineNum
,
0
,
"readLog fail, logFile not found"
,
true
);
}
File
logFile
=
new
File
(
log
Path
,
log
FileName
);
File
logFile
=
new
File
(
logFileName
);
if
(!
logFile
.
exists
())
{
return
new
LogResult
(
fromLineNum
,
0
,
"readLog fail, logFile not exists"
,
true
);
...
...
xxl-job-core/src/main/java/com/xxl/job/core/log/XxlJobLogger.java
浏览文件 @
8ed4d055
...
...
@@ -3,6 +3,8 @@ package com.xxl.job.core.log;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.text.MessageFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
...
...
@@ -17,46 +19,63 @@ public class XxlJobLogger {
/**
* append log
*
* @param callInfo
* @param appendLog
*/
p
ublic
static
void
log
(
String
appendLog
)
{
p
rivate
static
void
logDetail
(
StackTraceElement
callInfo
,
String
appendLog
)
{
// logFileName
String
logFileName
=
XxlJobFileAppender
.
contextHolder
.
get
();
if
(
logFileName
==
null
||
logFileName
.
trim
().
length
()==
0
)
{
return
;
}
// "yyyy-MM-dd HH:mm:ss [ClassName]-[MethodName]-[LineNumber]-[ThreadName] log";
/
*/
/ "yyyy-MM-dd HH:mm:ss [ClassName]-[MethodName]-[LineNumber]-[ThreadName] log";
StackTraceElement[] stackTraceElements = new Throwable().getStackTrace();
StackTraceElement
callInfo
=
stackTraceElements
[
1
];
StackTraceElement callInfo = stackTraceElements[1];
*/
StringBuffer
stringBuffer
=
new
StringBuffer
();
stringBuffer
.
append
(
xxlJobLoggerFormat
.
format
(
new
Date
())).
append
(
" "
)
.
append
(
"["
+
callInfo
.
getClassName
()
+
"]"
).
append
(
"-"
)
.
append
(
"["
+
callInfo
.
getMethodName
()
+
"]"
).
append
(
"-"
)
.
append
(
"["
+
callInfo
.
getClassName
()
+
"#"
+
callInfo
.
getMethodName
()
+
"]"
).
append
(
"-"
)
.
append
(
"["
+
callInfo
.
getLineNumber
()
+
"]"
).
append
(
"-"
)
.
append
(
"["
+
Thread
.
currentThread
().
getName
()
+
"]"
).
append
(
" "
)
.
append
(
appendLog
!=
null
?
appendLog:
""
);
String
formatAppendLog
=
stringBuffer
.
toString
();
// appendlog
String
logFileName
=
XxlJobFileAppender
.
contextHolder
.
get
();
if
(
logFileName
!=
null
&&
logFileName
.
trim
().
length
()>
0
)
{
XxlJobFileAppender
.
appendLog
(
logFileName
,
formatAppendLog
);
logger
.
debug
(
">>>>>>>>>>> [{}]: {}"
,
logFileName
,
formatAppendLog
);
}
else
{
logger
.
info
(
">>>>>>>>>>> {}"
,
formatAppendLog
);
}
}
/**
* append log with pattern
*
* @
*
* @param appendLogPattern like "aaa {0} bbb {1} ccc"
* @param appendLogArguments like "111, true"
*/
public
static
void
log
(
String
appendLogPattern
,
Object
...
appendLogArguments
)
{
String
appendLog
=
MessageFormat
.
format
(
appendLogPattern
,
appendLogArguments
);
log
(
appendLog
);
String
appendLog
=
appendLogPattern
;
if
(
appendLogArguments
!=
null
&&
appendLogArguments
.
length
>
0
)
{
appendLog
=
MessageFormat
.
format
(
appendLogPattern
,
appendLogArguments
);
}
StackTraceElement
callInfo
=
new
Throwable
().
getStackTrace
()[
1
];
logDetail
(
callInfo
,
appendLog
);
}
/**
* append exception stack
*
* @param e
*/
public
static
void
log
(
Throwable
e
)
{
StringWriter
stringWriter
=
new
StringWriter
();
e
.
printStackTrace
(
new
PrintWriter
(
stringWriter
));
String
appendLog
=
stringWriter
.
toString
();
StackTraceElement
callInfo
=
new
Throwable
().
getStackTrace
()[
1
];
logDetail
(
callInfo
,
appendLog
);
}
}
xxl-job-core/src/main/java/com/xxl/job/core/thread/JobThread.java
浏览文件 @
8ed4d055
...
...
@@ -92,6 +92,14 @@ public class JobThread extends Thread{
@Override
public
void
run
()
{
// init
try
{
handler
.
init
();
}
catch
(
Throwable
e
)
{
logger
.
error
(
e
.
getMessage
(),
e
);
}
// execute
while
(!
toStop
){
running
=
false
;
idleTimes
++;
...
...
@@ -106,21 +114,16 @@ public class JobThread extends Thread{
idleTimes
=
0
;
triggerLogIdSet
.
remove
(
triggerParam
.
getLogId
());
// parse param
String
[]
handlerParams
=
(
triggerParam
.
getExecutorParams
()!=
null
&&
triggerParam
.
getExecutorParams
().
trim
().
length
()>
0
)
?
(
String
[])(
Arrays
.
asList
(
triggerParam
.
getExecutorParams
().
split
(
","
)).
toArray
())
:
null
;
// log filename: yyyy-MM-dd/9999.log
// log filename, like "logPath/yyyy-MM-dd/9999.log"
String
logFileName
=
XxlJobFileAppender
.
makeLogFileName
(
new
Date
(
triggerParam
.
getLogDateTim
()),
triggerParam
.
getLogId
());
XxlJobFileAppender
.
contextHolder
.
set
(
logFileName
);
ShardingUtil
.
setShardingVo
(
new
ShardingUtil
.
ShardingVO
(
triggerParam
.
getBroadcastIndex
(),
triggerParam
.
getBroadcastTotal
()));
// execute
XxlJobLogger
.
log
(
"<br>----------- xxl-job job execute start -----------<br>----------- Param
s:"
+
Arrays
.
toString
(
handlerParams
));
executeResult
=
handler
.
execute
(
handlerParams
);
XxlJobLogger
.
log
(
"<br>----------- xxl-job job execute start -----------<br>----------- Param
:"
+
triggerParam
.
getExecutorParams
(
));
executeResult
=
handler
.
execute
(
triggerParam
.
getExecutorParams
()
);
if
(
executeResult
==
null
)
{
executeResult
=
ReturnT
.
FAIL
;
executeResult
=
IJobHandler
.
FAIL
;
}
XxlJobLogger
.
log
(
"<br>----------- xxl-job job execute end(finish) -----------<br>----------- ReturnT:"
+
executeResult
);
...
...
@@ -165,6 +168,13 @@ public class JobThread extends Thread{
}
}
// destroy
try
{
handler
.
destroy
();
}
catch
(
Throwable
e
)
{
logger
.
error
(
e
.
getMessage
(),
e
);
}
logger
.
info
(
">>>>>>>>>>> xxl-job JobThread stoped, hashCode:{}"
,
Thread
.
currentThread
());
}
}
xxl-job-core/src/main/java/com/xxl/job/core/util/JacksonUtil.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
core
.
util
;
import
org.codehaus.jackson.JsonGenerationException
;
import
org.codehaus.jackson.JsonParseException
;
import
org.codehaus.jackson.map.JsonMappingException
;
import
org.codehaus.jackson.map.ObjectMapper
;
import
org.codehaus.jackson.type.TypeReference
;
import
com.fasterxml.jackson.core.JsonGenerationException
;
import
com.fasterxml.jackson.core.JsonParseException
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.fasterxml.jackson.databind.JsonMappingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
xxl-job-core/src/main/java/com/xxl/job/core/util/ScriptUtil.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
core
.
util
;
import
com.xxl.job.core.log.XxlJobFileAppender
;
import
org.apache.commons.exec.CommandLine
;
import
org.apache.commons.exec.DefaultExecutor
;
import
org.apache.commons.exec.PumpStreamHandler
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
...
...
@@ -27,18 +25,6 @@ public class ScriptUtil {
* @throws IOException
*/
public
static
void
markScriptFile
(
String
scriptFileName
,
String
content
)
throws
IOException
{
// filePath/
File
filePathDir
=
new
File
(
XxlJobFileAppender
.
logPath
);
if
(!
filePathDir
.
exists
())
{
filePathDir
.
mkdirs
();
}
// filePath/gluesource/
File
filePathSourceDir
=
new
File
(
filePathDir
,
"gluesource"
);
if
(!
filePathSourceDir
.
exists
())
{
filePathSourceDir
.
mkdirs
();
}
// make file, filePath/gluesource/666-123456789.py
FileOutputStream
fileOutputStream
=
null
;
try
{
...
...
xxl-job-executor-samples/pom.xml
浏览文件 @
8ed4d055
...
...
@@ -14,6 +14,7 @@
<module>
xxl-job-executor-sample-spring
</module>
<module>
xxl-job-executor-sample-springboot
</module>
<module>
xxl-job-executor-sample-jfinal
</module>
<module>
xxl-job-executor-sample-nutz
</module>
</modules>
</project>
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/pom.xml
浏览文件 @
8ed4d055
...
...
@@ -16,7 +16,7 @@
<dependency>
<groupId>
com.jfinal
</groupId>
<artifactId>
jfinal
</artifactId>
<version>
2.
0
</version>
<version>
2.
2
</version>
</dependency>
<!-- slf4j -->
...
...
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/config/JFinalCoreConfig.java
浏览文件 @
8ed4d055
...
...
@@ -17,8 +17,9 @@ public class JFinalCoreConfig extends JFinalConfig {
private
Logger
logger
=
LoggerFactory
.
getLogger
(
JFinalCoreConfig
.
class
);
// ---------------------- xxl-job executor ----------------------
XxlJobExecutor
xxlJobExecutor
=
null
;
private
XxlJobExecutor
xxlJobExecutor
=
null
;
private
void
initXxlJobExecutor
()
{
// registry jobhandler
XxlJobExecutor
.
registJobHandler
(
"demoJobHandler"
,
new
DemoJobHandler
());
XxlJobExecutor
.
registJobHandler
(
"shardingJobHandler"
,
new
ShardingJobHandler
());
...
...
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/controller/IndexController.java
浏览文件 @
8ed4d055
...
...
@@ -7,4 +7,5 @@ public class IndexController extends Controller {
public
void
index
(){
renderText
(
"xxl job executor running."
);
}
}
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/DemoJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -6,28 +6,27 @@ import com.xxl.job.core.log.XxlJobLogger;
import
java.util.concurrent.TimeUnit
;
/**
* 任务Handler
的一个Demo
(Bean模式)
* 任务Handler
示例
(Bean模式)
*
* 开发步骤:
* 1、继承
“IJobHandler”
;
* 2、
执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
* 3、
在 "JFinalCoreConfig" 中注册,执行Jobhandler名称
;
* 1、继承
"IJobHandler":“com.xxl.job.core.handler.IJobHandler”
;
* 2、
注册到执行器工厂:在 "JFinalCoreConfig.initXxlJobExecutor" 中手动注册,注解key值对应的是调度中心新建任务的JobHandler属性的值。
* 3、
执行日志:需要通过 "XxlJobLogger.log" 打印执行日志
;
*
* @author xuxueli 2015-12-19 19:43:36
*/
public
class
DemoJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
XxlJobLogger
.
log
(
"XXL-JOB, Hello World."
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
XxlJobLogger
.
log
(
"beat at:"
+
i
);
TimeUnit
.
SECONDS
.
sleep
(
2
);
}
return
ReturnT
.
SUCCESS
;
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/java/com/xuxueli/executor/sample/jfinal/jobhandler/ShardingJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -14,7 +14,7 @@ import com.xxl.job.core.util.ShardingUtil;
public
class
ShardingJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
// 分片参数
ShardingUtil
.
ShardingVO
shardingVO
=
ShardingUtil
.
getShardingVo
();
...
...
@@ -29,7 +29,7 @@ public class ShardingJobHandler extends IJobHandler {
}
}
return
ReturnT
.
SUCCESS
;
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/resources/xxl-job-executor.properties
浏览文件 @
8ed4d055
...
...
@@ -4,10 +4,10 @@ xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### xxl-job executor address
xxl.job.executor.appname
=
xxl-job-executor-sample
xxl.job.executor.ip
=
xxl.job.executor.port
=
999
7
xxl.job.executor.port
=
999
6
### xxl-job log path
xxl.job.executor.logpath
=
/data/applogs/xxl-job/jobhandler
/
xxl.job.executor.logpath
=
/data/applogs/xxl-job/jobhandler
### xxl-job, access token
xxl.job.accessToken
=
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/WEB-INF/web.xml
浏览文件 @
8ed4d055
...
...
@@ -3,6 +3,7 @@
xmlns=
"http://java.sun.com/xml/ns/javaee"
xmlns:web=
"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id=
"WebApp_ID"
version=
"2.5"
>
<display-name>
xxl-job-executor-sample-jfinal
</display-name>
<context-param>
<param-name>
webAppRootKey
</param-name>
...
...
@@ -23,4 +24,9 @@
<url-pattern>
/*
</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>
index.html
</welcome-file>
</welcome-file-list>
</web-app>
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-jfinal/src/main/webapp/index.html
0 → 100644
浏览文件 @
8ed4d055
i am alive.
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-nutz/pom.xml
0 → 100644
浏览文件 @
8ed4d055
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<parent>
<groupId>
com.xuxueli
</groupId>
<artifactId>
xxl-job-executor-samples
</artifactId>
<version>
1.9.0-SNAPSHOT
</version>
</parent>
<modelVersion>
4.0.0
</modelVersion>
<artifactId>
xxl-job-executor-sample-nutz
</artifactId>
<packaging>
war
</packaging>
<dependencies>
<!-- nutz -->
<dependency>
<groupId>
org.nutz
</groupId>
<artifactId>
nutz
</artifactId>
<version>
1.r.62
</version>
</dependency>
<!-- slf4j -->
<dependency>
<groupId>
org.slf4j
</groupId>
<artifactId>
slf4j-log4j12
</artifactId>
<version>
${slf4j-api.version}
</version>
</dependency>
<!-- xxl-job -->
<dependency>
<groupId>
com.xuxueli
</groupId>
<artifactId>
xxl-job-core
</artifactId>
<version>
${project.parent.version}
</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/MainModule.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xuxueli
.
executor
.
sample
.
nutz
;
import
com.xuxueli.executor.sample.nutz.config.NutzSetup
;
import
org.nutz.mvc.annotation.*
;
import
org.nutz.mvc.ioc.provider.ComboIocProvider
;
/**
* nutz module
*
* @author xuxueli 2017-12-25 17:58:43
*/
@IocBy
(
type
=
ComboIocProvider
.
class
,
args
=
{
"*org.nutz.ioc.loader.annotation.AnnotationIocLoader"
,
"com.xuxueli.executor.sample.nutz"
})
@Encoding
(
input
=
"utf-8"
,
output
=
"utf-8"
)
@Modules
(
scanPackage
=
true
)
@Localization
(
"msg"
)
@Ok
(
"json"
)
@Fail
(
"json"
)
@SetupBy
(
NutzSetup
.
class
)
public
class
MainModule
{
}
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/config/NutzSetup.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xuxueli
.
executor
.
sample
.
nutz
.
config
;
import
com.xxl.job.core.executor.XxlJobExecutor
;
import
com.xxl.job.core.handler.IJobHandler
;
import
com.xxl.job.core.handler.annotation.JobHandler
;
import
org.nutz.ioc.impl.PropertiesProxy
;
import
org.nutz.mvc.NutConfig
;
import
org.nutz.mvc.Setup
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* nutz setup
*
* @author xuxueli 2017-12-25 17:58:43
*/
public
class
NutzSetup
implements
Setup
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
NutzSetup
.
class
);
//public static final Log logger = Logs.get();
private
XxlJobExecutor
xxlJobExecutor
=
null
;
@Override
public
void
init
(
NutConfig
cfg
)
{
// regist JobHandler
String
[]
beanNames
=
cfg
.
getIoc
().
getNamesByType
(
IJobHandler
.
class
);
if
(
beanNames
==
null
||
beanNames
.
length
==
0
)
{
return
;
}
for
(
String
beanName
:
beanNames
)
{
IJobHandler
jobHandler
=
cfg
.
getIoc
().
get
(
IJobHandler
.
class
,
beanName
);
String
name
=
jobHandler
.
getClass
().
getAnnotation
(
JobHandler
.
class
).
value
();
XxlJobExecutor
.
registJobHandler
(
name
,
jobHandler
);
}
// load executor prop
PropertiesProxy
xxlJobProp
=
new
PropertiesProxy
(
"xxl-job-executor.properties"
);
// init executor
xxlJobExecutor
=
new
XxlJobExecutor
();
xxlJobExecutor
.
setIp
(
xxlJobProp
.
get
(
"xxl.job.executor.ip"
));
xxlJobExecutor
.
setPort
(
xxlJobProp
.
getInt
(
"xxl.job.executor.port"
));
xxlJobExecutor
.
setAppName
(
xxlJobProp
.
get
(
"xxl.job.executor.appname"
));
xxlJobExecutor
.
setAdminAddresses
(
xxlJobProp
.
get
(
"xxl.job.admin.addresses"
));
xxlJobExecutor
.
setLogPath
(
xxlJobProp
.
get
(
"xxl.job.executor.logpath"
));
xxlJobExecutor
.
setAccessToken
(
xxlJobProp
.
get
(
"xxl.job.accessToken"
));
// start executor
try
{
xxlJobExecutor
.
start
();
}
catch
(
Exception
e
)
{
logger
.
error
(
e
.
getMessage
(),
e
);
}
}
@Override
public
void
destroy
(
NutConfig
cfg
)
{
if
(
xxlJobExecutor
!=
null
)
{
xxlJobExecutor
.
destroy
();
}
}
}
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/DemoJobHandler.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xuxueli
.
executor
.
sample
.
nutz
.
jobhandler
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
com.xxl.job.core.handler.IJobHandler
;
import
com.xxl.job.core.handler.annotation.JobHandler
;
import
com.xxl.job.core.log.XxlJobLogger
;
import
org.nutz.ioc.loader.annotation.IocBean
;
import
java.util.concurrent.TimeUnit
;
/**
* 任务Handler示例(Bean模式)
*
* 开发步骤:
* 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”;
* 2、注册到Nutz容器:添加“@IocBean”注解,被Nutz容器扫描为Bean实例;
* 3、注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,注解value值对应的是调度中心新建任务的JobHandler属性的值。
* 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
*
* @author xuxueli 2015-12-19 19:43:36
*/
@JobHandler
(
value
=
"demoJobHandler"
)
@IocBean
public
class
DemoJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
XxlJobLogger
.
log
(
"XXL-JOB, Hello World."
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
XxlJobLogger
.
log
(
"beat at:"
+
i
);
TimeUnit
.
SECONDS
.
sleep
(
2
);
}
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/jobhandler/ShardingJobHandler.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xuxueli
.
executor
.
sample
.
nutz
.
jobhandler
;
import
com.xxl.job.core.handler.annotation.JobHandler
;
import
org.nutz.ioc.loader.annotation.IocBean
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
com.xxl.job.core.handler.IJobHandler
;
import
com.xxl.job.core.log.XxlJobLogger
;
import
com.xxl.job.core.util.ShardingUtil
;
/**
* 分片广播任务
*
* @author xuxueli 2017-07-25 20:56:50
*/
@JobHandler
(
value
=
"shardingJobHandler"
)
@IocBean
public
class
ShardingJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
// 分片参数
ShardingUtil
.
ShardingVO
shardingVO
=
ShardingUtil
.
getShardingVo
();
XxlJobLogger
.
log
(
"分片参数:当前分片序号 = {0}, 总分片数 = {1}"
,
shardingVO
.
getIndex
(),
shardingVO
.
getTotal
());
// 业务逻辑
for
(
int
i
=
0
;
i
<
shardingVO
.
getTotal
();
i
++)
{
if
(
i
==
shardingVO
.
getIndex
())
{
XxlJobLogger
.
log
(
"第 {0} 片, 命中分片开始处理"
,
i
);
}
else
{
XxlJobLogger
.
log
(
"第 {0} 片, 忽略"
,
i
);
}
}
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/java/com/xuxueli/executor/sample/nutz/module/IndexModule.java
0 → 100644
浏览文件 @
8ed4d055
package
com
.
xuxueli
.
executor
.
sample
.
nutz
.
module
;
import
org.nutz.ioc.loader.annotation.IocBean
;
import
org.nutz.mvc.annotation.At
;
import
org.nutz.mvc.annotation.Ok
;
@IocBean
public
class
IndexModule
{
@At
(
"/"
)
@Ok
(
"json"
)
public
String
index
()
{
return
"xxl job executor running."
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/log4j.xml
0 → 100644
浏览文件 @
8ed4d055
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration
xmlns:log4j=
"http://jakarta.apache.org/log4j/"
threshold=
"null"
debug=
"null"
>
<appender
name=
"CONSOLE"
class=
"org.apache.log4j.ConsoleAppender"
>
<param
name=
"Target"
value=
"System.out"
/>
<layout
class=
"org.apache.log4j.PatternLayout"
>
<param
name=
"ConversionPattern"
value=
"%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-nutz [%c]-[%t]-[%M]-[%L]-[%p] %m%n"
/>
</layout>
</appender>
<appender
name=
"FILE"
class=
"org.apache.log4j.DailyRollingFileAppender"
>
<param
name=
"file"
value=
"/data/applogs/xxl-job/xxl-job-executor-sample-nutz.log"
/>
<param
name=
"append"
value=
"true"
/>
<param
name=
"encoding"
value=
"UTF-8"
/>
<layout
class=
"org.apache.log4j.PatternLayout"
>
<param
name=
"ConversionPattern"
value=
"%-d{yyyy-MM-dd HH:mm:ss} xxl-job-executor-sample-nutz [%c]-[%t]-[%M]-[%L]-[%p] %m%n"
/>
</layout>
</appender>
<root>
<level
value=
"INFO"
/>
<appender-ref
ref=
"CONSOLE"
/>
<appender-ref
ref=
"FILE"
/>
</root>
</log4j:configuration>
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/resources/xxl-job-executor.properties
0 → 100644
浏览文件 @
8ed4d055
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses
=
http://127.0.0.1:8080/xxl-job-admin
### xxl-job executor address
xxl.job.executor.appname
=
xxl-job-executor-sample
xxl.job.executor.ip
=
xxl.job.executor.port
=
9997
### xxl-job log path
xxl.job.executor.logpath
=
/data/applogs/xxl-job/jobhandler
### xxl-job, access token
xxl.job.accessToken
=
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/WEB-INF/web.xml
0 → 100644
浏览文件 @
8ed4d055
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns=
"http://java.sun.com/xml/ns/javaee"
xmlns:web=
"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id=
"WebApp_ID"
version=
"2.5"
>
<display-name>
xxl-job-executor-sample-nutz
</display-name>
<context-param>
<param-name>
webAppRootKey
</param-name>
<param-value>
xxl-job-executor-sample-nutz
</param-value>
</context-param>
<!-- nutz -->
<filter>
<filter-name>
nutz
</filter-name>
<filter-class>
org.nutz.mvc.NutFilter
</filter-class>
<init-param>
<param-name>
modules
</param-name>
<param-value>
com.xuxueli.executor.sample.nutz.MainModule
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>
nutz
</filter-name>
<url-pattern>
/*
</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>
index.html
</welcome-file>
</welcome-file-list>
</web-app>
xxl-job-executor-samples/xxl-job-executor-sample-nutz/src/main/webapp/index.html
0 → 100644
浏览文件 @
8ed4d055
i am alive.
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -10,12 +10,12 @@ import java.util.concurrent.TimeUnit;
/**
* 任务Handler
的一个Demo
(Bean模式)
* 任务Handler
示例
(Bean模式)
*
* 开发步骤:
* 1、
新建一个继承com.xxl.job.core.handler.IJobHandler的Java类
;
* 2、
该类被Spring容器扫描为Bean实例,如加“@Component”注解
;
* 3、
添加 “@JobHandler(value="自定义jobhandler名称")”注解,注解的value值为自定义的JobHandler名称,该名称
对应的是调度中心新建任务的JobHandler属性的值。
* 1、
继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”
;
* 2、
注册到Spring容器:添加“@Component”注解,被Spring容器扫描为Bean实例
;
* 3、
注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,注解value值
对应的是调度中心新建任务的JobHandler属性的值。
* 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
*
* @author xuxueli 2015-12-19 19:43:36
...
...
@@ -25,14 +25,14 @@ import java.util.concurrent.TimeUnit;
public
class
DemoJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
XxlJobLogger
.
log
(
"XXL-JOB, Hello World."
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
XxlJobLogger
.
log
(
"beat at:"
+
i
);
TimeUnit
.
SECONDS
.
sleep
(
2
);
}
return
ReturnT
.
SUCCESS
;
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -18,7 +18,7 @@ import org.springframework.stereotype.Service;
public
class
ShardingJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
// 分片参数
ShardingUtil
.
ShardingVO
shardingVO
=
ShardingUtil
.
getShardingVo
();
...
...
@@ -33,7 +33,7 @@ public class ShardingJobHandler extends IJobHandler {
}
}
return
ReturnT
.
SUCCESS
;
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/applicationcontext-xxl-job.xml
浏览文件 @
8ed4d055
...
...
@@ -3,9 +3,9 @@
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:context=
"http://www.springframework.org/schema/context"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans
-3.0
.xsd
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context
-3.0
.xsd"
>
http://www.springframework.org/schema/context/spring-context.xsd"
>
<bean
id=
"propertyConfigurer"
class=
"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
>
<property
name=
"fileEncoding"
value=
"utf-8"
/>
...
...
@@ -25,15 +25,15 @@
<bean
id=
"xxlJobExecutor"
class=
"com.xxl.job.core.executor.XxlJobExecutor"
init-method=
"start"
destroy-method=
"destroy"
>
<!-- 执行器IP[选填],为空则自动获取 -->
<property
name=
"ip"
value=
"${xxl.job.executor.ip}"
/>
<!-- 执行器端口号[
必须]
-->
<!-- 执行器端口号[
选填],为空则自动获取
-->
<property
name=
"port"
value=
"${xxl.job.executor.port}"
/>
<!-- 执行器AppName[选填],为空则关闭自动注册 -->
<property
name=
"appName"
value=
"${xxl.job.executor.appname}"
/>
<!-- 执行器注册中心地址[选填],为空则关闭自动注册 -->
<property
name=
"adminAddresses"
value=
"${xxl.job.admin.addresses}"
/>
<!-- 执行器日志路径[
必填]
-->
<!-- 执行器日志路径[
选填],为空则使用默认路径
-->
<property
name=
"logPath"
value=
"${xxl.job.executor.logpath}"
/>
<!-- 访问令牌
,非空则进行匹配校验[选填]
-->
<!-- 访问令牌
[选填],非空则进行匹配校验
-->
<property
name=
"accessToken"
value=
"${xxl.job.accessToken}"
/>
</bean>
...
...
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/resources/xxl-job-executor.properties
浏览文件 @
8ed4d055
...
...
@@ -7,7 +7,7 @@ xxl.job.executor.ip=
xxl.job.executor.port
=
9999
### xxl-job log path
xxl.job.executor.logpath
=
/data/applogs/xxl-job/jobhandler
/
xxl.job.executor.logpath
=
/data/applogs/xxl-job/jobhandler
### xxl-job, access token
xxl.job.accessToken
=
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/WEB-INF/web.xml
浏览文件 @
8ed4d055
...
...
@@ -3,12 +3,14 @@
xmlns=
"http://java.sun.com/xml/ns/javaee"
xmlns:web=
"http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id=
"WebApp_ID"
version=
"2.5"
>
<display-name>
xxl-job-executor-sample-spring
</display-name>
<context-param>
<param-name>
webAppRootKey
</param-name>
<param-value>
xxl-job-executor-sample-spring
</param-value>
</context-param>
<!-- spring -->
<context-param>
<param-name>
contextConfigLocation
</param-name>
<param-value>
classpath*:applicationcontext-*.xml
</param-value>
...
...
@@ -21,6 +23,7 @@
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>
index.html
</welcome-file>
</welcome-file-list>
...
...
xxl-job-executor-samples/xxl-job-executor-sample-spring/src/main/webapp/index.html
浏览文件 @
8ed4d055
200
\ No newline at end of file
i am alive.
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/mvc/controller/IndexController.java
浏览文件 @
8ed4d055
package
com
.
xxl
.
job
.
executor
.
mvc
.
controller
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.ResponseBody
;
@Controller
@EnableAutoConfiguration
public
class
IndexController
{
@RequestMapping
(
"/"
)
@ResponseBody
String
index
()
{
return
"xxl job executor running."
;
}
}
\ No newline at end of file
//package com.xxl.job.executor.mvc.controller;
//
//import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
//import org.springframework.stereotype.Controller;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.ResponseBody;
//
//@Controller
//@EnableAutoConfiguration
//public class IndexController {
//
// @RequestMapping("/")
// @ResponseBody
// String index() {
// return "xxl job executor running.";
// }
//
//}
\ No newline at end of file
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -4,35 +4,35 @@ import com.xxl.job.core.biz.model.ReturnT;
import
com.xxl.job.core.handler.IJobHandler
;
import
com.xxl.job.core.handler.annotation.JobHandler
;
import
com.xxl.job.core.log.XxlJobLogger
;
import
org.springframework.stereotype.
Service
;
import
org.springframework.stereotype.
Component
;
import
java.util.concurrent.TimeUnit
;
/**
* 任务Handler
的一个Demo
(Bean模式)
* 任务Handler
示例
(Bean模式)
*
* 开发步骤:
* 1、继承
“IJobHandler”
;
* 2、
装配到Spring,例如加 “@Service” 注解
;
* 3、
加 “@JobHandler” 注解,注解value值为新增任务生成的JobKey的值;多个JobKey用逗号分割;
* 1、继承
"IJobHandler":“com.xxl.job.core.handler.IJobHandler”
;
* 2、
注册到Spring容器:添加“@Component”注解,被Spring容器扫描为Bean实例
;
* 3、
注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,注解value值对应的是调度中心新建任务的JobHandler属性的值。
* 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
*
* @author xuxueli 2015-12-19 19:43:36
*/
@JobHandler
(
value
=
"demoJobHandler"
)
@
Service
@
Component
public
class
DemoJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
XxlJobLogger
.
log
(
"XXL-JOB, Hello World."
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
XxlJobLogger
.
log
(
"beat at:"
+
i
);
TimeUnit
.
SECONDS
.
sleep
(
2
);
}
return
ReturnT
.
SUCCESS
;
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/service/jobhandler/ShardingJobHandler.java
浏览文件 @
8ed4d055
...
...
@@ -18,7 +18,7 @@ import org.springframework.stereotype.Service;
public
class
ShardingJobHandler
extends
IJobHandler
{
@Override
public
ReturnT
<
String
>
execute
(
String
...
params
)
throws
Exception
{
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
// 分片参数
ShardingUtil
.
ShardingVO
shardingVO
=
ShardingUtil
.
getShardingVo
();
...
...
@@ -33,7 +33,7 @@ public class ShardingJobHandler extends IJobHandler {
}
}
return
ReturnT
.
SUCCESS
;
return
SUCCESS
;
}
}
xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties
浏览文件 @
8ed4d055
...
...
@@ -11,10 +11,10 @@ xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### xxl-job executor address
xxl.job.executor.appname
=
xxl-job-executor-sample
xxl.job.executor.ip
=
xxl.job.executor.port
=
-1
xxl.job.executor.port
=
9998
### xxl-job log path
xxl.job.executor.logpath
=
/data/applogs/xxl-job/jobhandler
/
xxl.job.executor.logpath
=
/data/applogs/xxl-job/jobhandler
### xxl-job, access token
xxl.job.accessToken
=
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论