1、Spring建立JobDetail的兩種方式java
定時任務兩種方式,Spring很好的封裝使用Quartz的細節,第一種方式是利用SPring封裝的Quartz類進行特定方法的實現,第二種是經過透明的使用Quartz達到定時任務開發的目的,整體說第二種對開發人員更方便!web
配置Spring的任務調度抽象層簡化了任務調度,在Quartz的基礎上提供了更好的調度對象。Spring使用Quartz框架來完成任務調度,建立Quartz的做業Bean(JobDetail),有一下兩種方法:spring
1:利用JobDetailBean包裝QuartzJobBean子類(即Job類)的實例。編程
2:利用MethodInvokingJobDetailFactoryBean工廠Bean包裝普通的Java對象(即Job類)。app
說明:框架
1:採用第一種方法 建立job類,必定要繼承QuartzJobBean ,實現 executeInternal(JobExecutionContextthis
jobexecutioncontext)方法,此方法就是被調度任務的執行體,而後將此Job類的實例直接配置到JobDetailBean中便可。這種方法和在普通的Quartz編程中是同樣的。spa
2:採用第二種方法建立Job類,無須繼承父類,直接配置MethodInvokingJobDetailFactoryBean便可。但須要指定一下兩個屬性:線程
targetObject:指定包含任務執行體的Bean實例。code
targetMethod:指定將指定Bean實例的該方法包裝成任務的執行體。
2、整合方式一示例步驟
1、將spring核心jar包和Spring-context-support.jar導入類路徑。
###不用導入quartz.jar?,千萬不忘了導入spring-context-support-3.2.0.M2.jar:這是由於這種方式是利用SPring封裝的Quartz類進行特定方法的實現。
咱們用到的兩個JobDetail:org.springframework.scheduling.quartz.JobDetailBean和org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
觸發器:org.springframework.scheduling.quartz.CronTriggerBean ;調度器:org.springframework.scheduling.quartz.SchedulerFactoryBean 都來源於這個jar包。
2、編寫Job類PunchJob(該類必須繼承QuartzJobBean)
package org.crazyit.hrsystem.schedule; import java.util.Date; import org.springframework.scheduling.quartz.QuartzJobBean; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.crazyit.hrsystem.service.EmpManager; public class PunchJob extends QuartzJobBean { //判斷做業是否執行的旗標 private boolean isRunning = false; //該做業類所依賴的業務邏輯組件 private EmpManager empMgr; public void setEmpMgr(EmpManager empMgr) { this.empMgr = empMgr; } //定義任務執行體 public void executeInternal(JobExecutionContext ctx) throws JobExecutionException { if (!isRunning) { System.out.println("開始調度自動打卡"); isRunning = true; //調用業務邏輯方法 empMgr.autoPunch(); isRunning = false; } } }
3、編寫quartz.xml配置文件
<?xml version="1.0" encoding="GBK"?> <!-- 指定Spring配置文件的Schema信息 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" default-lazy-init="false"> <!-- 定義<SPAN style="FONT-FAMILY: 'courier new', 'courier'">一</SPAN>個業務邏輯組件,繼承業務邏輯組件的模板 --> <bean id="empManager" class="org.crazyit.hrsystem.service.impl.EmpManagerImpl" parent="managerTemplate"/> <!-- 定義觸發器來管理任務Bean --> <bean id="cronTriggerPunch" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <!-- 使用嵌套Bean的方式來定義任務Bean --> <bean class="org.springframework.scheduling.quartz.JobDetailBean"> <!-- 指定任務Bean的實現類 --> <property name="jobClass" value="org.crazyit.hrsystem.schedule.PunchJob"/> <!-- 爲任務Bean注入屬性 --> <property name="jobDataAsMap"> <map> <entry key="empMgr" value-ref="empManager"/> </map> </property> </bean> </property> <!-- 指定Cron表達式:週一到週五7點、12點執行調度 --> <property name="cronExpression" value="0 0 7,12 ? * MON-FRI"/> </bean> <!-- 執行實際的調度器--> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTriggerPunch"></ref> <!--<ref local="cronTriggerPunch"/> 二者均可以用 --> </list> </property> </bean> </beans>
job data map(jobDataAsMap)可經過JobExecutionContext (執行時傳遞)獲取。JobDetailBean將 job data map的屬性映射到job的屬性。如例所示,若是job類PunchJob中包含一個empMgr屬性,JobDetailBean將自動注入到Job類PunchJob的實例中,可用於傳遞參數。若是不寫明,就會報
java.lang.NullPointerException錯誤,主要是由於沒有注入Bean。
在上面的配置中咱們是讓觸發器和任務嵌套的,其實還能夠將他們分離,形如:
<!-- 定義JobDetail的Bean --> <bean id="saveProjectJob" class="org.springframework.scheduling.quartz.JobDetailBean"> <!-- 定義Job的Bean --> <property name="jobClass"> <value> com.gresoft.fileupload.service.ParseFileQuartz </value> </property> <!-- 定義Job的Bean中引用到的其餘Bean --> <property name="jobDataAsMap"> <map> <entry key="readXmlService"> <ref bean="readXmlService" /> </entry> </map> </property> </bean> <!-- ----------------------------------------------------------- --> <!-- 定義觸發器的Bean --> <bean id="saveCron" class="org.springframework.scheduling.quartz.CronTriggerBean"> <!-- 指定jobDetail --> <property name="jobDetail"> <!-- <ref bean="saveProjectJob"></ref>二者均可以用 --> <ref local="saveProjectJob" /> </property> <!-- 指定任務觸發的時間 --> <property name="cronExpression"> <value>0/30 * * * * ?</value> </property> </bean>
4、讓容器加載quartz.xml
在web.xml中添加:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml,/WEB-INF/quartz.xml</param-value> </context-param>
###其實quartz.xml文件的內容徹底能夠寫在applicationContext.xml中的,不過那樣會顯得雜亂。
5、配置quartz的運行環境:quartz.properties文件(放在類路徑下)
文件名必須叫此名字,其實此文件咱們也能夠不配置的。
# 配置主調度器屬性 org.quartz.scheduler.instanceName = QuartzScheduler org.quartz.scheduler.instanceId = AUTO # 配置線程池 # Quartz線程池的實現類 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool # 線程池的線程數量 org.quartz.threadPool.threadCount = 1 # 線程池裏線程的優先級 org.quartz.threadPool.threadPriority = 10 # 配置做業存儲 org.quartz.jobStore.misfireThreshold = 60000 org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
若是咱們不配置此文件的話,默認使用quartz-2.1.6.jar中的quartz.properties文件(在該壓縮文件的org/quartz路徑下),若是須要改變其運行屬性,咱們能夠本身建立一個quartz.properties文件,並將該文件放在系統加載的類路徑下,ClassLoader就會自動加載並啓用其中的各類屬性。
3、注意事項
在Spring配置和Quartz集成內容時,有兩點須要注意
1、在<Beans>中不可以設置default-lazy-init="true",不然定時任務不觸發,若是不明確指明default-lazy-init的值,默認是false。
2、在<Beans>中不可以設置default-autowire="byName"的屬性,不然後臺會報org.springframework.beans.factory.BeanCreationException錯誤,這樣就不能經過Bean名稱自動注入,必須經過明確引用注入