Quartz學習(七)--Spring整合Quartz(JobDetailBean方式)

一、Spring創建JobDetail的兩種方式

   定時任務兩種方式,Spring很好的封裝使用Quartz的細節,第一種方式是利用SPring封裝的Quartz類進行特定方法的實現,第二種是通過透明的使用Quartz達到定時任務開發的目的,總體說第二種對開發人員更方便!

   配置Spring的任務調度抽象層簡化了任務調度,在Quartz的基礎上提供了更好的調度對象。Spring使用Quartz框架來完成任務調度,創建Quartz的作業Bean(JobDetail),有一下兩種方法:

   1:利用JobDetailBean包裝QuartzJobBean子類(即Job類)的實例。

   2:利用MethodInvokingJobDetailFactoryBean工廠Bean包裝普通的Java對象(即Job類)。

   說明:

      1:採用第一種方法 創建job類,一定要繼承QuartzJobBean ,實現 executeInternal(JobExecutionContext
jobexecutioncontext)方法,此方法就是被調度任務的執行體,然後將此Job類的實例直接配置到JobDetailBean中即可。這種方法和在普通的Quartz編程中是一樣的。

      2:採用第二種方法 創建Job類,無須繼承父類,直接配置MethodInvokingJobDetailFactoryBean即可。但需要指定一下兩個屬性:

        targetObject:指定包含任務執行體的Bean實例。

        targetMethod:指定將指定Bean實例的該方法包裝成任務的執行體。


二、整合方式一示例步驟

   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">

	<!-- 定義個業務邏輯組件,繼承業務邏輯組件的模板 -->
	<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就會自動加載並啓用其中的各種屬性。

 三、注意事項

   在Spring配置和Quartz集成內容時,有兩點需要注意
           1、在<Beans>中不能夠設置default-lazy-init="true",否則定時任務不觸發,如果不明確指明default-lazy-init的值,默認是false。
           2、在<Beans>中不能夠設置default-autowire="byName"的屬性,否則後臺會報org.springframework.beans.factory.BeanCreationException錯誤,這樣就不能通過Bean名稱自動注入,必須通過明確引用注入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章