一茄猫、關(guān)于Quartz
Quartz是OpenSymphony開源組織在Job scheduling領(lǐng)域又一個開源項目牌借,它可以與J2EE與J2SE應(yīng)用程序相結(jié)合也可以單獨使用。在java企業(yè)級應(yīng)用中,Quartz是使用最廣泛的定時調(diào)度框架播瞳。
在Quartz中的主要概念:
- Scheduler:調(diào)度任務(wù)的主要API
- ScheduleBuilder:用于構(gòu)建Scheduler狞谱,例如其簡單實現(xiàn)類SimpleScheduleBuilder
- Job:調(diào)度任務(wù)執(zhí)行的接口乃摹,也即定時任務(wù)執(zhí)行的方法
- JobDetail:定時任務(wù)作業(yè)的實例
- JobBuilder:關(guān)聯(lián)具體的Job,用于構(gòu)建JobDetail
- Trigger:定義調(diào)度執(zhí)行計劃的組件跟衅,即定時執(zhí)行
- TriggerBuilder:構(gòu)建Trigger
一孵睬、Quartz演示示例
在SpringBoot中,我們需要引入quartz的依賴伶跷。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--quartz定時調(diào)度依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
首先定義定時具體執(zhí)行邏輯Job掰读,創(chuàng)建類QuartzJob1,這里集繼承QuartzJobBean實現(xiàn)executeInternal即可叭莫,該方法即定時執(zhí)行任務(wù)邏輯蹈集,這里簡單打印了下當(dāng)前時間。
public class QuartzJob1 extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("QuartzJob1----" + sdf.format(new Date()));
}
}
然后創(chuàng)建QuartzConfig雇初,接著定義JobDetail拢肆,JobDetail由JobBuilder構(gòu)建,同時關(guān)聯(lián)了任務(wù)QuartzJob1。
@Configuration
public class QuartzConfig {
@Bean
public JobDetail jobDetail1(){
return JobBuilder.newJob(QuartzJob1.class).storeDurably().build();
}
}
最后我們需要定義定時調(diào)度Trigger郭怪,簡單實現(xiàn)類SimpleScheduleBuilder用于構(gòu)建Scheduler支示,TriggerBuilder則用于構(gòu)建Trigger,
@Configuration
public class QuartzConfig {
@Bean
public JobDetail jobDetail1(){
return JobBuilder.newJob(QuartzJob1.class).storeDurably().build();
}
@Bean
public Trigger trigger1(){
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1) //每一秒執(zhí)行一次
.repeatForever(); //永久重復(fù)鄙才,一直執(zhí)行下去
return TriggerBuilder.newTrigger()
.forJob(jobDetail1())
.withSchedule(scheduleBuilder)
.build();
}
}
這樣一個Quartz定時任務(wù)就配置完成了悼院。
其實Job的定義也可以使用內(nèi)部類,這樣可以省去Job類的創(chuàng)建咒循,例如下面定時任務(wù)2 jobDetail2和trigger2据途。
@Bean
public JobDetail jobDetail2(){
QuartzJobBean quartzJob2 = new QuartzJobBean() {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("內(nèi)部類quartzJob2----" + sdf.format(new Date()));
}
};
return JobBuilder.newJob(quartzJob2.getClass()).storeDurably().build();
}
@Bean
public Trigger trigger2(){
//JobDetail的bean注入不能省略
//JobDetail jobDetail3 = JobBuilder.newJob(QuartzJob2.class).storeDurably().build();
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2) //每2秒執(zhí)行一次
.repeatForever(); //永久重復(fù),一直執(zhí)行下去
return TriggerBuilder.newTrigger()
.forJob(jobDetail2())
.withSchedule(scheduleBuilder).build();
}
啟動程序叙甸,我們就可以看到控制臺的時間輸出了颖医。
同時Quartz是支持?jǐn)?shù)據(jù)持久化的,可以將定時調(diào)度信息持久化到數(shù)據(jù)庫裆蒸。
選擇持久化到數(shù)據(jù)庫熔萧,我們需要創(chuàng)建對應(yīng)的表,建表語句可以在Quartz官網(wǎng)進行下載僚祷,解壓后在docs\dbTables目錄下尋找對應(yīng)數(shù)據(jù)庫的SQL腳本佛致。
為了方便,我也將該文件放在了項目源碼resources里辙谜。
操作數(shù)據(jù)庫俺榆,我們引入相關(guān)的依賴。若有ORM框架装哆,例如mybatis罐脊,hibernate或者jpa,則無需再引入jdbc依賴蜕琴。
<!--mysql連接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--druid連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--jdbc依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
在application.yml配置文件中萍桌,我們對quartz持久化方式進行聲明。
server:
port: 10900
spring:
profiles:
active: dev
quartz:
job-store-type: jdbc #持久化到數(shù)據(jù)庫
properties:
org:
quartz:
datasource:
# 新版驅(qū)動從com.mysql.jdbc.Driver變更為com.mysql.cj.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
# 數(shù)據(jù)源需要添加時間標(biāo)準(zhǔn)和指定編碼格式解決亂碼 You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 1234
scheduler:
instancName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #StdJDBCDelegate說明支持集群
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 1000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 20
threadPriority: 5
這里主要就是job-store-type: jdbc凌简,表示持久化到數(shù)據(jù)庫上炎,然后就是數(shù)據(jù)源,由于該演示項目沒有其他ORM的數(shù)據(jù)源雏搂,所以這里將數(shù)據(jù)源信息定義在了quartz節(jié)點下的datasource節(jié)點藕施,如果已經(jīng)存在,可使用同一個屬性配置畔派,當(dāng)然最關(guān)鍵的是QuartzDataSource聲明砸讳。
這里關(guān)鍵的是@QuartzDataSource解藻,這個要和項目中已經(jīng)存在的數(shù)據(jù)源區(qū)分開。
//Error:EmbeddedDatabaseType class not found纽窟,Druid數(shù)據(jù)源初始化需要引入spring-jdbc依賴尘盼,JPA或mybatis依賴已經(jīng)包含該依賴
@Bean
@QuartzDataSource
@ConfigurationProperties(prefix = "spring.quartz.properties.org.quartz.datasource")
DataSource quartzDataSource(){
return DruidDataSourceBuilder.create().build();
}
這樣持久化就已經(jīng)配置好了憨愉,我們執(zhí)行sql烦绳,再啟動項目,啟動完成后配紫,我們可以看到數(shù)據(jù)庫中已經(jīng)有我們的定時調(diào)度數(shù)據(jù)了径密。
源碼地址:https://github.com/imyanger/springboot-project/tree/master/p25-springboot-quartz