基于Spring实现定时调度

比较常用的是,Spring对Quartz的支持,可以非常容易地进行定时任务的调度。一般,具有两种方式实现定时调度:

一种是通过继承Spring的org.springframework.scheduling.quartz.QuartzJobBean来定义定时任务,这种情况下与Spring代码有一定耦合。下面,通过例子来说明:

实现一个定时任务类,代码如下所示:

    package org.shirdrn.spring.scheduler.quartz;  
      
    import org.apache.log4j.Logger;  
    import org.quartz.JobExecutionContext;  
    import org.quartz.JobExecutionException;  
    import org.springframework.scheduling.quartz.QuartzJobBean;  
      
    public class MyQuartzJob extends QuartzJobBean {  
      
        private static final Logger LOG = Logger.getLogger(MyQuartzJob.class);  
        private static int counter = 0;  
      
        @Override  
        protected void executeInternal(JobExecutionContext context)  
                throws JobExecutionException {  
            JobControlInfo job = (JobControlInfo) context.getMergedJobDataMap().get("jobControlInfo");  
            String manager = (String) context.getMergedJobDataMap().get("manager");  
            int length = Integer.parseInt((String) context.getMergedJobDataMap().get("length"));  
            LOG.info("context: job=" + job + ", manager=" + manager + ", length=" + length);  
            LOG.info("Execute quartz job /"" + (++counter) + "/".");  
        }  
    }  

上面的JobExecutionContext context是一个任务执行上下文,可以通过配置,将需要的数据传递给executeInternal方法,然后在该方法中定义任务的处理逻辑。

这里,假设有一个类包含了对定时任务的控制信息,实现类为JobControlInfo,形式化定义如下所示:

    package org.shirdrn.spring.scheduler.quartz;  
      
    public class JobControlInfo {  
      
    }  

通过Spring配置传递给JobExecutionContext context。

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" xmlns:p="http://www.springframework.org/schema/p"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
          
        <bean id="myScheduler" lazy-init="false" autowire="no"  
            class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
            <property name="triggers">  
                <list>  
                    <ref bean="myQuartzJobTrigger" />  
                </list>  
            </property>  
        </bean>  
        <bean id="myQuartzJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
            <property name="jobDetail" ref="myQuartzJobDetail" />  
            <property name="startDelay" value="5000"/>  
            <property name="repeatInterval" value="2000" />  
        </bean>  
        <bean id="myQuartzJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">  
            <property name="jobClass">  
                <value>org.shirdrn.spring.scheduler.quartz.MyQuartzJob</value>  
            </property>  
            <property name="jobDataAsMap">  
                <map>  
                    <entry key="jobControlInfo" value-ref="jobControlInfo" />  
                    <entry key="length" value="100000" />  
                    <entry key="manager" value="Jack" />  
                </map>  
            </property>  
        </bean>  
        <bean id="jobControlInfo" class="org.shirdrn.spring.scheduler.quartz.JobControlInfo" scope="prototype"/>  
      
    </beans>  

下面可以启动定时任务了,代码如下所示:

    package org.shirdrn.spring.scheduler.quartz;  
      
    import java.io.BufferedReader;  
    import java.io.IOException;  
    import java.io.InputStreamReader;  
      
    import org.quartz.impl.StdScheduler;  
    import org.springframework.context.ApplicationContext;  
    import org.springframework.context.support.ClassPathXmlApplicationContext;  
      
    public class ContextInitializer {  
        public static void main(String[] args) {  
            ApplicationContext ctx = new ClassPathXmlApplicationContext(  
                    "org/shirdrn/spring/scheduler/quartz/quartz.xml");  
            StdScheduler myScheduler = (StdScheduler)ctx.getBean("myScheduler");  
            BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));  
            try {  
                while(true) {  
                    String line = reader.readLine();  
                    if(line!=null) {  
                        boolean quit = line.trim().equalsIgnoreCase("quit") || line.trim().equalsIgnoreCase("q");  
                        if(quit) {  
                            myScheduler.shutdown(true);  
                            break;  
                        }  
                    }  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  

我们定义这个定时任务,执行时间间隔为2s。 

另一种是完全与Spring代码解耦合,而只是通过Spring配置就能进行定时任务的配置,一个定时任务可以是任意的Java处理类。而对于定时的配置,是基于Unix系统的crontab命令来实现的,更加灵活地配置定时任务。

下面说明实现方法:

定义一个普通的Java类,里面的一个方法里面包含了定时任务的处理逻辑,如下所示:

    package org.shirdrn.spring.scheduler.quartz.cron;  
      
    import org.apache.log4j.Logger;  
      
      
    public class MyQuartzJob {  
      
        private static final Logger LOG = Logger.getLogger(MyQuartzJob.class);  
        private static int counter = 0;  
          
        public void scan() {  
            LOG.info("Execute quartz job /"" + (++counter) + "/".");  
        }  
    } 

然后看下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" xmlns:p="http://www.springframework.org/schema/p"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
      
        <bean id="myScheduler" lazy-init="false" autowire="no"  
            class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
            <property name="triggers">  
                <list>  
                    <ref bean="myJobTrigger" />  
                </list>  
            </property>  
        </bean>  
        <bean id="myJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
            <property name="jobDetail">  
                <ref bean="myJobDetail" />  
            </property>  
            <property name="cronExpression">  
                <value>00,10,20,30,40,50 * * * * ?</value>  
            </property>  
        </bean>  
        <bean id="myJobDetail"  
            class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
            <property name="targetObject">  
                <ref bean="myJob" />  
            </property>  
            <property name="targetMethod">  
                <value>scan</value>  
            </property>  
        </bean>  
        <bean id="myJob" class="org.shirdrn.spring.scheduler.quartz.cron.MyQuartzJob" />  
    </beans>  

通过Spring的org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean来设置目标定时任务处理内容,如处理类和处理方法,通过org.springframework.scheduling.quartz.CronTriggerBean的cronExpression属性来配置定时任务,非常灵活。

上述配置,定时任务会自动调用MyQuartzJob类的scan方法来执行任务。

对于cronExpression属性的值,包括以下7 个字段:

    秒   
    分   
    小时   
    月内日期   
    月   
    周内日期   
    年(可选字段)  

有关各个字段可以设置的值:

    Cron 触发器利用一系列特殊字符,如下所示:  
      
    ?反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。  
      
      
    ?问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行。  
      
      
    ?在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中,表示把执行安排在当月的第一个工作日内。  
      
      
    ?井号(#)字符为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。  
      
      
    ?星号(*)字符是通配字符,表示该字段可以接受任何可能的值。    

更多信息可以查阅相关资料。

启动定时任务,测试代码如下所示:

    package org.shirdrn.spring.scheduler.quartz.cron;  
      
    import org.springframework.context.ApplicationContext;  
    import org.springframework.context.support.ClassPathXmlApplicationContext;  
      
    public class ContextInitializer {  
        public static void main(String[] args) {  
            ApplicationContext ctx = new ClassPathXmlApplicationContext(  
                    "org/shirdrn/spring/scheduler/quartz/cron/quartz.xml");  
            ctx.getBean("myScheduler");  
        }  
    }  

 

你可能感兴趣的:(基于Spring实现定时调度)