1. 程式人生 > >SpringMVC整合Quartz實現定時任務和Spring自帶Task定時任務

SpringMVC整合Quartz實現定時任務和Spring自帶Task定時任務

在java中我們常用Timer和TimerTask實現定時功能,而在JavaEE專案中可以使用Spring整合Quartz定時器、Spring的Task任務。相比於Spring自帶的任務,Quartz非常的強大,能夠實現所有想要的定時任務,包括Tomcat伺服器開始啟動,定時定點定周,叢集定時任務等等的任務,有關Quartz的介紹和時間配置網上有很多的資料,就不在累贅,下面主要介紹SpringMVC整合Quartz的實現步驟。

一、Quartz定時任務

1、引入quartz 

 匯入quartz.jar包,或者pom.xml 配置對應的依賴:

                <dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>1.8.6</version>
		</dependency> 

2、 Web.xml配置

在Web專案web.xml中配置quartz的配置檔案載入路徑:

        <servlet>
		<servlet-name>rest</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				/WEB-INF/classes/rest-servlet.xml, 
			   /WEB-INF/classes/pyc-spring-quartz.xml
			</param-value>
		</init-param> 
		<load-on-startup>1</load-on-startup>
	</servlet> 

3、寫具體的定時排程的任務:

package andy.test.quartz.schedule;

/**  
 * @author Zhang,Tianyou  
 * @version:2014-12-11 下午12:00:24  
 * 
 *  一個測試的列印定時任務
 */

public class MyPrintSchedule {

	public void printSomething(){
		//內容就是列印一句話
		System.out.println("this is andy schedule");
	}
}
 

4、配置quartz的xml配置資訊

    Quartz配置檔名字可以隨便,需和web.xml中的一致。

     pyc-spring-quartz.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<!-- 新增排程的任務bean 配置對應的class-->
	<bean id="myPrintSchedule" class="andy.test.quartz.schedule.MyPrintSchedule" />

    <!--配置排程具體執行的方法-->
	<bean id="myPrintDetail"
		class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="myPrintSchedule" />
		<property name="targetMethod" value="printSomething" />
		<property name="concurrent" value="false" />
	</bean>

	<!--配置排程執行的觸發的時間-->
	<bean id="myPrintTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail" ref="myPrintDetail" />
		<property name="cronExpression">
			<!-- 每天早上8點執行任務排程 -->
			<value>0 0 8 * * ?</value>
		</property>
	</bean>

	

	<!-- quartz的排程工廠 排程工廠只能有一個,多個排程任務在list中新增 -->
	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="triggers">
			<list>
			     <!-- 所有的排程列表-->
				<ref local="myPrintTrigger" />
				
			</list>
		</property>
	</bean>

</beans> 

這樣就實現了myPrint的任務排程,執行時間是每天早上8點執行一次,列印:

     this is andy schedule

這句話。

quartz的功能是非常強大的,使用也非常的簡單方便,有事需要web啟動時,執行一些初始化的任務,這是我們執行配置對應的執行排程的觸發時間就能完成。其具體實現如下:

 <!--配置排程執行的觸發的時間-->
	<bean id="myPrintTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail" ref="myPrintDetail" />
		<property name="cronExpression">
			<!-- 不重複計數,只執行一次 -->
			<property name="repeatCount" value="0" />
		</property>
	</bean> 

上面的配置完成了,伺服器啟動執行的任務。只被執行一次。

二、Spring自帶的任務Task

   Spring自帶的定時任務是在spring3之後支援,相比於quartz定時任務Spring相對於簡單,配置也很簡單。quartz功能比Spring Task強大,支援叢集功能。

  1、在spring配置中新增task的schema

    pring配置檔案頭中新增名稱空間及描述

 <beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	
	//....其他
	
	xmlns:task="http://www.springframework.org/schema/task" 
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
		
		//.....其他
		
		http://www.springframework.org/schema/task
		http://www.springframework.org/schema/task/spring-task-4.1.xsd"> 

2、開啟掃描定時任務包

 <context:component-scan base-package="org.andy.task" /> 

3、配置開啟任務

 <task:annotation-driven /> 

  如果任務比較多,可以新增任務池
 <task:scheduler id="scheduler" pool-size="5" />
<task:annotation-driven executor="executor" scheduler="scheduler" />
    如果定時任務很多,可以配置executor執行緒池,這裡executor的含義和java.util.concurrent.Executor是一樣的,pool-size的大小官方推薦為5~10。scheduler的pool-size是ScheduledExecutorService執行緒池 

4、Spring的POJO任務類

package org.andy.task;

import org.apache.log4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 建立時間:2016年5月12日 下午3:48:38
 * 
 * @author andy
 * @version 2.2
 */
@Component("taskJob")
public class TaskJob {

	private static final Logger LOG = Logger.getLogger(TaskJob.class);
	
	//每分鐘的10秒執行
	@Scheduled(cron = "10 * * * * ?")
	public void job1(){
		LOG.info("hello。。。。"); 
	}
	
	//每10秒執行一次
    @Scheduled(fixedRate = 1000 * 1) 
	public void job(){
    	LOG.info("world");
	}
}
 


三、定時配置

   spring的task和quartz的任務格式都是一樣的。

Cron表示式包括下面7個欄位並區別順序:秒0-59,分0-59,小時0-23,月內日期1-31,月1-12或者JAN-DEC,周內日期1-7或者SUN-SAT,年(可選欄位)留空或者1970-2099並且通過特殊字元表示特殊意義,具體為下:
    斜線(/)字元表示增量值。例如,在秒欄位中"5/15"代表從第5秒開始,每15秒一次。
    問號(?)字元和字母L字元只有在月內日期和周內日期欄位中可用。問號表示這個欄位不包含具體值。所以,如果指定月內日期,可以在周內日期欄位中插入"?",表示周內日期值無關緊要。這裡有個很蛋疼的設定,無關Quartz,而是Spring整合Quartz後,它自己加的一個約束,那就是:日期(1-31)和星期(SUN-SAT)兩者,必須有一個是問號(?),系統在啟動的時候,Spring會檢查表示式,如果不符合它的規則,就會拋異常。所以在使用的時候這個地方一定要注意,而這個在Linux上執行Cron是沒有這個限制的。
    字母L字元是last的縮寫。放在月內日期欄位中,表示安排在當月最後一天執行。在周內日期欄位中,如果"L"單獨存在,就等於"7",否則代表當月內周內日期的最後一個例項。所以"0L"表示安排在當月的最後一個星期日執行。
    字母(W)字元把執行安排在最靠近指定值的工作日。把"1W"放在月內日期欄位中,表示把執行安排在當月的第一個工作日內。
    井號(#)字元為給定月份指定具體的工作日例項。把"MON#2"放在周內日期欄位中,表示把任務安排在當月的第二個星期一。
    星號(*)字元是通配字元,表示該欄位可以接受任何可能的值、表示式例子。
    例子:
    "0 0 08 * * ?" 每天上午8點觸發
    "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 2009-2019" 2009年至2019年的每月的最後一個星期五上午10:15觸發
    "0 15 10 ? * 6#3" 每月的第三個星期五上午10:15觸發