Nutz框架集成Quartz定时任务解决方案
Nutz框架集成Quartz定时任务解决方案
Nutz本身是个很不错的国产框架,轻量级、上手快,感兴趣的小伙伴可以去参考官网文档学习,使用,Nutz栏目主要是用于日常工作积累、备忘和分享。
功能需求
- 需求一:通过数据库任务信息能够动态控制任务的启动和停止
- 需求二:定时任务支持Cron和时间间隔触发器方式
- 需求三:能够实时监控任务状态
实现与设计思路
1.首先通过程序我们需要实现动态上的任务启停功能,这样我们就可以通过读取数据库的任务信息配置,来做到任务的启动和停止。
注意:这里我是使用了一个内置任务来监控任务信息表,这样我只用更新任务信息表,不在操作的时候考虑任务的启停,如果对实时性要求非常高这里建议不要使用我这种方式,在更新数据库前先动态启动任务,再去更新数据库的任务信息,保证系统任务和数据库信息同步,不过这样做,需要在系统启动和停止时,考虑到任务状态,这样即使重启系统,也能保证任务恢复到停止前的状态。
2.其次任务的启动方式满足cron表达式和时间间隔,就需要我们准备这两种触发器
3.监控任务状态,需要我们对所有任务进行动态监听,可将任务执行结果进行日志打印或记录到数据库和本地文件中,方便查看。
引入工具包
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.wuxx</groupId>
<artifactId>nutz-quartz</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>nutz-quartz Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<nutz.version>1.r.68.v20190220</nutz.version>
<nutz.quartz.version>1.r.70-SNAPSHOT</nutz.quartz.version>
<mysql.conn.version>8.0.33</mysql.conn.version>
<servlet-api.version>3.1.0</servlet-api.version>
<druid.version>1.2.23</druid.version>
<log4j.version>2.20.0</log4j.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutz</artifactId>
<version>${nutz.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutz-integration-quartz</artifactId>
<version>${nutz.quartz.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.conn.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- Druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-1.2-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
<build>
<finalName>nutz-quartz</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>nutz</id>
<url>http://jfrog.nutz.cn/artifactory/libs-release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>nutz-snapshots</id>
<url>http://jfrog.nutz.cn/artifactory/snapshots</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
</project>
数据库设计
表设计
创建脚本
/*
Navicat Premium Data Transfer
Source Server : localhost
Source Server Type : MySQL
Source Server Version : 80402
Source Host : localhost:3306
Source Schema : test
Target Server Type : MySQL
Target Server Version : 80402
File Encoding : 65001
Date: 16/12/2024 15:17:19
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for s_task_info
-- ----------------------------
DROP TABLE IF EXISTS `s_task_info`;
CREATE TABLE `s_task_info` (
`TASK_ID` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
`TASK_CH_NAME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务名称',
`TASK_EN_NAME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务英文名称',
`TASK_GROUP` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务分组',
`TASK_DESCRIPTION` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务描述',
`TASK_CRON` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务策略CRON',
`TASK_CLASS` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务加载类',
`TASK_TYPE` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '任务类型',
`TASK_EXECUTION_TIME` datetime(0) NULL DEFAULT NULL COMMENT '任务执行时间',
`STATUS` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '状态(运行中、暂停、停止)',
`CREATE_TIME` timestamp(6) NOT NULL COMMENT '创建时间',
`UPDATE_TIME` timestamp(6) NULL DEFAULT NULL COMMENT '更新时间',
`DEL_FLAG` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '静态任务标记(0否1是)',
`TASK_INTERVAL_UNIT` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '间隔时间类型,支持毫秒、秒、分钟、小时',
`TASK_INTERVAL` int(0) NULL DEFAULT NULL COMMENT '间隔时长',
`TASK_REPEAT` int(0) NULL DEFAULT NULL COMMENT '重复次数',
PRIMARY KEY (`TASK_ID`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '任务信息表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of s_task_info
-- ----------------------------
INSERT INTO `s_task_info` VALUES ('69f59841d659438281fc2b2ff6474683', '测试任务', 'testJob', 'Job1', '测试任务', '0 0/1 * * * ? ', 'com.wuxx.task.TestJob', 'CRON', '2024-12-16 15:14:09', '1', '2024-12-16 15:14:09.000000', '2024-12-16 15:14:09.000000', '0', 'INTERVAL_MINUTE', 1, 0);
SET FOREIGN_KEY_CHECKS = 1;
项目功能介绍
项目源码
nutz-quartz工程源码地址:gitCode
两种触发器的使用
通过任务类型配置,使用不同的触发器来启动任务,所以我们想使用不同的触发器,只需要设置不同的类型,任务类型包含:任务类型包含(taskType):
* CRON(“标准CRON支持”),
* INTERVAL_MILLISECOND(“固定间隔毫秒”),
* INTERVAL_SECOND(“固定间隔秒”),
* INTERVAL_MINUTE(“固定间隔分钟”),
* INTERVAL_HOUR(“固定间隔小时”)
taskType字段为以“INTERVAL_”类型开头时,需要设置taskIntervalUnit的时间间隔单位,还需要设置时间间隔(taskInterval),同时还能设置重复次数(taskRepeat,如果taskRepeat是0,则表示该任务无限重复)。
任务监听
/**
* created by wuxx on 2024/12/16.
* 监听器,用于监控任务的执行情况
*/
public class QuartzListener implements JobListener {
private static Logger log = LogManager.getLogger(QuartzListener.class);
@Override
public String getName() {
String name = this.getClass().getSimpleName();
log.debug("监听器的名称为: "+name);
return System.currentTimeMillis() + "QuartzListener";
}
@Override
public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
String name = jobExecutionContext.getJobDetail().getKey().getName(); //获取Job的name
log.debug("被监听的job的name是:"+name+" Scheduler在JobDetail将要被执行时调用的方法");
}
@Override
public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
String name = jobExecutionContext.getJobDetail().getKey().getName(); //获取Job的name
log.debug("Scheduler在JobDetail即将执行,但又被TriggerListerner否决时会调用的方法");
}
@Override
public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
String name = jobExecutionContext.getJobDetail().getKey().getName(); //获取Job的name
log.debug("Scheduler是在JobDetail被执行之后调用这个方法的");
}
}
可以根据实际的业务逻辑需求,在相应的方法中添加自己的业务逻辑,完成任务监听功能
任务分组
将任务分组配置,可以部署多个实例,可以保证每个实例上运行的任务不会重复
#任务分组,依据数据库taskGroup,多个任务组使用英文逗号间隔
quartz.task-group Job1,Job2,job3
运行结果
结尾
此方案相对来说不是很复杂,只是满足的最基础的业务功能需求,如果有更复杂的要求,也能在此基础上进行功能优化和增加,如此记录一下。