Merge branch 'master' into master
This commit is contained in:
commit
d0f5c1f6ee
18
README.md
18
README.md
|
@ -408,6 +408,24 @@ XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅
|
||||||
- 287、F5未来商店
|
- 287、F5未来商店
|
||||||
- 288、深圳环阳通信息技术有限公司
|
- 288、深圳环阳通信息技术有限公司
|
||||||
- 289、遠傳電信
|
- 289、遠傳電信
|
||||||
|
- 290、作业帮(北京)教育科技有限公司【作业帮】
|
||||||
|
- 291、成都科鸿智信科技有限公司
|
||||||
|
- 292、北京木屋时代科技有限公司
|
||||||
|
- 293、大学通(哈尔滨)科技有限责任公司
|
||||||
|
- 294、浙江华坤道威数据科技有限公司
|
||||||
|
- 295、吉祥航空【吉祥航空】
|
||||||
|
- 296、南京圆周网络科技有限公司
|
||||||
|
- 297、广州市洋葱omall电子商务
|
||||||
|
- 298、天津联物科技有限公司
|
||||||
|
- 299、跑哪儿科技(北京)有限公司
|
||||||
|
- 300、深圳市美西西餐饮有限公司(喜茶)
|
||||||
|
- 301、平安不动产有限公司【平安】
|
||||||
|
- 302、江苏中海昇物联科技有限公司
|
||||||
|
- 303、湖南牙医帮科技有限公司
|
||||||
|
- 304、重庆民航凯亚信息技术有限公司(易通航)
|
||||||
|
- 305、递易(上海)智能科技有限公司
|
||||||
|
- 306、亚朵
|
||||||
|
- 307、浙江新课堂教育股份有限公司
|
||||||
- ……
|
- ……
|
||||||
|
|
||||||
> 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
|
> 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
|
||||||
|
|
|
@ -379,6 +379,24 @@ XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅
|
||||||
- 287、F5未来商店
|
- 287、F5未来商店
|
||||||
- 288、深圳环阳通信息技术有限公司
|
- 288、深圳环阳通信息技术有限公司
|
||||||
- 289、遠傳電信
|
- 289、遠傳電信
|
||||||
|
- 290、作业帮(北京)教育科技有限公司【作业帮】
|
||||||
|
- 291、成都科鸿智信科技有限公司
|
||||||
|
- 292、北京木屋时代科技有限公司
|
||||||
|
- 293、大学通(哈尔滨)科技有限责任公司
|
||||||
|
- 294、浙江华坤道威数据科技有限公司
|
||||||
|
- 295、吉祥航空【吉祥航空】
|
||||||
|
- 296、南京圆周网络科技有限公司
|
||||||
|
- 297、广州市洋葱omall电子商务
|
||||||
|
- 298、天津联物科技有限公司
|
||||||
|
- 299、跑哪儿科技(北京)有限公司
|
||||||
|
- 300、深圳市美西西餐饮有限公司(喜茶)
|
||||||
|
- 301、平安不动产有限公司【平安】
|
||||||
|
- 302、江苏中海昇物联科技有限公司
|
||||||
|
- 303、湖南牙医帮科技有限公司
|
||||||
|
- 304、重庆民航凯亚信息技术有限公司(易通航)
|
||||||
|
- 305、递易(上海)智能科技有限公司
|
||||||
|
- 306、亚朵
|
||||||
|
- 307、浙江新课堂教育股份有限公司
|
||||||
- ……
|
- ……
|
||||||
|
|
||||||
> 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
|
> 更多接入的公司,欢迎在 [登记地址](https://github.com/xuxueli/xxl-job/issues/1 ) 登记,登记仅仅为了产品推广。
|
||||||
|
@ -415,7 +433,7 @@ XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅
|
||||||
|
|
||||||
### 1.6 环境
|
### 1.6 环境
|
||||||
- Maven3+
|
- Maven3+
|
||||||
- Jdk1.7+
|
- Jdk1.8+
|
||||||
- Mysql5.7+
|
- Mysql5.7+
|
||||||
|
|
||||||
|
|
||||||
|
@ -478,8 +496,8 @@ XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅
|
||||||
### 调度中心通讯TOKEN [选填]:非空时启用;
|
### 调度中心通讯TOKEN [选填]:非空时启用;
|
||||||
xxl.job.accessToken=
|
xxl.job.accessToken=
|
||||||
|
|
||||||
### 调度中心国际化配置 [选填]: 默认为空,表示中文; "en" 表示英文;
|
### 调度中心国际化配置 [必填]: 默认为 "zh_CN"/中文简体, 可选范围为 "zh_CN"/中文简体, "zh_TC"/中文繁体 and "en"/英文;
|
||||||
xxl.job.i18n=
|
xxl.job.i18n=zh_CN
|
||||||
|
|
||||||
## 调度线程池最大线程配置【必填】
|
## 调度线程池最大线程配置【必填】
|
||||||
xxl.job.triggerpool.fast.max=200
|
xxl.job.triggerpool.fast.max=200
|
||||||
|
@ -1245,7 +1263,7 @@ API服务请求参考代码:com.xxl.job.executor.ExecutorBizTest
|
||||||
- 2、提供基于HTTP的任务Handler(Bean任务,JobHandler="HttpJobHandler");业务方只需要提供HTTP链接即可,不限制语言、平台;
|
- 2、提供基于HTTP的任务Handler(Bean任务,JobHandler="HttpJobHandler");业务方只需要提供HTTP链接即可,不限制语言、平台;
|
||||||
|
|
||||||
### 5.18 任务失败告警
|
### 5.18 任务失败告警
|
||||||
默认提供邮件失败告警,可扩展短信、钉钉等方式,扩展代码位置为 "JobFailMonitorHelper.failAlarm";
|
默认提供邮件失败告警,可扩展短信、钉钉等方式。如果需要新增一种告警方式,只需要新增一个实现 "com.xxl.job.admin.core.alarm.JobAlarm" 接口的告警实现即可。可以参考默认提供邮箱告警实现 "EmailJobAlarm"。
|
||||||
|
|
||||||
### 5.19 调度中心Docker镜像构建
|
### 5.19 调度中心Docker镜像构建
|
||||||
可以通过以下命令快速构建调度中心,并启动运行;
|
可以通过以下命令快速构建调度中心,并启动运行;
|
||||||
|
@ -1686,46 +1704,61 @@ public ReturnT<String> execute(String param) {
|
||||||
- 注意:最新版本 "XxlJobSpringExecutor" 逻辑有调整,历史项目中该组件的配置方式请参考Sample示例项目进行调整,尤其注意需要移除组件的init和destroy方法;
|
- 注意:最新版本 "XxlJobSpringExecutor" 逻辑有调整,历史项目中该组件的配置方式请参考Sample示例项目进行调整,尤其注意需要移除组件的init和destroy方法;
|
||||||
|
|
||||||
### 6.28 版本 v2.2.0 Release Notes[迭代中]
|
### 6.28 版本 v2.2.0 Release Notes[迭代中]
|
||||||
- 1、[迭代中]调度中心升级springboot2.x;因此,系统要求JDK8+;
|
- 1、调度中心升级springboot2.x;因此,系统要求JDK8+;
|
||||||
|
- 2、执行器注册默认值优化;
|
||||||
|
- 3、SQL脚本编码默认utf8mb4执行,避免小概率下容器环境中乱码问题;
|
||||||
|
- 4、多个项目依赖升级至较新稳定版本,如mybatis、groovy和mysql驱动等;
|
||||||
|
- 5、默认数据库连接池调整为hikari,移除tomcat-jdbc依赖;
|
||||||
|
- 6、任务告警组件模块化:如果需要新增一种告警方式,只需要新增一个实现 "com.xxl.job.admin.core.alarm.JobAlarm" 接口的告警实现即可,更加灵活、方便定制;
|
||||||
|
- 7、执行器XxlJob注解扫描逻辑优化,修复任务为空时小概率NPE问题;
|
||||||
|
- 8、Web IDE交互问题修复:输入源码备注之后按回车跳转error问题处理;
|
||||||
|
- 9、调度中心国际化完善:新增 "中文繁体" 支持。默认为 "zh_CN"/中文简体, 可选范围为 "zh_CN"/中文简体, "zh_TC"/中文繁体 and "en"/英文;
|
||||||
|
- 10、移除旧类注解JobHandler,推荐使用基于方法注解 "@XxlJob" 的方式进行任务开发;(如需保留类注解JobHandler使用方式,可以参考旧版逻辑定制开发);
|
||||||
|
- 11、修复bootstrap.min.css.map 404问题;
|
||||||
|
- 12、[迭代中]自定义失败重试时间间隔;
|
||||||
|
- 13、[迭代中]任务复制功能;点击复制是弹出新建任务弹框,并初始化被复制任务信息;
|
||||||
|
- 14、[迭代中]新增执行器描述、任务描述属性;
|
||||||
|
- 15、[迭代中]任务执行一次的时候指定IP;
|
||||||
|
- 16、[迭代中]任务日志支持单个清理和状态转移,方便触发子任务;
|
||||||
|
- 17、[迭代中]任务结果丢失处理:针对长期处于运行中的任务(设置过期时间时,运行超过"过期时间+1min";未设置超时时间时,运行超过"30min"),主动检测该执行器是否在线,如果不在线主动标记失败;
|
||||||
|
- 18、[迭代中]优雅停机回调丢失问题修复;
|
||||||
|
|
||||||
|
|
||||||
### TODO LIST
|
### TODO LIST
|
||||||
- 1、任务分片路由:分片采用一致性Hash算法计算出尽量稳定的分片顺序,即使注册机器存在波动也不会引起分批分片顺序大的波动;目前采用IP自然排序,可以满足需求,待定;
|
- 1、任务分片路由:分片采用一致性Hash算法计算出尽量稳定的分片顺序,即使注册机器存在波动也不会引起分批分片顺序大的波动;目前采用IP自然排序,可以满足需求,待定;
|
||||||
- 2、任务单机多线程:提升任务单机并行处理能力;
|
- 2、调度隔离:调度中心针对不同执行器,各自维护不同的调度和远程触发组件。
|
||||||
- 3、调度任务优先级;
|
- 3、调度任务优先级;
|
||||||
- 4、多数据库支持,在重写并移除Quartz的基础上,DAO层通过JPA实现,不限制数据库类型;
|
- 4、多数据库支持,DAO层通过JPA实现,不限制数据库类型;
|
||||||
- 5、执行器Log清理功能:调度中心Log删除时同步删除执行器中的Log文件;
|
- 5、执行器Log清理功能:调度中心Log删除时同步删除执行器中的Log文件;
|
||||||
- 6、任务自动注册:Bean模式任务,JobHandler自动从执行器中查询展示为下拉框,选择后自动填充任务名称等属性;待考虑,因为任务自动注册将会导致任务难以管理控制;
|
- 6、延时任务:API触发,支持"动态传参、延时消费";该功能与 XXL-MQ 冲突,该场景建议用后者;
|
||||||
- 7、API事件触发类型任务(更类似MQ消息)支持"动态传参、延时消费";该类型任务不走调度组件,单独建立MQ消息表,调度中心竞争触发;待定,该功能与 XXL-MQ 冲突,该场景建议用后者;
|
- 7、调度线程池改为协程方式实现,大幅降低系统内存消耗;
|
||||||
- 8、调度线程池改为协程方式实现,大幅降低系统内存消耗;
|
- 8、任务、执行器数据全量本地缓存;新增消息表广播通知;
|
||||||
- 9、任务、执行器数据全量本地缓存;新增消息表广播通知;
|
- 9、忙碌转移优化,全部机器忙碌时不再直接失败;
|
||||||
- 10、忙碌转移优化,全部机器忙碌时不再直接失败;
|
- 10、任务触发参数优化:支持选择 "Cron触发"、"固定间隔时间触发"、"指定时间点触发"、"不选择" 等;
|
||||||
- 11、失败重试间隔;
|
- 11、调度日志列表加上执行时长列,并支持排序;
|
||||||
- 12、SimpleTrigger:除Cron外,支持设置固定时间间隔触发;
|
- 12、DAG流程任务:替换子任务,支持参数传递,共享数据:配置并列的"a-b、b-c"路径列表,构成串行、并行、dag任务流程,"dagre-d3"绘图;任务依赖,流程图,子任务+会签任务,各节点日志;支持根据成功、失败选择分支;
|
||||||
- 13、调度日志列表加上执行时长列,并支持排序;
|
- 13、日期过滤:支持多个时间段排除;
|
||||||
- 14、DAG流程任务:替换子任务,支持参数传递:配置并列的"a-b、b-c"路径列表,构成串行、并行、dag任务流程,"dagre-d3"绘图;任务依赖,流程图,子任务+会签任务,各节点日志;支持根据成功、失败选择分支;
|
- 14、告警增强:
|
||||||
- 15、日期过滤:支持多个时间段排除;
|
- 邮件告警:支持自定义标题、模板格式;
|
||||||
- 16、告警邮件内容,支持自定义模板配置;
|
- webhook告警:支持自定义告警URL、请求体格式;
|
||||||
- 17、暂停状态,支持Cron 为空;
|
- 15、新增任务运行模式 "GLUE模式(GO) ",支持GO任务;
|
||||||
- 18、新增任务运行模式 "GLUE模式(GO) ",支持GO任务;
|
- 16、GLUE 模式 Web Ide 版本对比功能;
|
||||||
- 19、注册中心优化,实时性注册发现:心跳注册间隔10s,refresh失败则首次注册并立即更新注册信息,心跳类似;30s过期销毁;
|
- 17、注册中心优化,实时性注册发现:心跳注册间隔10s,refresh失败则首次注册并立即更新注册信息,心跳类似;30s过期销毁;
|
||||||
- 20、提供执行器Docker镜像;
|
- 18、提供执行器Docker镜像;
|
||||||
- 21、脚本任务,支持数据参数,新版本仅支持单参数不支持需要兼容;
|
- 19、脚本任务,支持数据参数,新版本仅支持单参数不支持需要兼容;
|
||||||
- 22、GLUE 模式 Web Ide 版本对比功能;
|
- 20、批量调度:调度请求入queue,调度线程批量获取调度请求并发起远程调度;提高线程效率;
|
||||||
- 23、批量调度:调度请求入queue,调度线程批量获取调度请求并发起远程调度;提高线程效率;
|
- 21、多语言执行器:约定跨语言通讯方案,以及通讯接口;
|
||||||
- 24、多语言执行器:约定跨语言通讯方案,以及通讯接口;
|
- 22、架构升级;XXL-JOB演进成一种任务调度规范和协议。默认双向Restful通讯。
|
||||||
- 25、移除commons-exec,采用原生实现;
|
- 调度中心API:
|
||||||
- 26、调度中心JDK版本调整为JDK8,从而升级至最新版本SpringBoot;
|
- 说明:提供给执行器使用,不局限于官方执行器;第三方可据此开发业务自己的执行器;
|
||||||
- 27、执行器服务端口与注册端口分离,支持docker动态随机端口;
|
- API列表:执行器注册相关、任务回调相关;
|
||||||
- 28、执行器端口复用,复用容器端口提供通讯服务;
|
- 执行器API:
|
||||||
- 29、自定义失败重试时间间隔;
|
- 说明:官方执行器,接收调度中心请求,异步回调任务结果;
|
||||||
- 30、分片任务全部成功后触发子任务;
|
- API列表:心跳服务、任务触发、任务终止、任务日志查询;
|
||||||
- 31、任务复制功能;点击复制是弹出新建任务弹框,并初始化被复制任务信息;
|
- 23、执行器服务端口与注册端口分离,支持docker动态随机端口;
|
||||||
- 32、AccessToken按照执行器维度设置;控制调度、回调;
|
- 24、执行器端口复用,复用容器端口提供通讯服务;
|
||||||
- 33、任务执行一次的时候指定IP;
|
- 25、分片任务全部成功后触发子任务;
|
||||||
- 34、通讯调整;双向HTTP,回调和其他API自定义AccessToken,Restful,执行器复用容器端口;
|
- 26、AccessToken按照执行器维度设置;控制调度、回调;
|
||||||
- 35、父子任务参数传递;流程任务等,透传动态参数;
|
|
||||||
- 36、新增执行器描述、任务描述属性;
|
|
||||||
|
|
||||||
|
|
||||||
## 七、其他
|
## 七、其他
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
|
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
|
||||||
use `xxl_job`;
|
use `xxl_job`;
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
CREATE TABLE `xxl_job_info` (
|
CREATE TABLE `xxl_job_info` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
|
23
pom.xml
23
pom.xml
|
@ -20,24 +20,25 @@
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
<maven.compiler.source>1.7</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<maven.compiler.target>1.7</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<maven.test.skip>true</maven.test.skip>
|
<maven.test.skip>true</maven.test.skip>
|
||||||
|
|
||||||
<xxl-rpc.version>1.5.0</xxl-rpc.version>
|
<xxl-rpc.version>1.5.0</xxl-rpc.version>
|
||||||
|
|
||||||
<spring.version>4.3.25.RELEASE</spring.version>
|
<spring.version>5.2.5.RELEASE</spring.version>
|
||||||
<spring-boot.version>1.5.22.RELEASE</spring-boot.version>
|
<spring-boot.version>2.2.5.RELEASE</spring-boot.version>
|
||||||
<mybatis-spring-boot-starter.version>1.3.5</mybatis-spring-boot-starter.version>
|
|
||||||
<mysql-connector-java.version>5.1.48</mysql-connector-java.version>
|
|
||||||
|
|
||||||
<slf4j-api.version>1.7.29</slf4j-api.version>
|
<mybatis-spring-boot-starter.version>2.1.2</mybatis-spring-boot-starter.version>
|
||||||
<junit.version>4.12</junit.version>
|
<mysql-connector-java.version>8.0.19</mysql-connector-java.version>
|
||||||
|
|
||||||
<groovy.version>2.5.8</groovy.version>
|
<slf4j-api.version>1.7.30</slf4j-api.version>
|
||||||
|
<junit.version>4.13</junit.version>
|
||||||
|
|
||||||
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
|
<groovy.version>3.0.2</groovy.version>
|
||||||
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
|
|
||||||
|
<maven-source-plugin.version>3.2.1</maven-source-plugin.version>
|
||||||
|
<maven-javadoc-plugin.version>3.2.0</maven-javadoc-plugin.version>
|
||||||
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
|
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
|
||||||
<maven-war-plugin.version>3.2.3</maven-war-plugin.version>
|
<maven-war-plugin.version>3.2.3</maven-war-plugin.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- mybatis-starter:mybatis + mybatis-spring + tomcat-jdbc(default) -->
|
<!-- mybatis-starter:mybatis + mybatis-spring + hikari(default) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mybatis.spring.boot</groupId>
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.xxl.job.admin.core.alarm;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author xuxueli 2020-01-19
|
||||||
|
*/
|
||||||
|
public interface JobAlarm {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* job alarm
|
||||||
|
*
|
||||||
|
* @param info
|
||||||
|
* @param jobLog
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.xxl.job.admin.core.alarm;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JobAlarmer implements ApplicationContextAware, InitializingBean {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(JobAlarmer.class);
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
private List<JobAlarm> jobAlarmList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
Map<String, JobAlarm> serviceBeanMap = applicationContext.getBeansOfType(JobAlarm.class);
|
||||||
|
if (serviceBeanMap != null && serviceBeanMap.size() > 0) {
|
||||||
|
jobAlarmList = new ArrayList<JobAlarm>(serviceBeanMap.values());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* job alarm
|
||||||
|
*
|
||||||
|
* @param info
|
||||||
|
* @param jobLog
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean alarm(XxlJobInfo info, XxlJobLog jobLog) {
|
||||||
|
|
||||||
|
boolean result = false;
|
||||||
|
if (jobAlarmList!=null && jobAlarmList.size()>0) {
|
||||||
|
result = true; // success means all-success
|
||||||
|
for (JobAlarm alarm: jobAlarmList) {
|
||||||
|
boolean resultItem = false;
|
||||||
|
try {
|
||||||
|
resultItem = alarm.doAlarm(info, jobLog);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
if (!resultItem) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package com.xxl.job.admin.core.alarm.impl;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.core.alarm.JobAlarm;
|
||||||
|
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||||
|
import com.xxl.job.admin.core.util.I18nUtil;
|
||||||
|
import com.xxl.job.core.biz.model.ReturnT;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* job alarm by email
|
||||||
|
*
|
||||||
|
* @author xuxueli 2020-01-19
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class EmailJobAlarm implements JobAlarm {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(EmailJobAlarm.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fail alarm
|
||||||
|
*
|
||||||
|
* @param jobLog
|
||||||
|
*/
|
||||||
|
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog){
|
||||||
|
boolean alarmResult = true;
|
||||||
|
|
||||||
|
// send monitor email
|
||||||
|
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
|
||||||
|
|
||||||
|
// alarmContent
|
||||||
|
String alarmContent = "Alarm Job LogId=" + jobLog.getId();
|
||||||
|
if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) {
|
||||||
|
alarmContent += "<br>TriggerMsg=<br>" + jobLog.getTriggerMsg();
|
||||||
|
}
|
||||||
|
if (jobLog.getHandleCode()>0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) {
|
||||||
|
alarmContent += "<br>HandleCode=" + jobLog.getHandleMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
// email info
|
||||||
|
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(Integer.valueOf(info.getJobGroup()));
|
||||||
|
String personal = I18nUtil.getString("admin_name_full");
|
||||||
|
String title = I18nUtil.getString("jobconf_monitor");
|
||||||
|
String content = MessageFormat.format(loadEmailJobAlarmTemplate(),
|
||||||
|
group!=null?group.getTitle():"null",
|
||||||
|
info.getId(),
|
||||||
|
info.getJobDesc(),
|
||||||
|
alarmContent);
|
||||||
|
|
||||||
|
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
|
||||||
|
for (String email: emailSet) {
|
||||||
|
|
||||||
|
// make mail
|
||||||
|
try {
|
||||||
|
MimeMessage mimeMessage = XxlJobAdminConfig.getAdminConfig().getMailSender().createMimeMessage();
|
||||||
|
|
||||||
|
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||||
|
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailUserName(), personal);
|
||||||
|
helper.setTo(email);
|
||||||
|
helper.setSubject(title);
|
||||||
|
helper.setText(content, true);
|
||||||
|
|
||||||
|
XxlJobAdminConfig.getAdminConfig().getMailSender().send(mimeMessage);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(">>>>>>>>>>> xxl-job, job fail alarm email send error, JobLogId:{}", jobLog.getId(), e);
|
||||||
|
|
||||||
|
alarmResult = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alarmResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load email job alarm template
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static final String loadEmailJobAlarmTemplate(){
|
||||||
|
String mailBodyTemplate = "<h5>" + I18nUtil.getString("jobconf_monitor_detail") + ":</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 width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobgroup") +"</td>\n" +
|
||||||
|
" <td width=\"10%\" >"+ I18nUtil.getString("jobinfo_field_id") +"</td>\n" +
|
||||||
|
" <td width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobdesc") +"</td>\n" +
|
||||||
|
" <td width=\"10%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_title") +"</td>\n" +
|
||||||
|
" <td width=\"40%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_content") +"</td>\n" +
|
||||||
|
" </tr>\n" +
|
||||||
|
" </thead>\n" +
|
||||||
|
" <tbody>\n" +
|
||||||
|
" <tr>\n" +
|
||||||
|
" <td>{0}</td>\n" +
|
||||||
|
" <td>{1}</td>\n" +
|
||||||
|
" <td>{2}</td>\n" +
|
||||||
|
" <td>"+ I18nUtil.getString("jobconf_monitor_alarm_type") +"</td>\n" +
|
||||||
|
" <td>{3}</td>\n" +
|
||||||
|
" </tr>\n" +
|
||||||
|
" </tbody>\n" +
|
||||||
|
"</table>";
|
||||||
|
|
||||||
|
return mailBodyTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.xxl.job.admin.core.conf;
|
package com.xxl.job.admin.core.conf;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.core.alarm.JobAlarmer;
|
||||||
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
|
||||||
import com.xxl.job.admin.dao.*;
|
import com.xxl.job.admin.dao.*;
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
@ -10,6 +11,7 @@ import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xxl-job config
|
* xxl-job config
|
||||||
|
@ -81,9 +83,14 @@ public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
|
||||||
private JavaMailSender mailSender;
|
private JavaMailSender mailSender;
|
||||||
@Resource
|
@Resource
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
@Resource
|
||||||
|
private JobAlarmer jobAlarmer;
|
||||||
|
|
||||||
|
|
||||||
public String getI18n() {
|
public String getI18n() {
|
||||||
|
if (!Arrays.asList("zh_CN", "zh_TC", "en").contains(i18n)) {
|
||||||
|
return "zh_CN";
|
||||||
|
}
|
||||||
return i18n;
|
return i18n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,4 +151,8 @@ public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
|
||||||
return dataSource;
|
return dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JobAlarmer getJobAlarmer() {
|
||||||
|
return jobAlarmer;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
package com.xxl.job.admin.core.thread;
|
package com.xxl.job.admin.core.thread;
|
||||||
|
|
||||||
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||||
import com.xxl.job.admin.core.model.XxlJobGroup;
|
|
||||||
import com.xxl.job.admin.core.model.XxlJobInfo;
|
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||||
import com.xxl.job.admin.core.model.XxlJobLog;
|
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||||
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
import com.xxl.job.admin.core.util.I18nUtil;
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
|
||||||
|
|
||||||
import javax.mail.internet.MimeMessage;
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,13 +61,7 @@ public class JobFailMonitorHelper {
|
||||||
// 2、fail alarm monitor
|
// 2、fail alarm monitor
|
||||||
int newAlarmStatus = 0; // 告警状态:0-默认、-1=锁定状态、1-无需告警、2-告警成功、3-告警失败
|
int newAlarmStatus = 0; // 告警状态:0-默认、-1=锁定状态、1-无需告警、2-告警成功、3-告警失败
|
||||||
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
|
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
|
||||||
boolean alarmResult = true;
|
boolean alarmResult = XxlJobAdminConfig.getAdminConfig().getJobAlarmer().alarm(info, log);
|
||||||
try {
|
|
||||||
alarmResult = failAlarm(info, log);
|
|
||||||
} catch (Exception e) {
|
|
||||||
alarmResult = false;
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
newAlarmStatus = alarmResult?2:3;
|
newAlarmStatus = alarmResult?2:3;
|
||||||
} else {
|
} else {
|
||||||
newAlarmStatus = 1;
|
newAlarmStatus = 1;
|
||||||
|
@ -121,89 +107,4 @@ public class JobFailMonitorHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---------------------- alarm ----------------------
|
|
||||||
|
|
||||||
// email alarm template
|
|
||||||
private static final String mailBodyTemplate = "<h5>" + I18nUtil.getString("jobconf_monitor_detail") + ":</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 width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobgroup") +"</td>\n" +
|
|
||||||
" <td width=\"10%\" >"+ I18nUtil.getString("jobinfo_field_id") +"</td>\n" +
|
|
||||||
" <td width=\"20%\" >"+ I18nUtil.getString("jobinfo_field_jobdesc") +"</td>\n" +
|
|
||||||
" <td width=\"10%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_title") +"</td>\n" +
|
|
||||||
" <td width=\"40%\" >"+ I18nUtil.getString("jobconf_monitor_alarm_content") +"</td>\n" +
|
|
||||||
" </tr>\n" +
|
|
||||||
" </thead>\n" +
|
|
||||||
" <tbody>\n" +
|
|
||||||
" <tr>\n" +
|
|
||||||
" <td>{0}</td>\n" +
|
|
||||||
" <td>{1}</td>\n" +
|
|
||||||
" <td>{2}</td>\n" +
|
|
||||||
" <td>"+ I18nUtil.getString("jobconf_monitor_alarm_type") +"</td>\n" +
|
|
||||||
" <td>{3}</td>\n" +
|
|
||||||
" </tr>\n" +
|
|
||||||
" </tbody>\n" +
|
|
||||||
"</table>";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fail alarm
|
|
||||||
*
|
|
||||||
* @param jobLog
|
|
||||||
*/
|
|
||||||
private boolean failAlarm(XxlJobInfo info, XxlJobLog jobLog){
|
|
||||||
boolean alarmResult = true;
|
|
||||||
|
|
||||||
// send monitor email
|
|
||||||
if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
|
|
||||||
|
|
||||||
// alarmContent
|
|
||||||
String alarmContent = "Alarm Job LogId=" + jobLog.getId();
|
|
||||||
if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) {
|
|
||||||
alarmContent += "<br>TriggerMsg=<br>" + jobLog.getTriggerMsg();
|
|
||||||
}
|
|
||||||
if (jobLog.getHandleCode()>0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) {
|
|
||||||
alarmContent += "<br>HandleCode=" + jobLog.getHandleMsg();
|
|
||||||
}
|
|
||||||
|
|
||||||
// email info
|
|
||||||
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(Integer.valueOf(info.getJobGroup()));
|
|
||||||
String personal = I18nUtil.getString("admin_name_full");
|
|
||||||
String title = I18nUtil.getString("jobconf_monitor");
|
|
||||||
String content = MessageFormat.format(mailBodyTemplate,
|
|
||||||
group!=null?group.getTitle():"null",
|
|
||||||
info.getId(),
|
|
||||||
info.getJobDesc(),
|
|
||||||
alarmContent);
|
|
||||||
|
|
||||||
Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
|
|
||||||
for (String email: emailSet) {
|
|
||||||
|
|
||||||
// make mail
|
|
||||||
try {
|
|
||||||
MimeMessage mimeMessage = XxlJobAdminConfig.getAdminConfig().getMailSender().createMimeMessage();
|
|
||||||
|
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
|
||||||
helper.setFrom(XxlJobAdminConfig.getAdminConfig().getEmailUserName(), personal);
|
|
||||||
helper.setTo(email);
|
|
||||||
helper.setSubject(title);
|
|
||||||
helper.setText(content, true);
|
|
||||||
|
|
||||||
XxlJobAdminConfig.getAdminConfig().getMailSender().send(mimeMessage);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(">>>>>>>>>>> xxl-job, job fail alarm email send error, JobLogId:{}", jobLog.getId(), e);
|
|
||||||
|
|
||||||
alarmResult = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do something, custom alarm strategy, such as sms
|
|
||||||
|
|
||||||
|
|
||||||
return alarmResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,7 @@ public class I18nUtil {
|
||||||
try {
|
try {
|
||||||
// build i18n prop
|
// build i18n prop
|
||||||
String i18n = XxlJobAdminConfig.getAdminConfig().getI18n();
|
String i18n = XxlJobAdminConfig.getAdminConfig().getI18n();
|
||||||
i18n = (i18n!=null && i18n.trim().length()>0)?("_"+i18n):i18n;
|
String i18nFile = MessageFormat.format("i18n/message_{0}.properties", i18n);
|
||||||
String i18nFile = MessageFormat.format("i18n/message{0}.properties", i18n);
|
|
||||||
|
|
||||||
// load prop
|
// load prop
|
||||||
Resource resource = new ClassPathResource(i18nFile);
|
Resource resource = new ClassPathResource(i18nFile);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
### web
|
### web
|
||||||
server.port=8080
|
server.port=8080
|
||||||
server.context-path=/xxl-job-admin
|
server.servlet.context-path=/xxl-job-admin
|
||||||
|
|
||||||
### actuator
|
### actuator
|
||||||
management.context-path=/actuator
|
management.server.servlet.context-path=/actuator
|
||||||
management.health.mail.enabled=false
|
management.health.mail.enabled=false
|
||||||
|
|
||||||
### resources
|
### resources
|
||||||
|
@ -20,6 +20,7 @@ spring.freemarker.settings.number_format=0.##########
|
||||||
|
|
||||||
### mybatis
|
### mybatis
|
||||||
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
|
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
|
||||||
|
#mybatis.type-aliases-package=com.xxl.job.admin.core.model
|
||||||
|
|
||||||
### xxl-job, datasource
|
### xxl-job, datasource
|
||||||
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?Unicode=true&characterEncoding=UTF-8
|
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?Unicode=true&characterEncoding=UTF-8
|
||||||
|
@ -27,14 +28,18 @@ spring.datasource.username=root
|
||||||
spring.datasource.password=root_pwd
|
spring.datasource.password=root_pwd
|
||||||
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
|
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
|
||||||
|
|
||||||
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
|
### datasource-pool
|
||||||
spring.datasource.tomcat.max-wait=10000
|
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
|
||||||
spring.datasource.tomcat.max-active=30
|
spring.datasource.hikari.minimum-idle=10
|
||||||
spring.datasource.tomcat.test-on-borrow=true
|
spring.datasource.hikari.maximum-pool-size=30
|
||||||
spring.datasource.tomcat.validation-query=SELECT 1
|
spring.datasource.hikari.auto-commit=true
|
||||||
spring.datasource.tomcat.validation-interval=30000
|
spring.datasource.hikari.idle-timeout=30000
|
||||||
|
spring.datasource.hikari.pool-name=HikariCP
|
||||||
|
spring.datasource.hikari.max-lifetime=900000
|
||||||
|
spring.datasource.hikari.connection-timeout=10000
|
||||||
|
spring.datasource.hikari.connection-test-query=SELECT 1
|
||||||
|
|
||||||
### xxl-job email
|
### xxl-job, email
|
||||||
spring.mail.host=smtp.qq.com
|
spring.mail.host=smtp.qq.com
|
||||||
spring.mail.port=25
|
spring.mail.port=25
|
||||||
spring.mail.username=xxx@qq.com
|
spring.mail.username=xxx@qq.com
|
||||||
|
@ -47,8 +52,8 @@ spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFact
|
||||||
### xxl-job, access token
|
### xxl-job, access token
|
||||||
xxl.job.accessToken=
|
xxl.job.accessToken=
|
||||||
|
|
||||||
### xxl-job, i18n (default empty as chinese, "en" as english)
|
### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en")
|
||||||
xxl.job.i18n=
|
xxl.job.i18n=zh_CN
|
||||||
|
|
||||||
## xxl-job, triggerpool max size
|
## xxl-job, triggerpool max size
|
||||||
xxl.job.triggerpool.fast.max=200
|
xxl.job.triggerpool.fast.max=200
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
admin_name=任務調度中心
|
||||||
|
admin_name_full=分布式任務調度平臺XXL-JOB
|
||||||
|
admin_version=2.1.1
|
||||||
|
admin_i18n=
|
||||||
|
|
||||||
|
## system
|
||||||
|
system_tips=系統提示
|
||||||
|
system_ok=確定
|
||||||
|
system_close=關閉
|
||||||
|
system_save=儲存
|
||||||
|
system_cancel=取消
|
||||||
|
system_search=搜尋
|
||||||
|
system_status=狀態
|
||||||
|
system_opt=操作
|
||||||
|
system_please_input=請輸入
|
||||||
|
system_please_choose=请選擇
|
||||||
|
system_success=成功
|
||||||
|
system_fail=失敗
|
||||||
|
system_add_suc=新增成功
|
||||||
|
system_add_fail=新增失敗
|
||||||
|
system_update_suc=更新成功
|
||||||
|
system_update_fail=更新失敗
|
||||||
|
system_all=全部
|
||||||
|
system_api_error=API錯誤
|
||||||
|
system_show=查看
|
||||||
|
system_empty=無
|
||||||
|
system_opt_suc=操作成功
|
||||||
|
system_opt_fail=操作失敗
|
||||||
|
system_opt_edit=編輯
|
||||||
|
system_opt_del=刪除
|
||||||
|
system_unvalid=非法
|
||||||
|
system_not_found=不存在
|
||||||
|
system_nav=導航
|
||||||
|
system_digits=整數
|
||||||
|
system_lengh_limit=長度限制
|
||||||
|
system_permission_limit=權限控管
|
||||||
|
system_welcome=歡迎
|
||||||
|
|
||||||
|
## daterangepicker
|
||||||
|
daterangepicker_ranges_recent_hour=最近一小時
|
||||||
|
daterangepicker_ranges_today=今日
|
||||||
|
daterangepicker_ranges_yesterday=昨日
|
||||||
|
daterangepicker_ranges_this_month=本月
|
||||||
|
daterangepicker_ranges_last_month=上個月
|
||||||
|
daterangepicker_ranges_recent_week=最近一周
|
||||||
|
daterangepicker_ranges_recent_month=最近一月
|
||||||
|
daterangepicker_custom_name=自定義
|
||||||
|
daterangepicker_custom_starttime=起始時間
|
||||||
|
daterangepicker_custom_endtime=結束時間
|
||||||
|
daterangepicker_custom_daysofweek=日,一,二,三,四,五,六
|
||||||
|
daterangepicker_custom_monthnames=一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月
|
||||||
|
|
||||||
|
## dataTable
|
||||||
|
dataTable_sProcessing=處理中...
|
||||||
|
dataTable_sLengthMenu=每頁 _MENU_ 條記錄
|
||||||
|
dataTable_sZeroRecords=沒有相符合記錄
|
||||||
|
dataTable_sInfo=第 _PAGE_ 頁 ( 總共 _PAGES_ 頁,_TOTAL_ 條記錄 )
|
||||||
|
dataTable_sInfoEmpty=無記錄
|
||||||
|
dataTable_sInfoFiltered=(由 _MAX_ 項結果過濾)
|
||||||
|
dataTable_sSearch=搜尋
|
||||||
|
dataTable_sEmptyTable=表中資料為空
|
||||||
|
dataTable_sLoadingRecords=載入中...
|
||||||
|
dataTable_sFirst=首頁
|
||||||
|
dataTable_sPrevious=上頁
|
||||||
|
dataTable_sNext=下頁
|
||||||
|
dataTable_sLast=末頁
|
||||||
|
dataTable_sSortAscending=: 以升幂排序此列
|
||||||
|
dataTable_sSortDescending=: 以降幂排序此列
|
||||||
|
|
||||||
|
## login
|
||||||
|
login_btn=登入
|
||||||
|
login_remember_me=記住密碼
|
||||||
|
login_username_placeholder=請輸入登入帳號
|
||||||
|
login_password_placeholder=請輸入登入密碼
|
||||||
|
login_username_empty=請輸入登入帳號
|
||||||
|
login_username_lt_4=登入帳號不應低於4位數
|
||||||
|
login_password_empty=請輸入登入密碼
|
||||||
|
login_password_lt_4=登入密碼不應低於4位數
|
||||||
|
login_success=登入成功
|
||||||
|
login_fail=登入失敗
|
||||||
|
login_param_empty=帳號或密碼為空值
|
||||||
|
login_param_unvalid=帳號或密碼錯誤
|
||||||
|
|
||||||
|
## logout
|
||||||
|
logout_btn=登出
|
||||||
|
logout_confirm=確認登出?
|
||||||
|
logout_success=登出成功
|
||||||
|
logout_fail=登出失敗
|
||||||
|
|
||||||
|
## change pwd
|
||||||
|
change_pwd=修改密碼
|
||||||
|
change_pwd_suc_to_logout=修改密碼成功,即將登出
|
||||||
|
change_pwd_field_newpwd=新密碼
|
||||||
|
|
||||||
|
## dashboard
|
||||||
|
job_dashboard_name=運行報表
|
||||||
|
job_dashboard_job_num=任務數量
|
||||||
|
job_dashboard_job_num_tip=調度中心運行的任務數量
|
||||||
|
job_dashboard_trigger_num=調度次數
|
||||||
|
job_dashboard_trigger_num_tip=調度中心觸發的調度次數
|
||||||
|
job_dashboard_jobgroup_num=執行器數量
|
||||||
|
job_dashboard_jobgroup_num_tip=調度中心在線的執行器機器數量
|
||||||
|
job_dashboard_report=調度報表
|
||||||
|
job_dashboard_report_loaddata_fail=調度報表資料加載異常
|
||||||
|
job_dashboard_date_report=日期分布圖
|
||||||
|
job_dashboard_rate_report=成功比例圖
|
||||||
|
|
||||||
|
## job info
|
||||||
|
jobinfo_name=任務管理
|
||||||
|
jobinfo_job=任務
|
||||||
|
jobinfo_field_add=新增
|
||||||
|
jobinfo_field_update=更新任務
|
||||||
|
jobinfo_field_id=任務ID
|
||||||
|
jobinfo_field_jobgroup=執行器
|
||||||
|
jobinfo_field_jobdesc=任務描述
|
||||||
|
jobinfo_field_gluetype=運行模式
|
||||||
|
jobinfo_field_executorparam=任務參數
|
||||||
|
jobinfo_field_cron_unvalid=Cron 格式非法
|
||||||
|
jobinfo_field_cron_never_fire=Cron 格式非法,永遠不會觸發
|
||||||
|
jobinfo_field_author=負責人
|
||||||
|
jobinfo_field_timeout=任務超時秒數
|
||||||
|
jobinfo_field_alarmemail=告警郵件
|
||||||
|
jobinfo_field_alarmemail_placeholder=輸入多個告警郵件地址,請以逗號分隔
|
||||||
|
jobinfo_field_executorRouteStrategy=路由策略
|
||||||
|
jobinfo_field_childJobId=子任務ID
|
||||||
|
jobinfo_field_childJobId_placeholder=輸入子任務ID,如有多個請以逗號分隔
|
||||||
|
jobinfo_field_executorBlockStrategy=阻塞處理策略
|
||||||
|
jobinfo_field_executorFailRetryCount=失敗重試次數
|
||||||
|
jobinfo_field_executorFailRetryCount_placeholder=失敗重試次數,大於零時生效
|
||||||
|
jobinfo_script_location=腳本位置
|
||||||
|
jobinfo_shard_index=分片序號
|
||||||
|
jobinfo_shard_total=分片總數
|
||||||
|
jobinfo_opt_stop=停止
|
||||||
|
jobinfo_opt_start=啟動
|
||||||
|
jobinfo_opt_log=查詢日誌
|
||||||
|
jobinfo_opt_run=執行一次
|
||||||
|
jobinfo_opt_registryinfo=注冊節點
|
||||||
|
jobinfo_opt_next_time=下次執行時間
|
||||||
|
jobinfo_glue_remark=源碼備註
|
||||||
|
jobinfo_glue_remark_limit=源碼備註長度限制為4~100
|
||||||
|
jobinfo_glue_rollback=版本回復
|
||||||
|
jobinfo_glue_jobid_unvalid=任務ID非法
|
||||||
|
jobinfo_glue_gluetype_unvalid=該任務非GLUE模式
|
||||||
|
jobinfo_field_executorTimeout_placeholder=任務超時時間,單位秒,大於零時生效
|
||||||
|
|
||||||
|
## job log
|
||||||
|
joblog_name=調度日誌
|
||||||
|
joblog_status=狀態
|
||||||
|
joblog_status_all=全部
|
||||||
|
joblog_status_suc=成功
|
||||||
|
joblog_status_fail=失敗
|
||||||
|
joblog_status_running=進行中
|
||||||
|
joblog_field_triggerTime=調度時間
|
||||||
|
joblog_field_triggerCode=調度結果
|
||||||
|
joblog_field_triggerMsg=調度備註
|
||||||
|
joblog_field_handleTime=執行時間
|
||||||
|
joblog_field_handleCode=執行结果
|
||||||
|
joblog_field_handleMsg=執行備註
|
||||||
|
joblog_field_executorAddress=執行器地址
|
||||||
|
joblog_clean=清理
|
||||||
|
joblog_clean_log=日誌清理
|
||||||
|
joblog_clean_type=清理方式
|
||||||
|
joblog_clean_type_1=清理一個月之前日誌資料
|
||||||
|
joblog_clean_type_2=清理三個月之前日誌資料
|
||||||
|
joblog_clean_type_3=清理六個月之前日誌資料
|
||||||
|
joblog_clean_type_4=清理一年之前日誌資料
|
||||||
|
joblog_clean_type_5=清理一千條以前日誌資料
|
||||||
|
joblog_clean_type_6=清理一萬條以前日誌資料
|
||||||
|
joblog_clean_type_7=清理三萬條以前日誌資料
|
||||||
|
joblog_clean_type_8=清理十萬條以前日誌資料
|
||||||
|
joblog_clean_type_9=清理所有日誌資料
|
||||||
|
joblog_clean_type_unvalid=清理類型參数異常
|
||||||
|
joblog_handleCode_200=成功
|
||||||
|
joblog_handleCode_500=失敗
|
||||||
|
joblog_handleCode_502=失敗(超時)
|
||||||
|
joblog_kill_log=终止任務
|
||||||
|
joblog_kill_log_limit=調度失敗,無法终止日誌
|
||||||
|
joblog_kill_log_byman=人為操作主動終止
|
||||||
|
joblog_rolling_log=執行日誌
|
||||||
|
joblog_rolling_log_refresh=更新
|
||||||
|
joblog_rolling_log_triggerfail=任務發起調度失敗,無法查看執行日誌
|
||||||
|
joblog_rolling_log_failoften=終止請求Rolling日誌,請求失敗次數超上限,可刷新頁面重新加載日誌
|
||||||
|
joblog_logid_unvalid=日誌ID非法
|
||||||
|
|
||||||
|
## job group
|
||||||
|
jobgroup_name=執行器管理
|
||||||
|
jobgroup_list=執行器列表
|
||||||
|
jobgroup_add=新增執行器
|
||||||
|
jobgroup_edit=編輯執行器
|
||||||
|
jobgroup_del=刪除執行器
|
||||||
|
jobgroup_field_order=排序
|
||||||
|
jobgroup_field_title=名稱
|
||||||
|
jobgroup_field_addressType=注冊方式
|
||||||
|
jobgroup_field_addressType_0=自動注冊
|
||||||
|
jobgroup_field_addressType_1=手動登錄
|
||||||
|
jobgroup_field_addressType_limit=手動登錄注冊方式,機器地址不可為空
|
||||||
|
jobgroup_field_registryList=機器地址
|
||||||
|
jobgroup_field_registryList_unvalid=機器地址格式非法
|
||||||
|
jobgroup_field_registryList_placeholder=請輸入執行器地址列表,多個地址請以逗號分隔
|
||||||
|
jobgroup_field_appName_limit=限制以小寫字母開頭,由小寫字母、數字和中划線組成
|
||||||
|
jobgroup_field_appName_length=AppName長度限制為4~64
|
||||||
|
jobgroup_field_title_length=名稱長度限制為4~12
|
||||||
|
jobgroup_field_order_digits=請輸入整數
|
||||||
|
jobgroup_field_orderrange=取值範圍為1~1000
|
||||||
|
jobgroup_del_limit_0=拒絕刪除,該執行器使用中
|
||||||
|
jobgroup_del_limit_1=拒絕删除,系统至少保留一個執行器
|
||||||
|
jobgroup_empty=不存在有效執行器,請聯絡系統管理員
|
||||||
|
|
||||||
|
## job conf
|
||||||
|
jobconf_block_SERIAL_EXECUTION=單機串行
|
||||||
|
jobconf_block_DISCARD_LATER=丢棄后續調度
|
||||||
|
jobconf_block_COVER_EARLY=覆蓋之前調度
|
||||||
|
jobconf_route_first=第一個
|
||||||
|
jobconf_route_last=最後一個
|
||||||
|
jobconf_route_round=輪詢
|
||||||
|
jobconf_route_random=隨機
|
||||||
|
jobconf_route_consistenthash=一致性HASH
|
||||||
|
jobconf_route_lfu=最不經常使用
|
||||||
|
jobconf_route_lru=最近最久未使用
|
||||||
|
jobconf_route_failover=故障轉移
|
||||||
|
jobconf_route_busyover=忙碌轉移
|
||||||
|
jobconf_route_shard=分片廣播
|
||||||
|
jobconf_idleBeat=空閒檢測
|
||||||
|
jobconf_beat=心跳檢測
|
||||||
|
jobconf_monitor=任務調度中心監控告警
|
||||||
|
jobconf_monitor_detail=監控告警明细
|
||||||
|
jobconf_monitor_alarm_title=告警類型
|
||||||
|
jobconf_monitor_alarm_type=調度失敗
|
||||||
|
jobconf_monitor_alarm_content=告警内容
|
||||||
|
jobconf_trigger_admin_adress=調度機器
|
||||||
|
jobconf_trigger_exe_regtype=執行器-注冊方式
|
||||||
|
jobconf_trigger_exe_regaddress=執行器-地址列表
|
||||||
|
jobconf_trigger_address_empty=調度失敗:執行器地址為空
|
||||||
|
jobconf_trigger_run=觸發調度
|
||||||
|
jobconf_trigger_child_run=觸發子任務
|
||||||
|
jobconf_callback_child_msg1={0}/{1} [任務ID={2}], 觸發{3}, 觸發備註: {4} <br>
|
||||||
|
jobconf_callback_child_msg2={0}/{1} [任務ID={2}], 觸發失败, 觸發備註: 任務ID格式錯誤 <br>
|
||||||
|
jobconf_trigger_type=任務觸發類型
|
||||||
|
jobconf_trigger_type_cron=Cron觸發
|
||||||
|
jobconf_trigger_type_manual=手動觸發
|
||||||
|
jobconf_trigger_type_parent=父任務觸發
|
||||||
|
jobconf_trigger_type_api=API觸發
|
||||||
|
jobconf_trigger_type_retry=失敗重試觸發
|
||||||
|
|
||||||
|
## user
|
||||||
|
user_manage=用户管理
|
||||||
|
user_username=帳號
|
||||||
|
user_password=密碼
|
||||||
|
user_role=角色
|
||||||
|
user_role_admin=管理員
|
||||||
|
user_role_normal=普通用戶
|
||||||
|
user_permission=權限
|
||||||
|
user_add=新增用戶
|
||||||
|
user_update=更新用戶
|
||||||
|
user_username_repeat=帳號重複
|
||||||
|
user_username_valid=限制以小寫字母開頭,由小寫字母、數字組成
|
||||||
|
user_password_update_placeholder=請輸入新密碼,為空則不更新密碼
|
||||||
|
user_update_loginuser_limit=禁止操作當前登入帳號
|
||||||
|
|
||||||
|
## help
|
||||||
|
job_help=使用教程
|
||||||
|
job_help_document=官方文件
|
File diff suppressed because one or more lines are too long
1
xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/css/bootstrap.min.css.map
vendored
Executable file
1
xxl-job-admin/src/main/resources/static/adminlte/bower_components/bootstrap/css/bootstrap.min.css.map
vendored
Executable file
File diff suppressed because one or more lines are too long
|
@ -100,7 +100,7 @@
|
||||||
<h4 class="modal-title" ><i class="fa fa-fw fa-save"></i>${I18n.system_save}</h4>
|
<h4 class="modal-title" ><i class="fa fa-fw fa-save"></i>${I18n.system_save}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form class="form-horizontal form" role="form" >
|
<div class="form-horizontal form" role="form" >
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_glue_remark}<font color="red">*</font></label>
|
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_glue_remark}<font color="red">*</font></label>
|
||||||
<div class="col-sm-10"><input type="text" class="form-control" id="glueRemark" placeholder="${I18n.system_please_input}${I18n.jobinfo_glue_remark}" maxlength="64" ></div>
|
<div class="col-sm-10"><input type="text" class="form-control" id="glueRemark" placeholder="${I18n.system_please_input}${I18n.jobinfo_glue_remark}" maxlength="64" ></div>
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">${I18n.system_cancel}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,8 +3,6 @@ package com.xxl.job.core.executor.impl;
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
import com.xxl.job.core.biz.model.ReturnT;
|
||||||
import com.xxl.job.core.executor.XxlJobExecutor;
|
import com.xxl.job.core.executor.XxlJobExecutor;
|
||||||
import com.xxl.job.core.glue.GlueFactory;
|
import com.xxl.job.core.glue.GlueFactory;
|
||||||
import com.xxl.job.core.handler.IJobHandler;
|
|
||||||
import com.xxl.job.core.handler.annotation.JobHandler;
|
|
||||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||||
import com.xxl.job.core.handler.impl.MethodJobHandler;
|
import com.xxl.job.core.handler.impl.MethodJobHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -18,9 +16,11 @@ import org.springframework.core.MethodIntrospector;
|
||||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xxl-job executor (for spring)
|
* xxl-job executor (for spring)
|
||||||
*
|
*
|
||||||
|
@ -35,7 +35,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
|
||||||
// init JobHandler Repository
|
// init JobHandler Repository
|
||||||
initJobHandlerRepository(applicationContext);
|
/*initJobHandlerRepository(applicationContext);*/
|
||||||
|
|
||||||
// init JobHandler Repository (for method)
|
// init JobHandler Repository (for method)
|
||||||
initJobHandlerMethodRepository(applicationContext);
|
initJobHandlerMethodRepository(applicationContext);
|
||||||
|
@ -54,7 +54,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initJobHandlerRepository(ApplicationContext applicationContext) {
|
/*private void initJobHandlerRepository(ApplicationContext applicationContext) {
|
||||||
if (applicationContext == null) {
|
if (applicationContext == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -74,13 +74,14 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private void initJobHandlerMethodRepository(ApplicationContext applicationContext) {
|
private void initJobHandlerMethodRepository(ApplicationContext applicationContext) {
|
||||||
if (applicationContext == null) {
|
if (applicationContext == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// init job handler from method
|
// init job handler from method
|
||||||
|
|
||||||
String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true);
|
String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true);
|
||||||
for (String beanDefinitionName : beanDefinitionNames) {
|
for (String beanDefinitionName : beanDefinitionNames) {
|
||||||
Object bean = applicationContext.getBean(beanDefinitionName);
|
Object bean = applicationContext.getBean(beanDefinitionName);
|
||||||
|
@ -150,6 +151,7 @@ public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationC
|
||||||
registJobHandler(name, new MethodJobHandler(bean, method, initMethod, destroyMethod));
|
registJobHandler(name, new MethodJobHandler(bean, method, initMethod, destroyMethod));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- applicationContext ----------------------
|
// ---------------------- applicationContext ----------------------
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
package com.xxl.job.core.handler.annotation;
|
//package com.xxl.job.core.handler.annotation;
|
||||||
|
//
|
||||||
import java.lang.annotation.ElementType;
|
//import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Inherited;
|
//import java.lang.annotation.Inherited;
|
||||||
import java.lang.annotation.Retention;
|
//import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
//import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
//import java.lang.annotation.Target;
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* annotation for job handler
|
// * annotation for job handler
|
||||||
*
|
// *
|
||||||
* will be replaced by {@link com.xxl.job.core.handler.annotation.XxlJob}
|
// * will be replaced by {@link com.xxl.job.core.handler.annotation.XxlJob}
|
||||||
*
|
// *
|
||||||
* @author 2016-5-17 21:06:49
|
// * @author 2016-5-17 21:06:49
|
||||||
*/
|
// */
|
||||||
@Target({ElementType.TYPE})
|
//@Target({ElementType.TYPE})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
//@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Inherited
|
//@Inherited
|
||||||
@Deprecated
|
//@Deprecated
|
||||||
public @interface JobHandler {
|
//public @interface JobHandler {
|
||||||
|
//
|
||||||
String value() default "";
|
// String value();
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
|
|
@ -15,7 +15,7 @@ public @interface XxlJob {
|
||||||
/**
|
/**
|
||||||
* jobhandler name
|
* jobhandler name
|
||||||
*/
|
*/
|
||||||
String value() default "";
|
String value();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init handler, invoked when JobThread init
|
* init handler, invoked when JobThread init
|
||||||
|
|
Loading…
Reference in New Issue