Spring定時服務(wù)QuartZ原理及代碼案例
在JavaEE系統(tǒng)中,我們會經(jīng)常用到定時任務(wù),比如每天凌晨生成前天報表,每一小時生成匯總數(shù)據(jù)等等。
我們可以使用java.util.Timer結(jié)合java.util.TimerTask來完成這項工作,但時調(diào)度控制非常不方便,并且我們需要大量的代碼。
使用Quartz框架無疑是非常好的選擇,并且與Spring可以非常方便的集成。
Spring提供了支持時序調(diào)度的整合類。整個構(gòu)建任務(wù)調(diào)度服務(wù)需要三步:
1)向項目中添加jar包:添加quartz.jar包,將他加到你工程的classpath中去。
2)寫Class文件,在文件中定義你要執(zhí)行操作的函數(shù)你就可以通過配置來達到定時操作了。
3)提供applicationContext.xml Spring配置文件,其中配置你的定時發(fā)送操作以及設(shè)置定時器的各種屬性(包括運行頻率和初始運行時機)?!?/p>
小編做了一個每5秒打印一次當前時間的例子,具體請參考源碼,尤其注意配置文件的寫法。(詳見下面“示例”)
什么是Quartz?
Quartz是一個強大的企業(yè)級任務(wù)調(diào)度框架。它允許開發(fā)人員靈活地定義觸發(fā)器的調(diào)度時間表,并可對觸發(fā)器和任務(wù)進行關(guān)聯(lián)映射。此外,Quartz提供了調(diào)度運行環(huán)境的持久化機制,可以保存并會發(fā)調(diào)度現(xiàn)場,即使系統(tǒng)因故障關(guān)閉,任務(wù)調(diào)度現(xiàn)場數(shù)據(jù)并不會丟失。Spring中繼承并簡化了Quartz。
如何使用Quartz?
對于Quartz,我們使用的時候主要是注重兩個方面,一個是定時任務(wù)的業(yè)務(wù),另一個就是Cron表達式。
1>Quartz存在兩種方式來定義定時執(zhí)行任務(wù),一種是使用QuartJobBean和JobDetailBean;另一種是使用MethodInvokingJobDetailFactoryBean。
2>Cron表達式包括下面7個字段并區(qū)別順序:秒0-59,分0-59,小時0-23,月內(nèi)日期1-31,月1-12或者JAN-DEC,周內(nèi)日期1-7或者SUN-SAT,年(可選字段)留空或者1970-2099并且通過特殊字符表示特殊意義,具體為下:
- 斜線(/)字符表示增量值。例如,在秒字段中"5/15"代表從第5秒開始,每15秒一次。
- 問號(?)字符和字母L字符只有在月內(nèi)日期和周內(nèi)日期字段中可用。問號表示這個字段不包含具體值。所以,如果指定月內(nèi)日期,可以在周內(nèi)日期字段中插入"?",表示周內(nèi)日期值無關(guān)緊要。這里有個很蛋疼的設(shè)定,無關(guān)Quartz,而是Spring集成Quartz后,它自己加的一個約束,那就是:日期(1-31)和星期(SUN-SAT)兩者,必須有一個是問號(?),系統(tǒng)在啟動的時候,Spring會檢查表達式,如果不符合它的規(guī)則,就會拋異常。所以在使用的時候這個地方一定要注意,而這個在Linux上執(zhí)行Cron是沒有這個限制的。
- 字母L字符是last的縮寫。放在月內(nèi)日期字段中,表示安排在當月最后一天執(zhí)行。在周內(nèi)日期字段中,如果"L"單獨存在,就等于"7",否則代表當月內(nèi)周內(nèi)日期的最后一個實例。所以"0L"表示安排在當月的最后一個星期日執(zhí)行。
- 字母(W)字符把執(zhí)行安排在最靠近指定值的工作日。把"1W"放在月內(nèi)日期字段中,表示把執(zhí)行安排在當月的第一個工作日內(nèi)。
- 井號(#)字符為給定月份指定具體的工作日實例。把"MON#2"放在周內(nèi)日期字段中,表示把任務(wù)安排在當月的第二個星期一。
- 星號(*)字符是通配字符,表示該字段可以接受任何可能的值、表達式例子。
例子:
"0 0 08 * * ?" 每天上午8點觸發(fā)
"0 15 10 ? * *" 每天上午10:15觸發(fā)
"0 15 10 * * ?" 每天上午10:15觸發(fā)
"0 15 10 ? * 6L 2009-2019" 2009年至2019年的每月的最后一個星期五上午10:15觸發(fā)
"0 15 10 ? * 6#3" 每月的第三個星期五上午10:15觸發(fā)
【示例】
我們使用Spring定時服務(wù)Quartz來實現(xiàn)一個每5秒打印一次當前時間的小例子。
1:定義接口IPrintInfoService類
package demoinfo.spring.quartz;
public interface IPrintInfoService {
public void print();
}
2:實現(xiàn)接口類PrintInfoServiceImpl
package demoinfo.spring.quartz;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import demoinfo.spring.quartz.IPrintInfoService;
public class PrintInfoServiceImpl implements IPrintInfoService{
public void print() {
Calendar now = Calendar.getInstance();
System.out.println("現(xiàn)在是北京時間:" + this.format(now.getTime()));
}
public String format(Date date){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
}
3:基于QuartzJobBean的實現(xiàn)類PrintInfoJob
package demoinfo.spring.quartz;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import demoinfo.spring.quartz.IPrintInfoService;
public class PrintInfoJob extends QuartzJobBean{
private IPrintInfoService prinfInfoService = null;
public IPrintInfoService getPrinfInfoService() {
return prinfInfoService;
}
public void setPrinfInfoService(IPrintInfoService prinfInfoService) {
this.prinfInfoService = prinfInfoService;
}
@Override
protected void executeInternal(JobExecutionContext arg0)
throws JobExecutionException {
this.prinfInfoService.print();
}
}
4:Spring配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean id="printInfoService" class="demoinfo.spring.quartz.PrintInfoServiceImpl" />
<!-- 配置一個Job -->
<bean id="printInfoJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="demoinfo.spring.quartz.PrintInfoJob" />
<property name="jobDataAsMap">
<map>
<entry key="prinfInfoService" value-ref="printInfoService"></entry>
</map>
</property>
</bean>
<!-- 簡單的觸發(fā)器 -->
<bean id="simplePrintInfoTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail">
<ref bean="printInfoJob" />
</property>
<property name="startDelay">
<value>6000</value>
</property>
<property name="repeatInterval">
<value>6000</value>
</property>
</bean>
<!--復(fù)雜的觸發(fā)器 -->
<bean id="complexPrintInfoTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="printInfoJob" />
</property>
<property name="cronExpression">
<value>00,05,10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
</property>
</bean>
<!-- spring觸發(fā)工廠 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="complexPrintInfoTrigger" />
</list>
</property>
</bean>
</beans>
5:測試用例類SpringQuartzDemo
package demoinfo.spring.quartz;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringQuartzDemo {
public static void main(String[] args) {
System.out.println("測試開始......");
new ClassPathXmlApplicationContext(
"classpath:demoinfo/spring/quartz/applicationContext.xml");
System.out.println("測試結(jié)束......");
}
}
運行測試用例,可以看到控制臺每過5秒鐘就打印一次時間信息。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Quartz.Net實現(xiàn)原理及使用方法詳解
- JAVA使用quartz添加定時任務(wù),并依賴注入對象操作
- Springboot2.x+Quartz分布式集群的實現(xiàn)
- SpringBoot中使用Quartz管理定時任務(wù)的方法
- springboot+quartz以持久化的方式實現(xiàn)定時任務(wù)的代碼
- Springboot整合quartz產(chǎn)生錯誤及解決方案
- 淺談SpringBoot集成Quartz動態(tài)定時任務(wù)
- springboot Quartz動態(tài)修改cron表達式的方法
- Quartz.Net任務(wù)和觸發(fā)器實現(xiàn)方法詳解
相關(guān)文章
淺談spring的重試機制無效@Retryable@EnableRetry
這篇文章主要介紹了淺談spring的重試機制無效@Retryable@EnableRetry,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
springmvc fastjson 反序列化時間格式化方法(推薦)
下面小編就為大家?guī)硪黄猻pringmvc fastjson 反序列化時間格式化方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
Spring注解@Profile實現(xiàn)開發(fā)環(huán)境/測試環(huán)境/生產(chǎn)環(huán)境的切換
在進行軟件開發(fā)過程中,一般會將項目分為開發(fā)環(huán)境,測試環(huán)境,生產(chǎn)環(huán)境。本文主要介紹了Spring如何通過注解@Profile實現(xiàn)開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境的切換,需要的可以參考一下2023-04-04
Java微信公眾平臺開發(fā)(9) 關(guān)鍵字回復(fù)以及客服接口實現(xiàn)
這篇文章主要為大家詳細介紹了Java微信公眾平臺開發(fā)第九步,關(guān)鍵字回復(fù)以及客服接口實現(xiàn),以及遇到該公眾號暫時無法提供服務(wù)的解決方案,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04
服務(wù)性能優(yōu)化之mybatis-plus開啟與關(guān)閉SQL日志打印方法
這篇文章主要介紹了在Mybatis-plus中開啟和關(guān)閉控制臺SQL日志打印,在`application.properties`文件中,可以通過配置來實現(xiàn)SQL日志的開啟和關(guān)閉,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-12-12
java監(jiān)聽器實現(xiàn)在線人數(shù)統(tǒng)計
這篇文章主要為大家詳細介紹了java監(jiān)聽器實現(xiàn)在線人數(shù)統(tǒng)計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-11-11
Java中ThreadLocal避免內(nèi)存泄漏的方法詳解
ThreadLocal是Java中的一個線程本地存儲機制,它允許每個線程擁有一個獨立的本地存儲空間,用于存儲該線程的變量,本文主要介紹了ThreadLocal如何避免內(nèi)存泄漏,需要的朋友可以參考下2023-05-05

