Spring3整合Quartz实现定时作业

QuartzOpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EEJ2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表。Jobs可以做成标准的Java组件或 EJBs
Quartz是一个任务日程管理系统,一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。

Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了所有Quartz核心功能。这些功能的主要接口(API)Scheduler接口。它提供了简单的操作,例如:将任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。

quartz下载: http://www.quartz-scheduler.org/download/index.html 

Spring3中整合Quartz
虽然Quartz已经发布了2.X版本,但是Spring3目前只能整合Quartz1.8.5及以下版本。 

项目结构图



1.作业调度类的实现

package org.dennist.jobs;

import org.apache.log4j.Logger;
import org.dennist.service.SystemTimeHandler;
/**
*
*   
*
*  @version : 1.1
*  
*  @author  : 苏若年          <a href="mailto:DennisIT@163.com">发送邮件</a>
*    
*  @since   : 1.0        创建时间:   2013-7-8       上午09:49:20
*     
*  TODO     : org.dennist.jobs.TimeQuartzJob.java
*
*/

public class TimeQuartzJob {

    private final Logger logger = Logger.getLogger(TimeQuartzJob.class);
    
    private SystemTimeHandler systemTimeHandler;
    
    public void noticeSystemTime(){
        logger.info("定时器执行,调用系统时间服务类中的系统时间通知方法");    
        systemTimeHandler.noticeSystemTime();
    }

    public SystemTimeHandler getSystemTimeHandler() {
        return systemTimeHandler;
    }

    public void setSystemTimeHandler(SystemTimeHandler systemTimeHandler) {
        this.systemTimeHandler = systemTimeHandler;
    }
    
}

作业调度类中调用实现了SystemTimeHandler接口的类SystemTimeHandlerImpl,实现定时向控制台输出格式化的系统时间,SystemTimeHandlerImpl的类实现如下

package org.dennist.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.Logger;
import org.dennist.jobs.TimeQuartzJob;
import org.dennist.service.SystemTimeHandler;

/**
 *
 *   
 *
 *  @version : 1.1
 *  
 *  @author  : 苏若年          <a href="mailto:DennisIT@163.com">发送邮件</a>
 *    
 *  @since   : 1.0        创建时间:   2013-7-8       上午09:55:10
 *     
 *  TODO     : org.dennist.service.impl.SystemTimeHandlerImpl.java
 *
 */

public class SystemTimeHandlerImpl implements SystemTimeHandler{

    private final Logger logger = Logger.getLogger(TimeQuartzJob.class);
    
    public void noticeSystemTime() {
        logger.info("notice system time to all users");
        SimpleDateFormat format = new SimpleDateFormat("现在时间是: yyyy/MM/dd hh:mm:ss");
        System.out.println(format.format(new Date()).toString());
    }

}

2.Web.xml中配置spring上下文监听和quartz初始化监听

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    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">
    
    <display-name>spring-quartz</display-name>
    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>quartzapp</param-value>
    </context-param>
    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.properties</param-value>
    </context-param>
    <context-param>
        <param-name>log4jRefreshInterval</param-name>
        <param-value>3000</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context.xml</param-value>
    </context-param>
    
    <!-- Quartz初始化监听 -->
    <listener>
        <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
    </listener>
    
    <!-- 注入 字符编码过滤器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    
    <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
View Code

3.contextConfigLocation指定配置文件的路径为根目录下的spring-context.xml,该配置文件中引入系统Bean实例化管理配置文件spring-beans.xml和定时任务配置类spring-jobs.xml.

spring-context.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:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    
    <context:component-scan base-package="com.dennisit" />
        
    <!-- Root Context: defines shared resources visible to all other web components -->

    <import resource="spring-beans.xml" />
    
    <import resource="spring-jobs.xml" />    
    
</beans>

Bean管理配置文件spring-beans.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:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    
    <!-- 实例化service对象 -->
    <bean id="systemTimeHandler" class="org.dennist.service.impl.SystemTimeHandlerImpl" autowire="byType"/>
    
</beans>

定时作业管理配置文件spring-jobs.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:p="http://www.springframework.org/schema/p" 
    xmlns:task="http://www.springframework.org/schema/task" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/task  
    http://www.springframework.org/schema/task/spring-task-3.0.xsd">
    
   <!--  
           这里加入了  
        xmlns:task="http://www.springframework.org/schema/task"  
           http://www.springframework.org/schema/task   
           http://www.springframework.org/schema/task/spring-task-3.0.xsd  
   --> 
   
       <!--  spring3.0之前的用法,配置比较繁琐 --> 
   
    <!-- 值班提醒定时器  这个是定时器要调用方法的类 -->   
    <bean id="timeNoticeJob" class="org.dennist.jobs.TimeQuartzJob" autowire="byType"/>
            
    <!-- 定义调用对象和调用对象的方法   -->     
    <bean id="timeNoticeJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="timeNoticeJob"/> <!-- 调用的类 --> 
        <property name="targetMethod" value="noticeSystemTime" /> <!-- 调用类中的方法 --> 
        <property name="concurrent" value="true"/>   <!-- false,证明不执行并发任务 -->   
    </bean> 
    
    <!-- 定义触发时间 -->
    <bean id="timeNoticeJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="timeNoticeJobDetail" /> 
        <property name="cronExpression"> 
            <value>0 0/1 * * * ?</value> <!-- cron表达式 此处定义为一直触发执行任务 -->
        </property>  
    </bean> 

    <!-- 调度工厂,将触发时间列入; 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
    <bean id="schedulerlist" lazy-init="false"
 autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
      <property name="triggers"> 
             <list> 
                 <ref bean="timeNoticeJobTrigger"/>
                 <!-- 可以增加多个定时作业 -->
             </list>
      </property>
    </bean>

 </beans>

4.程序执行效果图,每隔一分钟在控制台打印系统时间



说明:上面的方法是在Spring3之前用的配置方法,spring3之后使用如下方法配置,方便简单.

<?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:p="http://www.springframework.org/schema/p" 
    xmlns:task="http://www.springframework.org/schema/task" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/task  
    http://www.springframework.org/schema/task/spring-task-3.0.xsd">
    
    <!--  spring3.0之后的新用法,配置有变化,而且比以前简单了很多 --> 

    <!-- 定时器  这个是定时器要调用方法的类 --> 
      <bean id="timeNoticeJob" class="org.dennist.jobs.TimeQuartzJob" autowire="byType"/>
  
      <!-- 定义调用对象和调用对象的方法   --> 
      <task:scheduled-tasks>
        <!-- 调用的类TimeQuartzJob    调用类中的方法noticeSystemTime  设置每分钟调用一次-->
        <task:scheduled ref="timeNoticeJob" method="noticeSystemTime" cron="0 0/1 * * * ?" />
      </task:scheduled-tasks> 
 
 </beans>

 

5.Quartz中的cron表达式说明

一个cron表达式有至少6个(也可能是7个)由空格分隔的时间元素。从左至右,这些元素的定义如下:
1.秒(0–59)
2.分钟(0–59)
3.小时(0–23)
4.月份中的日期(1–31)
5.月份(1–12或JAN–DEC)
6.星期中的日期(1–7或SUN–SAT)
7.年份(1970–2099) 为可选属性

每一个元素都可以显式地规定一个值(如6),一个区间(如9-12),一个列表(如9,11,13)或一个通配符(如*)。“月份中的日期”和“星期中的日期”这两个元素是互斥的,因此应该通过设置一个问号(?)来表明你不想设置的那个字段。如下显示了一些cron表达式的例子和它们的意义:

"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触发
"0 6 * * *"  每天早上6点
"0 */2 * * *"每两个小时
"0 23-7/2,8 * * *" 晚上11点到早上8点之间每两个小时,早上八点
"0 11 4 * 1-3" 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
"0 4 1 1 *" 1月1日早上4点

 
附 录:
Quartz中的cron表达式跟Linux中的crontab有所不同,如下为Linux中的自动化定时任务crontab命令
基本格式 :

*  *  *  *  *  command
分 时 日 月 周 命令

前五个字段可以取整数值,指定何时开始工作,第六个域是字符串,即命令字段,其中包括了crontab调度执行的命令。 各个字段之间用spaces或tabs分割。

前5个字段分别表示:
     分钟:0-59
     小时:1-23
     日期:1-31
     月份:1-12
     星期:0-6(0表示周日)
第6个字段表示运行的命令

还可以用一些特殊符号:

      *:表示任何时刻
       ,:表示分割
     -:表示一个段,如第二端里: 1-5,就表示1到5点
     /n: 表示每个n的单位执行一次,如第二段里,*/1, 就表示每隔1个小时执行一次命令。也可以写成1-23/1.


举例:

30 21 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每晚的21:30重启apache。

45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每月1、10、22日的4 : 45重启apache。


10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每周六、周日的1 : 10重启apache。

0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。

0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每星期六的11 : 00 pm重启apache。

* */1 * * * /usr/local/etc/rc.d/lighttpd restart
每一小时重启apache

* 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart
晚上11点到早上7点之间,每隔一小时重启apache

0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart
每月的4号与每周一到周三的11点重启apache

0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart
一月一号的4点重启apache

 
参考文献:[ http://blog.sina.com.cn/s/blog_71420de901019jg5.html ]

转载请注明出处:[ http://www.cnblogs.com/dennisit/p/3177800.html ]

 

posted @ 2013-07-08 14:54  苏二  阅读(1659)  评论(0编辑  收藏  举报