Merge branch 'master' into master

2.5.0
许雪里 11 months ago committed by GitHub
commit 66e0d56724
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -40,6 +40,19 @@ Now, it's already open source, and many companies use it in production environme
XXL-JOB是一个分布式任务调度平台其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线开箱即用。
## Sponsor
XXL-JOB is an open source and free project, with its ongoing development made possible entirely by the support of these awesome backers.
XXL-JOB 是一个开源且免费项目,其正在进行的开发完全得益于支持者的支持。开源不易,[前往赞助项目开发](https://www.xuxueli.com/page/donate.html )
<!-- supporter start -->
<h5 style="color: silver;" >金牌赞助方</h5>
<a href="https://www.jetbrains.com/idea/?from=xuxueli.com" title="jetbrains" target="_blank" >
<img width="55px" src="http://www.xuxueli.com/page/static/images/logo_intellij.jpeg" >
</a>
<!-- supporter end -->
## Documentation
- [中文文档](https://www.xuxueli.com/xxl-job/)
- [English Documentation](https://www.xuxueli.com/xxl-job/en/)
@ -119,6 +132,8 @@ XXL-JOB是一个分布式任务调度平台其核心设计目标是开发迅
于2021-12-06XXL-JOB参与"[2021年度OSC中国开源项目评选](https://www.oschina.net/project/top_cn_2021) "评比,在当时已录入的一万多个开源项目中角逐,最终当选"最受欢迎项目"。
于2024-11-06XXL-JOB经 GitCode 官方评审,获得 “G-Star项目毕业认证”。
> 我司大众点评目前已接入XXL-JOB内部别名《Ferrari》Ferrari基于XXL-JOB的V1.1版本定制而成,新接入应用推荐升级最新版本)。
据最新统计, 自2016-01-21接入至2017-12-01期间该系统已调度约100万次表现优异。新接入应用推荐使用最新版本因为经过数十个版本的更新系统的任务模型、UI交互模型以及底层调度通讯模型都有了较大的优化和提升核心功能更加稳定高效。
@ -766,6 +781,41 @@ XXL-JOB是一个分布式任务调度平台其核心设计目标是开发迅
- 640、再造再生健康科技有限公司
- 641、华宝证券
- 642、卓正医疗
- 643、深圳湛信科技
- 644、陕西鑫众为软件有限公司
- 645、深圳市润农科技有限公司
- 646、庚商教育智能科技有限公司
- 647、杭州祎声科技
- 648、四川久远银海软件股份有限公司
- 649、GeeFox极狐低代码
- 650、浙江和仁科技股份有限公司
- 651、宁波聚臻智能科技有限公司
- 652、福建福昕软件开发股份有限公司【福昕】
- 653、广州中长康达信息技术有限公司
- 654、武汉趣改信息科技有限公司
- 655、北京华夏思源科技发展有限公司
- 656、宁波关关通科技有限公司
- 657、青岛吕氏餐饮有限公司
- 658、杭州乐刻网络科技有限公司
- 659、上海红瓦信息科技有限公司
- 660、陕西旅小宝信息科技有限公司
- 661、中科卓恒(大连)科技有限公司
- 662、北京华益精点生物技术有限公司
- 663、马士基中国航运有限公司【马士基】
- 664、陕西美咚网络科技有限公司
- 665、山东新北洋信息技术股份有限公司
- 666、福建中瑞文化发展集团有限公司
- 667、黑龙江省建工集团有限责任公司【黑龙江省建工】
- 668、志信能达安全科技(广州)有限公司
- 669、重庆开源共创科技有限公司
- 670、华泰人寿保险股份有限公司【华泰人寿】
- 671、成都盘古纵横集团
- 672、北京果果乐学科技有限公司
- 673、北京凌云空间科技有限公司
- 674、临工重机股份有限公司
- 675、上海热风时尚管理集团【热风】
- 676、HashKey Exchange
- 677、傲基深圳跨境商务股份有限公司
- ……
> 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
@ -785,10 +835,4 @@ This product is open source and free, and will continue to provide free communit
- Licensed under the GNU General Public License (GPL) v3.
- Copyright (c) 2015-present, xuxueli.
产品开源免费,并且将持续提供免费的社区技术支持。个人或企业内部可自由的接入和使用。如有需要可邮件联系作者免费获取项目授权。
## Donate
No matter how much the donation amount is enough to express your thought, thank you very much [To donate](https://www.xuxueli.com/page/donate.html )
无论捐赠金额多少都足够表达您这份心意,非常感谢 [前往捐赠](https://www.xuxueli.com/page/donate.html )
产品开源免费,并且将持续提供免费的社区技术支持。个人或企业内部可自由的接入和使用。如有需要可 [邮件联系](https://www.xuxueli.com/page/community.html) 作者免费获取项目授权。

@ -736,6 +736,41 @@ XXL-JOB是一个分布式任务调度平台其核心设计目标是开发迅
- 640、再造再生健康科技有限公司
- 641、华宝证券
- 642、卓正医疗
- 643、深圳湛信科技
- 644、陕西鑫众为软件有限公司
- 645、深圳市润农科技有限公司
- 646、庚商教育智能科技有限公司
- 647、杭州祎声科技
- 648、四川久远银海软件股份有限公司
- 649、GeeFox极狐低代码
- 650、浙江和仁科技股份有限公司
- 651、宁波聚臻智能科技有限公司
- 652、福建福昕软件开发股份有限公司【福昕】
- 653、广州中长康达信息技术有限公司
- 654、武汉趣改信息科技有限公司
- 655、北京华夏思源科技发展有限公司
- 656、宁波关关通科技有限公司
- 657、青岛吕氏餐饮有限公司
- 658、杭州乐刻网络科技有限公司
- 659、上海红瓦信息科技有限公司
- 660、陕西旅小宝信息科技有限公司
- 661、中科卓恒(大连)科技有限公司
- 662、北京华益精点生物技术有限公司
- 663、马士基中国航运有限公司【马士基】
- 664、陕西美咚网络科技有限公司
- 665、山东新北洋信息技术股份有限公司
- 666、福建中瑞文化发展集团有限公司
- 667、黑龙江省建工集团有限责任公司【黑龙江省建工】
- 668、志信能达安全科技(广州)有限公司
- 669、重庆开源共创科技有限公司
- 670、华泰人寿保险股份有限公司【华泰人寿】
- 671、成都盘古纵横集团
- 672、北京果果乐学科技有限公司
- 673、北京凌云空间科技有限公司
- 674、临工重机股份有限公司
- 675、上海热风时尚管理集团【热风】
- 676、HashKey Exchange
- 677、傲基深圳跨境商务股份有限公司
- ……
> 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
@ -756,6 +791,7 @@ XXL-JOB是一个分布式任务调度平台其核心设计目标是开发迅
--- | ---
[https://github.com/xuxueli/xxl-job](https://github.com/xuxueli/xxl-job) | [Download](https://github.com/xuxueli/xxl-job/releases)
[http://gitee.com/xuxueli0323/xxl-job](http://gitee.com/xuxueli0323/xxl-job) | [Download](http://gitee.com/xuxueli0323/xxl-job/releases)
[https://gitcode.com/xuxueli0323/xxl-job](https://gitcode.com/xuxueli0323/xxl-job) | [Download](https://gitcode.com/xuxueli0323/xxl-job/tags)
#### 中央仓库地址
@ -875,8 +911,6 @@ docker pull xuxueli/xxl-job-admin
- 创建容器并运行
```
docker run -p 8080:8080 -v /tmp:/data/applogs --name xxl-job-admin -d xuxueli/xxl-job-admin:{指定版本}
/**
* 如需自定义 mysql 等配置,可通过 "-e PARAMS" 指定,参数格式 PARAMS="--key=value --key2=value2"
* 配置项参考文件:/xxl-job/xxl-job-admin/src/main/resources/application.properties
@ -1027,7 +1061,7 @@ public XxlJobSpringExecutor xxlJobExecutor() {
GLUE模式(PHP):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "php" 脚本;
GLUE模式(NodeJS):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "nodejs" 脚本;
GLUE模式(PowerShell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "PowerShell" 脚本;
- JobHandler运行模式为 "BEAN模式" 时生效对应执行器中新开发的JobHandler类“@JobHandler”注解自定义的value值
- JobHandler运行模式为 "BEAN模式" 时生效对应执行器中新开发的JobHandler类“@XxlJob”注解自定义的value值
- 执行参数:任务执行所需的参数;
高级配置:
@ -1469,7 +1503,7 @@ xxl-job-admin#com.xxl.job.admin.controller.JobApiController.callback
#### 5.5.4 执行器
执行器实际上是一个内嵌的Server默认端口9999配置项xxl.job.executor.port
在项目启动时,执行器会通过“@JobHandler”识别Spring容器中“Bean模式任务”以注解的value属性为key管理起来。
在项目启动时,执行器会通过“@XxlJob”识别Spring容器中“Bean模式任务”以注解的value属性为key管理起来。
“执行器”接收到“调度中心”的调度请求时如果任务类型为“Bean模式”将会匹配Spring容器中的“Bean模式任务”然后调用其execute方法执行任务逻辑。如果任务类型为“GLUE模式”将会加载GLue代码实例化Java对象注入依赖的Spring服务注意Glue代码中注入的Spring服务必须存在与该“执行器”项目的Spring容器中然后调用execute方法执行任务逻辑。
@ -1561,7 +1595,7 @@ echo "分片总数 total = $3"
- 1、执行器改为手动注册下线一半机器列表A组线上运行另一半机器列表B组
- 2、等待A组机器任务运行结束并编译上线执行器注册地址替换为A组
- 3、等待B组机器任务运行结束并编译上线执行器注册地址替换为A组+B组
操作结束;
操作结束;
### 5.13 任务执行结果说明
系统根据以下标准判断任务执行结果,可参考之。
@ -1589,7 +1623,7 @@ XXL-JOB是一个跨语言的任务调度平台主要体现在如下几个方
可以通过以下命令快速构建调度中心,并启动运行;
```
mvn clean package
docker build -t xuxueli/xxl-job-admin ./xxl-job-admin
docker build -t xuxueli/xxl-job-admin:{version} ./xxl-job-admin
docker run --name xxl-job-admin -p 8080:8080 -d xuxueli/xxl-job-admin
```
@ -1818,7 +1852,7 @@ Header
#### d、查看执行日志
```
说明:终止任务,滚动方式加载
说明:查看任务日志,滚动方式加载
------
@ -2341,17 +2375,39 @@ public void execute() {
- 5、【优化】任务线程名优化提升可读性与问题定位效率(ISSUE-2527)。
### 7.33 版本 v2.4.0 Release Notes[2023-03-23]
- 1、【优化】执行器任务Bean扫描逻辑优化解决懒加载注解失效问题
- 1、【优化】执行器任务Bean扫描逻辑优化解决懒加载注解失效问题
- 2、【优化】多个项目依赖升级至较新稳定版本涉及netty、groovy、spring、springboot、mybatis等
- 3、【修复】"CVE-2022-36157" 授权漏洞修复。
- 4、【修复】"CVE-2022-43183" SSRF漏洞修复。
- 3、【修复】漏洞修复包括"CVE-2022-36157" 授权漏洞修复;"CVE-2022-43183" SSRF漏洞修复
### 7.34 版本 v2.4.1 Release Notes[规划中]
### 7.34 版本 v2.4.1 Release Notes[2024-04-17]
- 1、【优化】多个项目依赖升级至较新稳定版本涉及netty、groovy、springboot、mybatis等
- 2、【修复】"CVE-2022-43402" groovy低版本漏洞修复。
- 3、【修复】调度日志页面XSS漏洞修复(ISSUE-3360)。
- 4、[规划中]注册节点,弹框分页展示;解决注册节点过多时无法展示问题;
- 2、【优化】执行器注册节点显示交互调整优化注册节点过多时展示不全体验
- 3、【修复】漏洞修复包括"CVE-2022-43402" groovy低版本漏洞修复"CVE-2024-29025" netty低版本漏洞修复"CVE-2024-3366" freemarker模板注入漏洞修复"CVE-2022-43183" 越权漏洞增强修复;
- 4、【修复】调度日志页面XSS问题修复(ISSUE-3360)。
### 7.35 版本 v2.4.2 Release Notes[2024-11-16]
- 1、【优化】调度中心任务Next计算逻辑调整避免Cron解析失败导致重复执行问题。
- 2、【优化】Cron解析组件代码重构微调健壮性提升
- 3、【优化】修改密码交互调整避免CSRF隐患
- 4、【优化】JdkSerializeTool流关闭逻辑优化
- 5、【优化】任务信息、执行日志API非功能设计完善避免越权隐患
- 6、【修复】漏洞修复包括 "CVE-2024-42681" 子任务越权漏洞修复、"CVE-2023-33779" 任务API越权问题修复
- 7、【升级】多个项目依赖升级至较新稳定版本涉及netty、groovy、gson、springboot、mybatis等
**备注:**
- a、“CVE-2024-38820”漏洞源自spring当前使用spring5.x及springboot2.x软件普遍受该问题影响。 该问题修复需要升级至spring6.x与springboot3.x同时需要升级JDK17如有诉求可自行升级。计划下个大版本升级spring及jdk版本解决该问题。
- b、本次升级数据模型及通讯协议向前兼容v2.4.*可无缝升级。
### 7.36 版本 v2.5.0 Release Notes[规划中]
- 1、【优化】框架基础守护线程异常处理逻辑优化避免极端情况下因Error导致调度终止问题
- 2、【优化】部分系统日志优化提升可读性
- 3、【重构】调度线程任务信息更新逻辑优化避免极端情况下已关闭任务被启动问题
- 5、【重构】执行器注册逻辑重构降低多调度中心地址时并发注册问题注册表“xxl_job_registry”新增唯一索引避免冗余注册信息存储
- 4、[规划中]升级springboot3.x解决2.x老版本漏洞类问题。注意springboot3.x依赖jdk17
- 5、[规划中]安全功能增强通讯加密参数改用加密数据避免AccessToken明文 降低token泄漏风险
- 6、[规划中]登陆态Token声称逻辑优化混淆登陆时间属性降低token泄漏风险
### TODO LIST
- 1、调度隔离调度中心针对不同执行器各自维护不同的调度和远程触发组件。

Binary file not shown.

Binary file not shown.

@ -1,5 +1,5 @@
#
# XXL-JOB v2.4.1-SNAPSHOT
# XXL-JOB
# Copyright (c) 2015-present, xuxueli.
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
@ -54,7 +54,8 @@ CREATE TABLE `xxl_job_log` (
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`),
KEY `idx_jobid_jobgroup` (`job_id`,`job_group`)
KEY `I_jobid_jobgroup` (`job_id`,`job_group`),
KEY `I_job_id` (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
@ -86,7 +87,7 @@ CREATE TABLE `xxl_job_registry` (
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
UNIQUE KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 KiB

After

Width:  |  Height:  |  Size: 286 KiB

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId>
<version>2.4.1-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
@ -17,31 +17,32 @@
</modules>
<properties>
<!-- env -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.test.skip>true</maven.test.skip>
<netty.version>4.1.106.Final</netty.version>
<gson.version>2.10.1</gson.version>
<spring.version>5.3.31</spring.version>
<!-- plugin -->
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.11.1</maven-javadoc-plugin.version>
<maven-gpg-plugin.version>3.2.7</maven-gpg-plugin.version>
<!-- base -->
<slf4j-api.version>2.0.16</slf4j-api.version>
<junit-jupiter.version>5.11.3</junit-jupiter.version>
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
<!-- net -->
<netty.version>4.1.115.Final</netty.version>
<gson.version>2.11.0</gson.version>
<!-- spring -->
<spring.version>5.3.39</spring.version>
<spring-boot.version>2.7.18</spring-boot.version>
<!-- db -->
<mybatis-spring-boot-starter.version>2.3.2</mybatis-spring-boot-starter.version>
<mysql-connector-j.version>8.3.0</mysql-connector-j.version>
<slf4j-api.version>2.0.11</slf4j-api.version>
<junit-jupiter.version>5.10.1</junit-jupiter.version>
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
<groovy.version>4.0.18</groovy.version>
<maven-source-plugin.version>3.3.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.6.3</maven-javadoc-plugin.version>
<maven-gpg-plugin.version>3.1.0</maven-gpg-plugin.version>
<mysql-connector-j.version>9.1.0</mysql-connector-j.version>
<!-- dynamic language -->
<groovy.version>4.0.24</groovy.version>
</properties>
<build>
@ -76,6 +77,12 @@
<profile>
<id>release</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>xxl-job-core</module>
</modules>
<build>
<plugins>
<!-- Source -->

@ -4,11 +4,15 @@
<parent>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId>
<version>2.4.1-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>xxl-job-admin</artifactId>
<packaging>jar</packaging>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
@ -89,13 +93,14 @@
</execution>
</executions>
</plugin>
<!-- docker -->
<plugin>
<!--<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<!-- made of '[a-z0-9-_.]' -->
&lt;!&ndash; made of '[a-z0-9-_.]' &ndash;&gt;
<imageName>${project.artifactId}:${project.version}</imageName>
<dockerDirectory>${project.basedir}</dockerDirectory>
<resources>
@ -106,7 +111,8 @@
</resource>
</resources>
</configuration>
</plugin>
</plugin>-->
</plugins>
</build>

@ -1,7 +1,7 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.service.LoginService;
import com.xxl.job.admin.service.impl.LoginService;
import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.core.biz.model.ReturnT;
import org.springframework.beans.propertyeditors.CustomDateEditor;

@ -1,5 +1,6 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.controller.interceptor.PermissionInterceptor;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLogGlue;
import com.xxl.job.admin.core.util.I18nUtil;
@ -43,7 +44,7 @@ public class JobCodeController {
}
// valid permission
JobInfoController.validPermission(request, jobInfo.getJobGroup());
PermissionInterceptor.validJobGroupPermission(request, jobInfo.getJobGroup());
// Glue类型-字典
model.addAttribute("GlueTypeEnum", GlueTypeEnum.values());
@ -55,7 +56,7 @@ public class JobCodeController {
@RequestMapping("/save")
@ResponseBody
public ReturnT<String> save(Model model, int id, String glueSource, String glueRemark) {
public ReturnT<String> save(HttpServletRequest request, int id, String glueSource, String glueRemark) {
// valid
if (glueRemark==null) {
return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobinfo_glue_remark")) );
@ -63,23 +64,26 @@ public class JobCodeController {
if (glueRemark.length()<4 || glueRemark.length()>100) {
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_remark_limit"));
}
XxlJobInfo exists_jobInfo = xxlJobInfoDao.loadById(id);
if (exists_jobInfo == null) {
XxlJobInfo existsJobInfo = xxlJobInfoDao.loadById(id);
if (existsJobInfo == null) {
return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
}
// valid permission
PermissionInterceptor.validJobGroupPermission(request, existsJobInfo.getJobGroup());
// update new code
exists_jobInfo.setGlueSource(glueSource);
exists_jobInfo.setGlueRemark(glueRemark);
exists_jobInfo.setGlueUpdatetime(new Date());
existsJobInfo.setGlueSource(glueSource);
existsJobInfo.setGlueRemark(glueRemark);
existsJobInfo.setGlueUpdatetime(new Date());
exists_jobInfo.setUpdateTime(new Date());
xxlJobInfoDao.update(exists_jobInfo);
existsJobInfo.setUpdateTime(new Date());
xxlJobInfoDao.update(existsJobInfo);
// log old code
XxlJobLogGlue xxlJobLogGlue = new XxlJobLogGlue();
xxlJobLogGlue.setJobId(exists_jobInfo.getId());
xxlJobLogGlue.setGlueType(exists_jobInfo.getGlueType());
xxlJobLogGlue.setJobId(existsJobInfo.getId());
xxlJobLogGlue.setGlueType(existsJobInfo.getGlueType());
xxlJobLogGlue.setGlueSource(glueSource);
xxlJobLogGlue.setGlueRemark(glueRemark);
@ -88,7 +92,7 @@ public class JobCodeController {
xxlJobLogGlueDao.save(xxlJobLogGlue);
// remove code backup more than 30
xxlJobLogGlueDao.removeOld(exists_jobInfo.getId(), 30);
xxlJobLogGlueDao.removeOld(existsJobInfo.getId(), 30);
return ReturnT.SUCCESS;
}

@ -1,6 +1,6 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.core.cron.CronExpression;
import com.xxl.job.admin.controller.interceptor.PermissionInterceptor;
import com.xxl.job.admin.core.exception.XxlJobException;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
@ -9,11 +9,8 @@ import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
import com.xxl.job.admin.core.thread.JobScheduleHelper;
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.service.LoginService;
import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;
@ -29,7 +26,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.util.*;
/**
@ -60,7 +56,7 @@ public class JobInfoController {
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
// filter group
List<XxlJobGroup> jobGroupList = filterJobGroupByRole(request, jobGroupList_all);
List<XxlJobGroup> jobGroupList = PermissionInterceptor.filterJobGroupByRole(request, jobGroupList_all);
if (jobGroupList==null || jobGroupList.size()==0) {
throw new XxlJobException(I18nUtil.getString("jobgroup_empty"));
}
@ -71,33 +67,6 @@ public class JobInfoController {
return "jobinfo/jobinfo.index";
}
public static List<XxlJobGroup> filterJobGroupByRole(HttpServletRequest request, List<XxlJobGroup> jobGroupList_all){
List<XxlJobGroup> jobGroupList = new ArrayList<>();
if (jobGroupList_all!=null && jobGroupList_all.size()>0) {
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
if (loginUser.getRole() == 1) {
jobGroupList = jobGroupList_all;
} else {
List<String> groupIdStrs = new ArrayList<>();
if (loginUser.getPermission()!=null && loginUser.getPermission().trim().length()>0) {
groupIdStrs = Arrays.asList(loginUser.getPermission().trim().split(","));
}
for (XxlJobGroup groupItem:jobGroupList_all) {
if (groupIdStrs.contains(String.valueOf(groupItem.getId()))) {
jobGroupList.add(groupItem);
}
}
}
}
return jobGroupList;
}
public static void validPermission(HttpServletRequest request, int jobGroup) {
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
if (!loginUser.validPermission(jobGroup)) {
throw new RuntimeException(I18nUtil.getString("system_permission_limit") + "[username="+ loginUser.getUsername() +"]");
}
}
@RequestMapping("/pageList")
@ResponseBody
public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
@ -109,14 +78,24 @@ public class JobInfoController {
@RequestMapping("/add")
@ResponseBody
public ReturnT<String> add(XxlJobInfo jobInfo) {
return xxlJobService.add(jobInfo);
public ReturnT<String> add(HttpServletRequest request, XxlJobInfo jobInfo) {
// valid permission
PermissionInterceptor.validJobGroupPermission(request, jobInfo.getJobGroup());
// opt
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
return xxlJobService.add(jobInfo, loginUser);
}
@RequestMapping("/update")
@ResponseBody
public ReturnT<String> update(XxlJobInfo jobInfo) {
return xxlJobService.update(jobInfo);
public ReturnT<String> update(HttpServletRequest request, XxlJobInfo jobInfo) {
// valid permission
PermissionInterceptor.validJobGroupPermission(request, jobInfo.getJobGroup());
// opt
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
return xxlJobService.update(jobInfo, loginUser);
}
@RequestMapping("/remove")
@ -139,15 +118,11 @@ public class JobInfoController {
@RequestMapping("/trigger")
@ResponseBody
//@PermissionLimit(limit = false)
public ReturnT<String> triggerJob(int id, String executorParam, String addressList) {
// force cover job param
if (executorParam == null) {
executorParam = "";
}
JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, executorParam, addressList);
return ReturnT.SUCCESS;
public ReturnT<String> triggerJob(HttpServletRequest request, int id, String executorParam, String addressList) {
// login user
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
// trigger
return xxlJobService.trigger(loginUser, id, executorParam, addressList);
}
@RequestMapping("/nextTriggerTime")
@ -170,7 +145,7 @@ public class JobInfoController {
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
logger.error("nextTriggerTime error. scheduleType = {}, scheduleConf= {}", scheduleType, scheduleConf, e);
return new ReturnT<List<String>>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type")+I18nUtil.getString("system_unvalid")) + e.getMessage());
}
return new ReturnT<List<String>>(result);

@ -1,5 +1,6 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.controller.interceptor.PermissionInterceptor;
import com.xxl.job.admin.core.complete.XxlJobCompleter;
import com.xxl.job.admin.core.exception.XxlJobException;
import com.xxl.job.admin.core.model.XxlJobGroup;
@ -56,7 +57,7 @@ public class JobLogController {
List<XxlJobGroup> jobGroupList_all = xxlJobGroupDao.findAll();
// filter group
List<XxlJobGroup> jobGroupList = JobInfoController.filterJobGroupByRole(request, jobGroupList_all);
List<XxlJobGroup> jobGroupList = PermissionInterceptor.filterJobGroupByRole(request, jobGroupList_all);
if (jobGroupList==null || jobGroupList.size()==0) {
throw new XxlJobException(I18nUtil.getString("jobgroup_empty"));
}
@ -73,7 +74,7 @@ public class JobLogController {
model.addAttribute("jobInfo", jobInfo);
// valid permission
JobInfoController.validPermission(request, jobInfo.getJobGroup());
PermissionInterceptor.validJobGroupPermission(request, jobInfo.getJobGroup());
}
return "joblog/joblog.index";
@ -94,7 +95,7 @@ public class JobLogController {
int jobGroup, int jobId, int logStatus, String filterTime) {
// valid permission
JobInfoController.validPermission(request, jobGroup); // 仅管理员支持查询全部;普通用户仅支持查询有权限的 jobGroup
PermissionInterceptor.validJobGroupPermission(request, jobGroup); // 仅管理员支持查询全部;普通用户仅支持查询有权限的 jobGroup
// parse param
Date triggerTimeStart = null;
@ -206,8 +207,11 @@ public class JobLogController {
@RequestMapping("/clearLog")
@ResponseBody
public ReturnT<String> clearLog(int jobGroup, int jobId, int type){
public ReturnT<String> clearLog(HttpServletRequest request, int jobGroup, int jobId, int type){
// valid permission
PermissionInterceptor.validJobGroupPermission(request, jobGroup);
// opt
Date clearBeforeTime = null;
int clearBeforeNum = 0;
if (type == 1) {

@ -1,12 +1,12 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.controller.interceptor.PermissionInterceptor;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobUserDao;
import com.xxl.job.admin.service.LoginService;
import com.xxl.job.core.biz.model.ReturnT;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@ -27,7 +27,7 @@ import java.util.Map;
*/
@Controller
@RequestMapping("/user")
public class UserController {
public class JobUserController {
@Resource
private XxlJobUserDao xxlJobUserDao;
@ -112,7 +112,7 @@ public class UserController {
public ReturnT<String> update(HttpServletRequest request, XxlJobUser xxlJobUser) {
// avoid opt login seft
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
if (loginUser.getUsername().equals(xxlJobUser.getUsername())) {
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("user_update_loginuser_limit"));
}
@ -140,7 +140,7 @@ public class UserController {
public ReturnT<String> remove(HttpServletRequest request, int id) {
// avoid opt login seft
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
if (loginUser.getId() == id) {
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("user_update_loginuser_limit"));
}
@ -151,11 +151,14 @@ public class UserController {
@RequestMapping("/updatePwd")
@ResponseBody
public ReturnT<String> updatePwd(HttpServletRequest request, String password){
public ReturnT<String> updatePwd(HttpServletRequest request, String password, String oldPassword){
// valid password
// valid
if (oldPassword==null || oldPassword.trim().length()==0){
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("system_please_input") + I18nUtil.getString("change_pwd_field_oldpwd"));
}
if (password==null || password.trim().length()==0){
return new ReturnT<String>(ReturnT.FAIL.getCode(), "密码不可为空");
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("system_please_input") + I18nUtil.getString("change_pwd_field_oldpwd"));
}
password = password.trim();
if (!(password.length()>=4 && password.length()<=20)) {
@ -163,13 +166,17 @@ public class UserController {
}
// md5 password
String md5OldPassword = DigestUtils.md5DigestAsHex(oldPassword.getBytes());
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
// update pwd
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY);
// do write
// valid old pwd
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
XxlJobUser existUser = xxlJobUserDao.loadByUserName(loginUser.getUsername());
if (!md5OldPassword.equals(existUser.getPassword())) {
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("change_pwd_field_oldpwd") + I18nUtil.getString("system_unvalid"));
}
// write new
existUser.setPassword(md5Password);
xxlJobUserDao.update(existUser);

@ -1,9 +1,10 @@
package com.xxl.job.admin.controller.interceptor;
import com.xxl.job.admin.controller.annotation.PermissionLimit;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.service.LoginService;
import com.xxl.job.admin.service.impl.LoginService;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
@ -11,6 +12,9 @@ import org.springframework.web.servlet.AsyncHandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
@ -50,10 +54,66 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
if (needAdminuser && loginUser.getRole()!=1) {
throw new RuntimeException(I18nUtil.getString("system_permission_limit"));
}
request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser);
request.setAttribute(LoginService.LOGIN_IDENTITY_KEY, loginUser); // set loginUser, with request
}
return true; // proceed with the next interceptor
}
// -------------------- permission tool --------------------
/**
* get loginUser
*
* @param request
* @return
*/
public static XxlJobUser getLoginUser(HttpServletRequest request){
XxlJobUser loginUser = (XxlJobUser) request.getAttribute(LoginService.LOGIN_IDENTITY_KEY); // get loginUser, with request
return loginUser;
}
/**
* valid permission by JobGroup
*
* @param request
* @param jobGroup
*/
public static void validJobGroupPermission(HttpServletRequest request, int jobGroup) {
XxlJobUser loginUser = getLoginUser(request);
if (!loginUser.validPermission(jobGroup)) {
throw new RuntimeException(I18nUtil.getString("system_permission_limit") + "[username="+ loginUser.getUsername() +"]");
}
}
/**
* filter XxlJobGroup by role
*
* @param request
* @param jobGroupList_all
* @return
*/
public static List<XxlJobGroup> filterJobGroupByRole(HttpServletRequest request, List<XxlJobGroup> jobGroupList_all){
List<XxlJobGroup> jobGroupList = new ArrayList<>();
if (jobGroupList_all!=null && jobGroupList_all.size()>0) {
XxlJobUser loginUser = PermissionInterceptor.getLoginUser(request);
if (loginUser.getRole() == 1) {
jobGroupList = jobGroupList_all;
} else {
List<String> groupIdStrs = new ArrayList<>();
if (loginUser.getPermission()!=null && loginUser.getPermission().trim().length()>0) {
groupIdStrs = Arrays.asList(loginUser.getPermission().trim().split(","));
}
for (XxlJobGroup groupItem:jobGroupList_all) {
if (groupIdStrs.contains(String.valueOf(groupItem.getId()))) {
jobGroupList.add(groupItem);
}
}
}
}
return jobGroupList;
}
}

@ -55,6 +55,10 @@ public class XxlJobCompleter {
String[] childJobIds = xxlJobInfo.getChildJobId().split(",");
for (int i = 0; i < childJobIds.length; i++) {
int childJobId = (childJobIds[i]!=null && childJobIds[i].trim().length()>0 && isNumeric(childJobIds[i]))?Integer.valueOf(childJobIds[i]):-1;
if (childJobId == xxlJobLog.getJobId()) {
logger.info("jobid {} is self, ignore it.", childJobId);
continue;
}
if (childJobId > 0) {
JobTriggerPoolHelper.trigger(childJobId, TriggerTypeEnum.PARENT, -1, null, null, null);

@ -363,9 +363,9 @@ public final class CronExpression implements Serializable, Cloneable {
// the second immediately following it.
while (difference == 1000) {
newDate = getTimeAfter(lastDate);
if(newDate == null)
if(newDate == null) {
break;
}
difference = newDate.getTime() - lastDate.getTime();
if (difference == 1000) {
@ -668,8 +668,9 @@ public final class CronExpression implements Serializable, Cloneable {
if(c == '-') {
ValueSet vs = getValue(0, s, i+1);
lastdayOffset = vs.value;
if(lastdayOffset > 30)
throw new ParseException("Offset from last day must be <= 30", i+1);
if(lastdayOffset > 30) {
throw new ParseException("Offset from last day must be <= 30", i + 1);
}
i = vs.pos;
}
if(s.length() > i) {
@ -732,8 +733,9 @@ public final class CronExpression implements Serializable, Cloneable {
if (c == 'L') {
if (type == DAY_OF_WEEK) {
if(val < 1 || val > 7)
if(val < 1 || val > 7) {
throw new ParseException("Day-of-Week values must be between 1 and 7", -1);
}
lastdayOfWeek = true;
} else {
throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i);
@ -750,8 +752,9 @@ public final class CronExpression implements Serializable, Cloneable {
} else {
throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i);
}
if(val > 31)
if(val > 31) {
throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i);
}
TreeSet<Integer> set = getSet(type);
set.add(val);
i++;

@ -65,7 +65,7 @@ public class JobCompleteHelper {
// wait for JobTriggerPoolHelper-init
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -92,7 +92,7 @@ public class JobCompleteHelper {
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
}
@ -100,7 +100,7 @@ public class JobCompleteHelper {
try {
TimeUnit.SECONDS.sleep(60);
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -127,7 +127,7 @@ public class JobCompleteHelper {
monitorThread.interrupt();
try {
monitorThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}

@ -71,7 +71,7 @@ public class JobFailMonitorHelper {
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job fail monitor thread error:{}", e);
}
@ -79,7 +79,7 @@ public class JobFailMonitorHelper {
try {
TimeUnit.SECONDS.sleep(10);
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -102,7 +102,7 @@ public class JobFailMonitorHelper {
monitorThread.interrupt();
try {
monitorThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}

@ -87,7 +87,7 @@ public class JobLogReportHelper {
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job log report thread error:{}", e);
}
@ -121,7 +121,7 @@ public class JobLogReportHelper {
try {
TimeUnit.MINUTES.sleep(1);
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -144,7 +144,7 @@ public class JobLogReportHelper {
logrThread.interrupt();
try {
logrThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}

@ -107,14 +107,14 @@ public class JobRegistryHelper {
XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().update(group);
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
}
}
try {
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(">>>>>>>>>>> xxl-job, job registry monitor thread error:{}", e);
}
@ -138,7 +138,7 @@ public class JobRegistryHelper {
registryMonitorThread.interrupt();
try {
registryMonitorThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@ -159,13 +159,19 @@ public class JobRegistryHelper {
registryOrRemoveThreadPool.execute(new Runnable() {
@Override
public void run() {
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryUpdate(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
// 0-fail; 1-save suc; 2-update suc;
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registrySaveOrUpdate(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
if (ret == 1) {
// fresh (add)
freshGroupRegistryInfo(registryParam);
}
/*int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryUpdate(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
if (ret < 1) {
XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registrySave(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue(), new Date());
// fresh
freshGroupRegistryInfo(registryParam);
}
}*/
}
});
@ -187,7 +193,7 @@ public class JobRegistryHelper {
public void run() {
int ret = XxlJobAdminConfig.getAdminConfig().getXxlJobRegistryDao().registryDelete(registryParam.getRegistryGroup(), registryParam.getRegistryKey(), registryParam.getRegistryValue());
if (ret > 0) {
// fresh
// fresh (delete)
freshGroupRegistryInfo(registryParam);
}
}

@ -11,7 +11,6 @@ import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@ -44,7 +43,7 @@ public class JobScheduleHelper {
try {
TimeUnit.MILLISECONDS.sleep(5000 - System.currentTimeMillis()%1000 );
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@ -150,7 +149,7 @@ public class JobScheduleHelper {
// tx stop
} catch (Exception e) {
} catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#scheduleThread error:{}", e);
}
@ -160,21 +159,21 @@ public class JobScheduleHelper {
if (conn != null) {
try {
conn.commit();
} catch (SQLException e) {
} catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
}
try {
conn.setAutoCommit(connAutoCommit);
} catch (SQLException e) {
} catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
}
try {
conn.close();
} catch (SQLException e) {
} catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@ -185,7 +184,7 @@ public class JobScheduleHelper {
if (null != preparedStatement) {
try {
preparedStatement.close();
} catch (SQLException e) {
} catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@ -200,7 +199,7 @@ public class JobScheduleHelper {
try {
// pre-read period: success > scan each second; fail > skip this period;
TimeUnit.MILLISECONDS.sleep((preReadSuc?1000:PRE_READ_MS) - System.currentTimeMillis()%1000);
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!scheduleThreadToStop) {
logger.error(e.getMessage(), e);
}
@ -227,7 +226,7 @@ public class JobScheduleHelper {
// align second
try {
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000);
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!ringThreadToStop) {
logger.error(e.getMessage(), e);
}
@ -255,7 +254,7 @@ public class JobScheduleHelper {
// clear
ringItemData.clear();
}
} catch (Exception e) {
} catch (Throwable e) {
if (!ringThreadToStop) {
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread error:{}", e);
}
@ -269,18 +268,29 @@ public class JobScheduleHelper {
ringThread.start();
}
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) throws Exception {
private void refreshNextValidTime(XxlJobInfo jobInfo, Date fromTime) {
try {
Date nextValidTime = generateNextValidTime(jobInfo, fromTime);
if (nextValidTime != null) {
jobInfo.setTriggerLastTime(jobInfo.getTriggerNextTime());
jobInfo.setTriggerNextTime(nextValidTime.getTime());
} else {
// generateNextValidTime fail, stop job
jobInfo.setTriggerStatus(0);
jobInfo.setTriggerLastTime(0);
jobInfo.setTriggerNextTime(0);
logger.warn(">>>>>>>>>>> xxl-job, refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}",
logger.error(">>>>>>>>>>> xxl-job, refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}",
jobInfo.getId(), jobInfo.getScheduleType(), jobInfo.getScheduleConf());
}
} catch (Throwable e) {
// generateNextValidTime error, stop job
jobInfo.setTriggerStatus(0);
jobInfo.setTriggerLastTime(0);
jobInfo.setTriggerNextTime(0);
logger.error(">>>>>>>>>>> xxl-job, refreshNextValidTime error for job: jobId={}, scheduleType={}, scheduleConf={}",
jobInfo.getId(), jobInfo.getScheduleType(), jobInfo.getScheduleConf(), e);
}
}
private void pushTimeRing(int ringSecond, int jobId){
@ -301,7 +311,7 @@ public class JobScheduleHelper {
scheduleThreadToStop = true;
try {
TimeUnit.SECONDS.sleep(1); // wait
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
if (scheduleThread.getState() != Thread.State.TERMINATED){
@ -309,7 +319,7 @@ public class JobScheduleHelper {
scheduleThread.interrupt();
try {
scheduleThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@ -328,7 +338,7 @@ public class JobScheduleHelper {
if (hasRingData) {
try {
TimeUnit.SECONDS.sleep(8);
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@ -337,7 +347,7 @@ public class JobScheduleHelper {
ringThreadToStop = true;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
if (ringThread.getState() != Thread.State.TERMINATED){
@ -345,7 +355,7 @@ public class JobScheduleHelper {
ringThread.interrupt();
try {
ringThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}

@ -93,7 +93,7 @@ public class JobTriggerPoolHelper {
try {
// do trigger
XxlJobTrigger.trigger(jobId, triggerType, failRetryCount, executorShardingParam, executorParam, addressList);
} catch (Exception e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
} finally {

@ -41,8 +41,21 @@ public interface XxlJobInfoDao {
public int findAllCount();
/**
* find schedule job, limit "trigger_status = 1"
*
* @param maxNextTime
* @param pagesize
* @return
*/
public List<XxlJobInfo> scheduleJobQuery(@Param("maxNextTime") long maxNextTime, @Param("pagesize") int pagesize );
/**
* update schedule job, limit "trigger_status = 1"avoid stopping tasks from being opened
*
* @param xxlJobInfo
* @return
*/
public int scheduleUpdate(XxlJobInfo xxlJobInfo);

@ -21,16 +21,21 @@ public interface XxlJobRegistryDao {
public List<XxlJobRegistry> findAll(@Param("timeout") int timeout,
@Param("nowTime") Date nowTime);
public int registryUpdate(@Param("registryGroup") String registryGroup,
public int registrySaveOrUpdate(@Param("registryGroup") String registryGroup,
@Param("registryKey") String registryKey,
@Param("registryValue") String registryValue,
@Param("updateTime") Date updateTime);
public int registrySave(@Param("registryGroup") String registryGroup,
/*public int registryUpdate(@Param("registryGroup") String registryGroup,
@Param("registryKey") String registryKey,
@Param("registryValue") String registryValue,
@Param("updateTime") Date updateTime);
public int registrySave(@Param("registryGroup") String registryGroup,
@Param("registryKey") String registryKey,
@Param("registryValue") String registryValue,
@Param("updateTime") Date updateTime);*/
public int registryDelete(@Param("registryGroup") String registryGroup,
@Param("registryKey") String registryKey,
@Param("registryValue") String registryValue);

@ -2,6 +2,7 @@ package com.xxl.job.admin.service;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.core.biz.model.ReturnT;
import java.util.Date;
@ -33,7 +34,7 @@ public interface XxlJobService {
* @param jobInfo
* @return
*/
public ReturnT<String> add(XxlJobInfo jobInfo);
public ReturnT<String> add(XxlJobInfo jobInfo, XxlJobUser loginUser);
/**
* update job
@ -41,7 +42,7 @@ public interface XxlJobService {
* @param jobInfo
* @return
*/
public ReturnT<String> update(XxlJobInfo jobInfo);
public ReturnT<String> update(XxlJobInfo jobInfo, XxlJobUser loginUser);
/**
* remove job
@ -67,6 +68,17 @@ public interface XxlJobService {
*/
public ReturnT<String> stop(int id);
/**
* trigger
*
* @param loginUser
* @param jobId
* @param executorParam
* @param addressList
* @return
*/
public ReturnT<String> trigger(XxlJobUser loginUser, int jobId, String executorParam, String addressList);
/**
* dashboard info
*

@ -1,4 +1,4 @@
package com.xxl.job.admin.service;
package com.xxl.job.admin.service.impl;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.core.util.CookieUtil;
@ -6,7 +6,7 @@ import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.core.util.JacksonUtil;
import com.xxl.job.admin.dao.XxlJobUserDao;
import com.xxl.job.core.biz.model.ReturnT;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import javax.annotation.Resource;
@ -17,7 +17,7 @@ import java.math.BigInteger;
/**
* @author xuxueli 2019-05-04 22:13:264
*/
@Configuration
@Service
public class LoginService {
public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY";
@ -26,6 +26,8 @@ public class LoginService {
private XxlJobUserDao xxlJobUserDao;
// ---------------------- token tool ----------------------
private String makeToken(XxlJobUser xxlJobUser){
String tokenJson = JacksonUtil.writeValueAsString(xxlJobUser);
String tokenHex = new BigInteger(tokenJson.getBytes()).toString(16);
@ -41,6 +43,8 @@ public class LoginService {
}
// ---------------------- login tool, with cookie and db ----------------------
public ReturnT<String> login(HttpServletRequest request, HttpServletResponse response, String username, String password, boolean ifRemember){
// param

@ -4,10 +4,13 @@ import com.xxl.job.admin.core.cron.CronExpression;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLogReport;
import com.xxl.job.admin.core.model.XxlJobUser;
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
import com.xxl.job.admin.core.thread.JobScheduleHelper;
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
import com.xxl.job.admin.core.util.I18nUtil;
import com.xxl.job.admin.dao.*;
import com.xxl.job.admin.service.XxlJobService;
@ -58,7 +61,7 @@ public class XxlJobServiceImpl implements XxlJobService {
}
@Override
public ReturnT<String> add(XxlJobInfo jobInfo) {
public ReturnT<String> add(XxlJobInfo jobInfo, XxlJobUser loginUser) {
// valid base
XxlJobGroup group = xxlJobGroupDao.load(jobInfo.getJobGroup());
@ -128,6 +131,10 @@ public class XxlJobServiceImpl implements XxlJobService {
return new ReturnT<String>(ReturnT.FAIL_CODE,
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
}
if (!loginUser.validPermission(childJobInfo.getJobGroup())) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_permission_limit")), childJobIdItem));
}
} else {
return new ReturnT<String>(ReturnT.FAIL_CODE,
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
@ -166,7 +173,7 @@ public class XxlJobServiceImpl implements XxlJobService {
}
@Override
public ReturnT<String> update(XxlJobInfo jobInfo) {
public ReturnT<String> update(XxlJobInfo jobInfo, XxlJobUser loginUser) {
// valid base
if (jobInfo.getJobDesc()==null || jobInfo.getJobDesc().trim().length()==0) {
@ -215,11 +222,19 @@ public class XxlJobServiceImpl implements XxlJobService {
String[] childJobIds = jobInfo.getChildJobId().split(",");
for (String childJobIdItem: childJobIds) {
if (childJobIdItem!=null && childJobIdItem.trim().length()>0 && isNumeric(childJobIdItem)) {
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(Integer.parseInt(childJobIdItem));
int childJobId = Integer.parseInt(childJobIdItem);
XxlJobInfo childJobInfo = xxlJobInfoDao.loadById(childJobId);
if (childJobId == jobInfo.getId()) {
return new ReturnT<String>(ReturnT.FAIL_CODE, (I18nUtil.getString("jobinfo_field_childJobId")+"("+childJobId+")"+I18nUtil.getString("system_unvalid")) );
}
if (childJobInfo==null) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_not_found")), childJobIdItem));
}
if (!loginUser.validPermission(childJobInfo.getJobGroup())) {
return new ReturnT<String>(ReturnT.FAIL_CODE,
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_permission_limit")), childJobIdItem));
}
} else {
return new ReturnT<String>(ReturnT.FAIL_CODE,
MessageFormat.format((I18nUtil.getString("jobinfo_field_childJobId")+"({0})"+I18nUtil.getString("system_unvalid")), childJobIdItem));
@ -345,6 +360,42 @@ public class XxlJobServiceImpl implements XxlJobService {
return ReturnT.SUCCESS;
}
@Override
public ReturnT<String> trigger(XxlJobUser loginUser, int jobId, String executorParam, String addressList) {
// permission
if (loginUser == null) {
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("system_permission_limit"));
}
XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(jobId);
if (xxlJobInfo == null) {
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
}
if (!hasPermission(loginUser, xxlJobInfo.getJobGroup())) {
return new ReturnT<String>(ReturnT.FAIL.getCode(), I18nUtil.getString("system_permission_limit"));
}
// force cover job param
if (executorParam == null) {
executorParam = "";
}
JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.MANUAL, -1, null, executorParam, addressList);
return ReturnT.SUCCESS;
}
private boolean hasPermission(XxlJobUser loginUser, int jobGroup){
if (loginUser.getRole() == 1) {
return true;
}
List<String> groupIdStrs = new ArrayList<>();
if (loginUser.getPermission()!=null && loginUser.getPermission().trim().length()>0) {
groupIdStrs = Arrays.asList(loginUser.getPermission().trim().split(","));
}
return groupIdStrs.contains(String.valueOf(jobGroup));
}
@Override
public Map<String, Object> dashboardInfo() {

@ -17,6 +17,7 @@ spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########
spring.freemarker.settings.new_builtin_class_resolver=safer
### mybatis
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml

@ -1,6 +1,6 @@
admin_name=Scheduling Center
admin_name_full=Distributed Task Scheduling Platform XXL-JOB
admin_version=2.4.1-SNAPSHOT
admin_version=2.5.0-SNAPSHOT
admin_i18n=en
## system
@ -91,6 +91,7 @@ logout_fail=Logout fail
## change pwd
change_pwd=Change password
change_pwd_suc_to_logout=Change password successful, about to log out login
change_pwd_field_oldpwd=old password
change_pwd_field_newpwd=new password
## dashboard

@ -1,6 +1,6 @@
admin_name=任务调度中心
admin_name_full=分布式任务调度平台XXL-JOB
admin_version=2.4.1-SNAPSHOT
admin_version=2.5.0-SNAPSHOT
admin_i18n=
## system
@ -91,6 +91,7 @@ logout_fail=注销失败
## change pwd
change_pwd=修改密码
change_pwd_suc_to_logout=修改密码成功,即将注销登陆
change_pwd_field_oldpwd=旧密码
change_pwd_field_newpwd=新密码
## dashboard

@ -1,6 +1,6 @@
admin_name=任務調度中心
admin_name_full=分布式任務調度平臺XXL-JOB
admin_version=2.4.1-SNAPSHOT
admin_version=2.5.0-SNAPSHOT
admin_i18n=
## system
@ -91,6 +91,7 @@ logout_fail=登出失敗
## change pwd
change_pwd=修改密碼
change_pwd_suc_to_logout=修改密碼成功,即將登出
change_pwd_field_oldpwd=舊密碼
change_pwd_field_newpwd=新密碼
## dashboard

@ -232,9 +232,12 @@
UPDATE xxl_job_info
SET
trigger_last_time = #{triggerLastTime},
trigger_next_time = #{triggerNextTime},
trigger_status = #{triggerStatus}
trigger_next_time = #{triggerNextTime}
<if test="triggerStatus == 0">
, trigger_status = #{triggerStatus}
</if>
WHERE id = #{id}
AND trigger_status = 1
</update>
</mapper>

@ -178,9 +178,9 @@
<select id="findLogReport" resultType="java.util.Map" >
SELECT
COUNT(handle_code) triggerDayCount,
SUM(CASE WHEN (trigger_code in (0, 200) and handle_code = 0) then 1 else 0 end) as triggerDayCountRunning,
SUM(CASE WHEN handle_code = 200 then 1 else 0 end) as triggerDayCountSuc
COUNT(handle_code) "triggerDayCount",
SUM(CASE WHEN (trigger_code in (0, 200) and handle_code = 0) then 1 else 0 end) as "triggerDayCountRunning",
SUM(CASE WHEN handle_code = 200 then 1 else 0 end) as "triggerDayCountSuc"
FROM xxl_job_log
WHERE trigger_time BETWEEN #{from} and #{to}
</select>

@ -39,6 +39,14 @@
WHERE t.update_time <![CDATA[ > ]]> DATE_ADD(#{nowTime},INTERVAL -#{timeout} SECOND)
</select>
<insert id="registrySaveOrUpdate" >
INSERT INTO xxl_job_registry( `registry_group` , `registry_key` , `registry_value`, `update_time`)
VALUES( #{registryGroup} , #{registryKey} , #{registryValue}, #{updateTime})
ON DUPLICATE KEY UPDATE
`update_time` = #{updateTime}
</insert>
<!--
<update id="registryUpdate" >
UPDATE xxl_job_registry
SET `update_time` = #{updateTime}
@ -51,6 +59,7 @@
INSERT INTO xxl_job_registry( `registry_group` , `registry_key` , `registry_value`, `update_time`)
VALUES( #{registryGroup} , #{registryKey} , #{registryValue}, #{updateTime})
</insert>
-->
<delete id="registryDelete" >
DELETE FROM xxl_job_registry

@ -99,15 +99,23 @@ $(function(){
errorClass : 'help-block',
focusInvalid : true,
rules : {
oldPassword : {
required : true ,
rangelength:[4,20]
},
password : {
required : true ,
rangelength:[4,50]
rangelength:[4,20]
}
},
messages : {
oldPassword : {
required : I18n.system_please_input +I18n.change_pwd_field_oldpwd,
rangelength : "密码长度限制为4~20"
},
password : {
required : '' ,
rangelength : "密码长度限制为4~50"
required : I18n.system_please_input +I18n.change_pwd_field_newpwd,
rangelength : "密码长度限制为4~20"
}
},
highlight : function(element) {

@ -123,7 +123,7 @@ $(function() {
var id = $(this).attr("_id");
var row = tableData['key'+id];
var html = '<div>';
/*var html = '<div>';
if (row.registryList) {
for (var index in row.registryList) {
html += (parseInt(index)+1) + '. <span class="badge bg-green" >' + row.registryList[index] + '</span><br>';
@ -135,8 +135,19 @@ $(function() {
title: I18n.jobinfo_opt_registryinfo ,
btn: [ I18n.system_ok ],
content: html
});
});*/
var html = '<table class="table table-bordered"><tbody>';
if (row.registryList) {
for (var index in row.registryList) {
html += '<tr><th>' + (parseInt(index)+1) + '</th>';
html += '<th><span class="badge bg-green" >' + row.registryList[index] + '</span></th><tr>';
}
}
html += '</tbody></table>';
$('#showRegistryListModal .data').html(html);
$('#showRegistryListModal').modal({backdrop: false, keyboard: false}).modal('show');
});

@ -16,12 +16,12 @@ $(function(){
userName : {
required : true ,
minlength: 4,
maxlength: 18
maxlength: 20
},
password : {
required : true ,
minlength: 4,
maxlength: 18
maxlength: 20
}
},
messages : {
@ -32,7 +32,7 @@ $(function(){
password : {
required : I18n.login_password_empty ,
minlength : I18n.login_password_lt_4
/*,maxlength:"登录密码不应超过18位"*/
/*,maxlength:"登录密码不应超过20位"*/
}
},
highlight : function(element) {

@ -107,9 +107,13 @@
</div>
<div class="modal-body">
<form class="form-horizontal form" role="form" >
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.change_pwd_field_oldpwd}<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" name="oldPassword" placeholder="${I18n.system_please_input} ${I18n.change_pwd_field_oldpwd}" maxlength="20" ></div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.change_pwd_field_newpwd}<font color="red">*</font></label>
<div class="col-sm-10"><input type="text" class="form-control" name="password" placeholder="${I18n.system_please_input} ${I18n.change_pwd_field_newpwd}" maxlength="18" ></div>
<div class="col-sm-10"><input type="text" class="form-control" name="password" placeholder="${I18n.system_please_input} ${I18n.change_pwd_field_newpwd}" maxlength="20" ></div>
</div>
<hr>
<div class="form-group">

@ -70,6 +70,25 @@
</section>
</div>
<!-- . -->
<div class="modal fade" id="showRegistryListModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" >${I18n.jobinfo_opt_registryinfo}</h4>
</div>
<div class="modal-body">
<div class="data" style="word-wrap: break-word;"></div>
</div>
<div class="modal-footer">
<div class="text-center" >
<button type="button" class="btn btn-info ok" data-dismiss="modal" >${I18n.system_ok}</button>
</div>
</div>
</div>
</div>
</div>
<!-- . -->
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog ">

@ -15,11 +15,11 @@
<div class="login-box-body">
<p class="login-box-msg">${I18n.admin_name}</p>
<div class="form-group has-feedback">
<input type="text" name="userName" class="form-control" placeholder="${I18n.login_username_placeholder}" maxlength="18" >
<input type="text" name="userName" class="form-control" placeholder="${I18n.login_username_placeholder}" maxlength="20" >
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" name="password" class="form-control" placeholder="${I18n.login_password_placeholder}" maxlength="18" >
<input type="password" name="password" class="form-control" placeholder="${I18n.login_password_placeholder}" maxlength="20" >
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">

@ -1,6 +1,6 @@
package com.xxl.job.admin.controller;
import com.xxl.job.admin.service.LoginService;
import com.xxl.job.admin.service.impl.LoginService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;

@ -8,6 +8,7 @@ import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class XxlJobRegistryDaoTest {
@ -17,14 +18,32 @@ public class XxlJobRegistryDaoTest {
@Test
public void test(){
int ret = xxlJobRegistryDao.registryUpdate("g1", "k1", "v1", new Date());
int ret = xxlJobRegistryDao.registrySaveOrUpdate("g1", "k1", "v1", new Date());
/*int ret = xxlJobRegistryDao.registryUpdate("g1", "k1", "v1", new Date());
if (ret < 1) {
ret = xxlJobRegistryDao.registrySave("g1", "k1", "v1", new Date());
}
}*/
List<XxlJobRegistry> list = xxlJobRegistryDao.findAll(1, new Date());
int ret2 = xxlJobRegistryDao.removeDead(Arrays.asList(1));
}
@Test
public void test2() throws InterruptedException {
for (int i = 0; i < 100; i++) {
new Thread(()->{
int ret = xxlJobRegistryDao.registrySaveOrUpdate("g1", "k1", "v1", new Date());
System.out.println(ret);
/*int ret = xxlJobRegistryDao.registryUpdate("g1", "k1", "v1", new Date());
if (ret < 1) {
ret = xxlJobRegistryDao.registrySave("g1", "k1", "v1", new Date());
}*/
}).start();
}
TimeUnit.SECONDS.sleep(10);
}
}

@ -4,7 +4,7 @@
<parent>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId>
<version>2.4.1-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>xxl-job-core</artifactId>
<packaging>jar</packaging>

@ -89,14 +89,14 @@ public class EmbedServer {
} catch (InterruptedException e) {
logger.info(">>>>>>>>>>> xxl-job remoting server stop.");
} catch (Exception e) {
} catch (Throwable e) {
logger.error(">>>>>>>>>>> xxl-job remoting server error.", e);
} finally {
// stop
try {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
} catch (Exception e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@ -200,7 +200,7 @@ public class EmbedServer {
default:
return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping(" + uri + ") not found.");
}
} catch (Exception e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
return new ReturnT<String>(ReturnT.FAIL_CODE, "request error:" + ThrowableUtil.toString(e));
}

@ -53,12 +53,12 @@ public class ExecutorRegistryThread {
} else {
logger.info(">>>>>>>>>>> xxl-job registry fail, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
}
} catch (Exception e) {
} catch (Throwable e) {
logger.info(">>>>>>>>>>> xxl-job registry error, registryParam:{}", registryParam, e);
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -69,7 +69,7 @@ public class ExecutorRegistryThread {
if (!toStop) {
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
}
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!toStop) {
logger.warn(">>>>>>>>>>> xxl-job, executor registry thread interrupted, error msg:{}", e.getMessage());
}
@ -89,7 +89,7 @@ public class ExecutorRegistryThread {
} else {
logger.info(">>>>>>>>>>> xxl-job registry-remove fail, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.info(">>>>>>>>>>> xxl-job registry-remove error, registryParam:{}", registryParam, e);
}
@ -97,7 +97,7 @@ public class ExecutorRegistryThread {
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -119,7 +119,7 @@ public class ExecutorRegistryThread {
registryThread.interrupt();
try {
registryThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}

@ -81,7 +81,7 @@ public class JobLogFileCleanThread {
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -90,7 +90,7 @@ public class JobLogFileCleanThread {
try {
TimeUnit.DAYS.sleep(1);
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}

@ -36,7 +36,7 @@ public class JobThread extends Thread{
private String stopReason;
private boolean running = false; // if running job
private int idleTimes = 0; // idel times
private int idleTimes = 0; // idle times
public JobThread(int jobId, IJobHandler handler) {
@ -185,7 +185,7 @@ public class JobThread extends Thread{
} else {
if (idleTimes > 30) {
if(triggerQueue.size() == 0) { // avoid concurrent trigger causes jobId-lost
XxlJobExecutor.removeJobThread(jobId, "excutor idel times over limit.");
XxlJobExecutor.removeJobThread(jobId, "excutor idle times over limit.");
}
}
}

@ -76,7 +76,7 @@ public class TriggerCallbackThread {
doCallback(callbackParamList);
}
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -90,7 +90,7 @@ public class TriggerCallbackThread {
if (callbackParamList!=null && callbackParamList.size()>0) {
doCallback(callbackParamList);
}
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -111,7 +111,7 @@ public class TriggerCallbackThread {
while(!toStop){
try {
retryFailCallbackFile();
} catch (Exception e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -119,7 +119,7 @@ public class TriggerCallbackThread {
}
try {
TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
} catch (InterruptedException e) {
} catch (Throwable e) {
if (!toStop) {
logger.error(e.getMessage(), e);
}
@ -139,7 +139,7 @@ public class TriggerCallbackThread {
triggerCallbackThread.interrupt();
try {
triggerCallbackThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@ -149,7 +149,7 @@ public class TriggerCallbackThread {
triggerRetryCallbackThread.interrupt();
try {
triggerRetryCallbackThread.join();
} catch (InterruptedException e) {
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
@ -173,7 +173,7 @@ public class TriggerCallbackThread {
} else {
callbackLog(callbackParamList, "<br>----------- xxl-job job callback fail, callbackResult:" + callbackResult);
}
} catch (Exception e) {
} catch (Throwable e) {
callbackLog(callbackParamList, "<br>----------- xxl-job job callback error, errorMsg:" + e.getMessage());
}
}

@ -51,16 +51,18 @@ public class JdkSerializeTool {
* @return
*/
public static <T> Object deserialize(byte[] bytes, Class<T> clazz) {
ObjectInputStream ois = null;
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
try {
ois.close();
bais.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);

@ -1,11 +1,10 @@
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job</artifactId>
<version>2.4.1-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>xxl-job-executor-samples</artifactId>
<packaging>pom</packaging>
@ -15,4 +14,8 @@
<module>xxl-job-executor-sample-springboot</module>
</modules>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
</project>

@ -6,7 +6,7 @@
<parent>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-executor-samples</artifactId>
<version>2.4.1-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>xxl-job-executor-sample-frameless</artifactId>
<packaging>jar</packaging>
@ -21,7 +21,7 @@
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<artifactId>slf4j-reload4j</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
<!-- junit -->

@ -6,7 +6,7 @@
<parent>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-executor-samples</artifactId>
<version>2.4.1-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>xxl-job-executor-sample-springboot</artifactId>
<packaging>jar</packaging>
@ -66,6 +66,9 @@
</goals>
</execution>
</executions>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>

Loading…
Cancel
Save