quartz定时任务的配置与使用
有存在一类需求,是需要去定时执行的,此时就需要使用到定时任务。例如说,每分钟扫描超时支付的订单,每小时清理一次日志文件,每天统计前一天的数据并生成报表,每个月月初的工资单的推送,每年一次的生日提醒等等。
Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。
它有很多特征,如:数据库支持,集群,插件,EJB 作业预构建,JavaMail 及其它,支持 cron-like 表达式等等。
在 Quartz 体系结构中,有三个组件非常重要:
- Scheduler :调度器
- Trigger :触发器
- Job :任务
1、导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 实现对 Quartz 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
</project>
2、application.yml配置
logging:
file:
name: slf4j-test
path: ./logs
max-size: 10MB
level:
root: info
config: classpath:logback-gnete.xml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
name: mybatis
password: 123456
url: jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false
username: root
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 100
maximum-pool-size: 500
auto-commit: true
idle-timeout: 30000
pool-name: DatebookHikariCP
max-lifetime: 1800000
connection-timeout: 30000
validation-timeout: 3000
quartz:
job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
jdbc:
initialize-schema: always
properties:
org:
quartz:
scheduler:
instanceName: AiCloudwalkSmpcGneteScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX # JobStore 实现类
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_ # Quartz 表前缀
isClustered: true # 是集群模式
clusterCheckinInterval: 10000
useProperties: false
dataSource: quartzDataSource # 使用的数据源
dataSource:
quartzDataSource:
driver: com.mysql.jdbc.Driver
URL: jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
user: root
password: 123456
provider: hikaricp
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10 # 线程池大小,默认为10
threadPriority: 5 # 线程优先级
threadsInheritContextClassLoaderOfInitializingThread: true
messages:
basename: messages_zh
crons:
quartzJobFirst: 0/5 * * * * ?
#mybatis
mybatis:
mapper-locations: classpath*:mybatis/mysql/*.xml
type-aliases-package: com.example.demo.entity
crons表达式的在线生成网站:http://www.bejson.com/othertools/cron/。
更多Quartz Scheduler 附加属性,可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html
3、自定义AbstractQuartzConfig类
package com.example.demo.configs;
import org.quartz.*;
public abstract class AbstractQuartzConfig {
private String name = null;
protected JobDetail job(Class <? extends Job> clazz){
this.name = clazz.getSimpleName();
return JobBuilder.newJob()
.ofType(clazz)
.withIdentity(name)
.storeDurably() // 没有 Trigger 关联的时候任务是否被保留。因为创建 JobDetail 时,还没 Trigger 指向它,所以需要设置为 true ,表示保留。
.build();
}
protected Trigger triggerJob(String cros, JobDetail jobDetail){
return TriggerBuilder.newTrigger()
.forJob(jobDetail) // 对应 Job 为 jobDetail
.withIdentity("triggerFor".concat(this.name)) // 名字为 triggerFor*
.startNow() //立即启动
.withSchedule(CronScheduleBuilder.cronSchedule(cros).withMisfireHandlingInstructionDoNothing())
.build();
}
}
4、自定义的QuartzConfig类
package com.example.demo.configs;
import com.example.demo.job.QuartzJobFirst;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig extends AbstractQuartzConfig{
@Value("${crons.quartzJobFirst}")
private String cros;
@Bean
public JobDetail jobTest(){
return super.job(QuartzJobFirst.class);
}
@Bean
public Trigger triggerJobTest(){
return super.triggerJob(cros,this.jobTest());
}
}
传入yml文件中定义的crons。
使用@Bean自动设置。也可以手动设置。
5、创建QuartzJobFirst定时任务
package com.example.demo.job;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
@Slf4j
@DisallowConcurrentExecution
public class QuartzJobFirst extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("————————————定时任务正在运行————————————");
}
}
通过在 Job 实现类上添加 @DisallowConcurrentExecution
注解,实现在相同 Quartz Scheduler 集群中,相同 JobKey 的 JobDetail ,保证在多个 JVM 进程中,有且仅有一个节点在执行。
6、Application类
package com.example.demo;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@Slf4j
@MapperScan({"com.example.demo.**.mapper"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
7、项目结构
如图:
8、运行结果
定时相关的表: