maven下整合spring和quartz

最近在研究Spring中的定時任務功能,最好的辦法固然是使用Quartz來實現。對於一個新手來講,花了我很多時間,這裏我寫個筆記,給你們參考。 
我使用的是Maven來管理項目,須要的Jar包我給你們貼出來。
 
quartz-1.8.5.jar 
commons-logging.jar 
spring-core-3.0.5.RELEASE.jar 
spring-beans-3.0.5.RELEASE.jar 
spring-context-3.0.5.RELEASE.jar 
spring-context-support-3.0.5.RELEASE.jar 
spring-asm-3.0.5.RELEASE.jar 
spring-expression-3.0.5.RELEASE.jar 
spring.transaction-3.0.5.RELEASE.jar 
spring-web-3.0.5.RELEASE.jar
 
Maven的pom.xml的配置: 
html

Xml代碼  收藏代碼java

  1. <?xml version="1.0" encoding="UTF-8"?>  
    <project xmlns="http://maven.apache.org/POM/4.0.0"  
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
        <modelVersion>4.0.0</modelVersion>  
      
        <groupId>QtzTest</groupId>  
        <artifactId>QtzTest</artifactId>  
        <version>1.0</version>  
      
        <properties>  
            <springframework.version>3.0.5.RELEASE</springframework.version>  
        </properties>  
      
        <dependencies>  
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-context</artifactId>  
                <version>${springframework.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-context-support</artifactId>  
                <version>${springframework.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-tx</artifactId>  
                <version>${springframework.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.springframework</groupId>  
                <artifactId>spring-web</artifactId>  
                <version>${springframework.version}</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.quartz-scheduler</groupId>  
                <artifactId>quartz</artifactId>  
                <version>1.8.5</version>  
            </dependency>  
        </dependencies>  
      
        <build>  
            <finalName>${project.artifactId}</finalName>  
            <plugins>  
                <plugin>  
                    <groupId>org.mortbay.jetty</groupId>  
                    <artifactId>jetty-maven-plugin</artifactId>  
                    <version>7.5.4.v20111024</version>  
                    <configuration>  
                        <scanIntervalSeconds>10</scanIntervalSeconds>  
                        <webApp>  
                            <contextPath>/${project.artifactId}</contextPath>  
                        </webApp>  
                    </configuration>  
                </plugin>  
            </plugins>  
        </build>  
    </project>


特別注意一點,與Spring3.1如下版本整合必須使用Quartz1,最初我拿2.1.3的,怎麼搞都報錯: 
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.scheduling.quartz.CronTriggerBean] for bean with name 'mytrigger' defined in class path resource [applicationContext.xml]: problem with class file or dependent class; nested exception is java.lang.IncompatibleClassChangeError: class org.springframework.scheduling.quartz.CronTriggerBean has interface org.quartz.CronTrigger as super class 

查看發現spring3.0.5中org.springframework.scheduling.quartz.CronTriggerBean繼承了org.quartz.CronTrigger(public class CronTriggerBeanextends CronTrigger),而在quartz2.1.3中org.quartz.CronTrigger是個接口(publicabstract interface CronTrigger extends Trigger),而在quartz1.8.5及1.8.4中org.quartz.CronTrigger是個類(publicclass CronTrigger extends Trigger),從而形成沒法在applicationContext中配置觸發器。這是spring3.1如下版本和quartz2版本不兼容的一個bug。(感謝tiren的回覆,spring3.1以及之後版本支持quartz2) 

在Spring中使用Quartz有兩種方式實現:第一種是任務類繼承QuartzJobBean,第二種則是在配置文件裏定義任務類和要執行的方法,類和方法仍然是普通類。很顯然,第二種方式遠比第一種方式來的靈活。 

第一種方式的JAVA代碼: 
web

Java代碼  收藏代碼spring

  1. package com.ncs.hj;  
      
    import org.quartz.JobExecutionContext;  
    import org.quartz.JobExecutionException;  
    import org.springframework.scheduling.quartz.QuartzJobBean;  
      
    public class SpringQtz extends QuartzJobBean{  
        private static int counter = 0;  
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {  
            System.out.println();  
            long ms = System.currentTimeMillis();  
            System.out.println("\t\t" + new Date(ms));  
            System.out.println(ms);  
            System.out.println("(" + counter++ + ")");  
            String s = (String) context.getMergedJobDataMap().get("service");  
            System.out.println(s);  
            System.out.println();  
        }  
    }


第二種方式的JAVA代碼: 
數據庫

Java代碼  收藏代碼express

  1. package com.ncs.hj;  
      
    import org.quartz.JobExecutionContext;  
    import org.quartz.JobExecutionException;  
    import org.springframework.scheduling.quartz.QuartzJobBean;  
      
    import java.util.Date;  
      
    public class SpringQtz {  
        private static int counter = 0;  
        protected void execute()  {  
            long ms = System.currentTimeMillis();  
            System.out.println("\t\t" + new Date(ms));  
            System.out.println("(" + counter++ + ")");  
        }  
    }


Spring的配置文件: 
apache

Xml代碼  收藏代碼app

  1. <!------------ 配置調度程序quartz ,其中配置JobDetail有兩種方式-------------->    
        <!--方式一:使用JobDetailBean,任務類必須實現Job接口 -->     
        <bean id="myjob" class="org.springframework.scheduling.quartz.JobDetailBean">    
         <property name="name" value="exampleJob"></property>    
         <property name="jobClass" value="com.ncs.hj.SpringQtz"></property>   
         <property name="jobDataAsMap">  
    <map>  
        <entry key="service"><value>simple is the beat</value></entry>  
    </map>  
    ;/property>  
        </bean>   
        <!--運行時請將方式一註釋掉! -->    
        <!-- 方式二:使用MethodInvokingJobDetailFactoryBean,任務類能夠不實現Job接口,經過targetMethod指定調用方法-->    
        <!-- 定義目標bean和bean中的方法 -->  
        <bean id="SpringQtzJob" class="com.ncs.hj.SpringQtz"/>  
        <bean id="SpringQtzJobMethod" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
        <property name="targetObject">  
            <ref bean="SpringQtzJob"/>  
        </property>  
        <property name="targetMethod">  <!-- 要執行的方法名稱 -->  
            <value>execute</value>  
        </property>  
    </bean>  
      
    <!-- ======================== 調度觸發器 ======================== -->  
    <bean id="CronTriggerBean" class="org.springframework.scheduling.quartz.CronTriggerBean">  
        <property name="jobDetail" ref="SpringQtzJobMethod"></property>  
        <property name="cronExpression" value="0/5 * * * * ?"></property>  
    </bean>  
      
    <!-- ======================== 調度工廠 ======================== -->  
    <bean id="SpringJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
        <property name="triggers">  
            <list>  
                <ref bean="CronTriggerBean"/>  
            </list>  
        </property>  
    </bean>


關於cronExpression表達式,這裏講解一下: 
字段 容許值 容許的特殊字符 
秒 0-59 , - * / 
分 0-59 , - * / 
小時 0-23 , - * / 
日期 1-31 , - * ? / L W C 
月份 1-12 或者 JAN-DEC , - * / 
星期 1-7 或者 SUN-SAT , - * ? / L C # 
年(可選) 留空, 1970-2099 , - * / 
表達式意義 
"0 0 12 * * ?" 天天中午12點觸發 
"0 15 10 ? * *" 天天上午10:15觸發 
"0 15 10 * * ?" 天天上午10:15觸發 
"0 15 10 * * ? *" 天天上午10:15觸發 
"0 15 10 * * ? 2005" 2005年的天天上午10:15觸發 
"0 * 14 * * ?" 在天天下午2點到下午2:59期間的每1分鐘觸發 
"0 0/5 14 * * ?" 在天天下午2點到下午2:55期間的每5分鐘觸發 
"0 0/5 14,18 * * ?" 在天天下午2點到2:55期間和下午6點到6:55期間的每5分鐘觸發 
"0 0-5 14 * * ?" 在天天下午2點到下午2:05期間的每1分鐘觸發 
"0 10,44 14 ? 3 WED" 每一年三月的星期三的下午2:10和2:44觸發 
"0 15 10 ? * MON-FRI" 週一至週五的上午10:15觸發 
"0 15 10 15 * ?" 每個月15日上午10:15觸發 
"0 15 10 L * ?" 每個月最後一日的上午10:15觸發 
"0 15 10 ? * 6L" 每個月的最後一個星期五上午10:15觸發 
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每個月的最後一個星期五上午10:15觸發 
"0 15 10 ? * 6#3" 每個月的第三個星期五上午10:15觸發 
天天早上6點 
0 6 * * * 
每兩個小時 
0 */2 * * * 
晚上11點到早上8點之間每兩個小時,早上八點 
0 23-7/2,8 * * * 
每月的4號和每一個禮拜的禮拜一到禮拜三的早上11點 
0 11 4 * 1-3 
1月1日早上4點 
0 4 1 1 *
 
最後別忘了在web.xml裏面配置Spring: 
maven

Xml代碼  收藏代碼ui

  1. <?xml version="1.0" encoding="UTF-8"?>  
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"  
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
              http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
             version="2.5">  
        <welcome-file-list>  
            <welcome-file>index.html</welcome-file>  
        </welcome-file-list>  
      
        <context-param>  
            <param-name>contextConfigLocation</param-name>  
            <param-value>/WEB-INF/spring-config.xml</param-value>  
        </context-param>  
      
        <listener>  
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
        </listener>  
    </web-app>


運行結果: 
Wed Feb 08 13:58:30 CST 2012 
(0) 
Wed Feb 08 13:58:35 CST 2012 
(1) 
Wed Feb 08 13:58:40 CST 2012 
(2) 
Wed Feb 08 13:58:45 CST 2012 
(3) 
Wed Feb 08 13:58:50 CST 2012 
(4) 
Wed Feb 08 13:58:55 CST 2012 
(5) 
Wed Feb 08 13:59:00 CST 2012 
(6) 


若是要用spring3.1  和quartz2以上,要引用3.1以上的包。和quartz2.2.1的版本。而後applicationcontext.xml中配置。

把調度觸發器改成:org.springframework.scheduling.quartz.CronTriggerFactoryBean 這個觸發器】


基本原理很簡單,項目啓動的時候加載web.xml。而後找到spring的配置文件:applicationcontext.xml。而後初始化調度器和調度任務。指定調度任務後根據設定的時間定時執行調度方法,咱們項目是用它來定時執行備份數據庫的腳本、天天備份數據庫。

方法一和方法二仍是有區別的.

  在和spring整合的時候,若是採用方法一,那麼方法一沒法獲取到spring管理的bean,致使在方法中autowrite的注入無效。若是採用方法二:那麼能夠獲取到spring管理的bean,依賴注入有效

相關文章
相關標籤/搜索