基礎環境
SpringBoot
2.0 開始官方提供了對quartz
定時任務的自動配置支援依賴spring-boot-starter-quartz
元件,無需自行整合
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
複製程式碼
環境版本:
- SpringBoot 2.1.6.RELEASE
- Java 8
定時任務配置
新增依賴
在pom.xml中新增quartz、Jpa、mysql驅動、lombok依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
複製程式碼
新增配置檔案
新增資料庫配置
spring:
datasource:
primary:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: hmdt
url: jdbc:mysql://db/bussines_db?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
quartz:
url: jdbc:mysql://db/bussines_quartz?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: hmdt
quartz:
#相關屬性配置
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
# 資料來源名稱
dataSource: quartzDataSource
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 1000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
job-store-type: jdbc
#初始化表結構
jdbc:
initialize-schema: never
jpa:
hibernate:
ddl-auto: update
show-sql: true
database-platform: org.hibernate.dialect.MySQL55Dialect
properties:
hibernate:
format_sql: true
use_sql_comments: true
複製程式碼
資料庫配置也有樣例配在spring.quartz.properties
中,但親測配置無效,並且由於還需要指定連線池等資訊,此處配置在spring的連線池中更容易管理
下載官網建表語句
儘管使用了JPA
,但由於沒有實體關聯,spring
並不會幫我們自動建表,還需要去官網下載sql
指令碼
官網壓縮包路徑quartz-2.3.0-SNAPSHOT\src\org\quartz\impl\jdbcjobstore
中支援大量資料庫建表語句,選擇對應的使用即可
配置多資料來源
多配置源之前在文章中詳細說過配置樣例和原因,這裡不再贅述
SpringBoot2.x Data JPA 多資料來源爬坑
編寫資料庫配置,統一使用HikariCP
連線池
package com.gcb.invest.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* 定時任務資料來源配置
*
* @author F嘉陽
* @date 2019-07-28 21:52
*/
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("spring.datasource.primary.configuration")
public HikariDataSource firstDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
@Bean
@ConfigurationProperties("spring.datasource.quartz")
public DataSourceProperties quartzDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@QuartzDataSource
@ConfigurationProperties("spring.datasource.quartz.configuration")
public HikariDataSource quartzDataSource() {
return quartzDataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
}
複製程式碼
定時任務配置
配置樣例1——Bean注入
編寫定時任務,由於經過Spring的封裝,使用變得更加方便
此處通過內部類配置定時任務,並使用@DisallowConcurrentExecution
註解指定其在分散式環境下不可併發執行
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* 定時任務配置
*
* @author :F嘉陽
* @date :2019/7/29 9:16
*/
@Slf4j
@Configuration
public class QuartzConfig {
/**
* 測試定時任務構建
*
* @return
*/
@Bean
public JobDetail testTaskJobDetail() {
return JobBuilder.newJob(TestTask.class)
.withIdentity(TestTask.class.getName())
.storeDurably(true)
.build();
}
/**
* 測試定時任務配置
*
* @return
*/
@Bean
public Trigger testTaskTrigger() {
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?");
return TriggerBuilder.newTrigger()
.forJob(testTaskJobDetail())
.withIdentity(TestTask.class.getName())
.withSchedule(scheduleBuilder)
.build();
}
@DisallowConcurrentExecution
private class TestTask extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.debug("執行測試定時任務");
}
}
}
複製程式碼
配置樣例2——排程器注入
另一種方式可使用注入排程器手動構建任務,不過需要呼叫該方法之後排程器才會被建立
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.UUID;
/**
* @author :F嘉陽
* @date :2019/7/29 8:59
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class QuartzTimerService {
@Autowired
private Scheduler scheduler;
public void buildGoodStockTimer() throws Exception {
//任務名稱
String name = UUID.randomUUID().toString();
//任務所屬分組
String group = CustomQuartzJob.class.getName();
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
//建立任務
JobDetail jobDetail = JobBuilder.newJob(CustomQuartzJob.class).withIdentity(name,group).build();
//建立任務觸發器
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(name,group).withSchedule(scheduleBuilder).build();
//將觸發器與任務繫結到排程器內
scheduler.scheduleJob(jobDetail, trigger);
}
}
複製程式碼
定時任務類
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* @author :F嘉陽
* @date :2019/7/29 8:55
*/
@Slf4j
@DisallowConcurrentExecution
public class CustomQuartzJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("執行定時任務");
}
}
複製程式碼
執行結果
執行成功
在分散式環境下自動進行作業節點遷移