zoukankan      html  css  js  c++  java
  • 【spring配置】——spring整合Quartz定时器

    第一种:为普通java类中的某个方法配置跑批任务

    1. MethodInvokingJobDetailFactoryBean  
    2. CronTriggerBean  
    3. SchedulerFactoryBean  

    1.定义要跑批的类和方法:

    1. package com.xy.utils.quartz;  
    2.   
    3. import org.joda.time.DateTime;  
    4. import org.slf4j.Logger;  
    5. import org.slf4j.LoggerFactory;  
    6.   
    7. /** 
    8.  * 测试定时器类 
    9.  * @author javaw 
    10.  * 
    11.  */  
    12. public class TestQuartz {  
    13.         
    14.        public static Logger logger = LoggerFactory.getLogger(TestQuartz.class);    
    15.        public void TestMethod(){  
    16.             logger.info("Auto Execute TestMethod start! Date={}" ,new DateTime().toString("YYYY-MM-DD HH:mm:ss" ));  
    17.             logger.info("**********测试跑批类************");  
    18.             logger.info("Auto Execute TestMethod end! Date={}" ,new DateTime().toString("YYYY-MM-DD HH:mm:ss" ));  
    19.       }  
    20. }  

    2.配置Spring定时器让quartz自动执行testMethod方法:

    1. <!-- 实例化bean -->  
    2. <bean id= "testMethodQuartz" class ="com.xy.utils.quartz.TestQuartz"/>  
    3.   
    4. <!-- 配置MethodInvokingJobDetailFactoryBean -->  
    5. <bean id= "testTaskMethod"  
    6. class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
    7.        <property name="targetObject" ref="testMethodQuartz"/>  
    8.        <property name="targetMethod" value="TestMethod"/>  
    9.        <property name="concurrent" value="false"/>  
    10. </bean>  
    11.   
    12. <!-- 配置定时表达式 -->  
    13. <bean id= "testTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >  
    14.        <property name="jobDetail" ref="testTaskMethod" />   
    15.       <!-- 每一分钟执行一次 -->   
    16.       <property name="cronExpression" value="0 0/1 * * * ?" />   
    17. </bean>  
    18.   
    19. <!-- 配置调度工厂 -->  
    20. <bean id= "testSchedulerFactoryBean"  
    21.     class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    22.        <property name="triggers" >  
    23.              <list>  
    24.                    <ref bean="testTaskTrigger" />  
    25.              </list>  
    26.        </property>  
    27. </bean>  

    3.写测试方法进行调用(不用启动tomcat):

    1. public static void main(String[] args) {  
    2.       SchedulerFactoryBean schedulerFactoryBean = (SchedulerFactoryBean) SpringUtilsFromClassPathXml.getBean( "testSchedulerFactoryBean");  
    3.              //启动调度器  
    4.       schedulerFactoryBean.start();  
    5. }  

    第二种:为继承QuartzJobBean的java类配置跑批任务

    1.写java类继承QuartzJobBean,重写executeInternal 方法:

    1. package com.xy.utils.quartz;  
    2.   
    3. import org.joda.time.DateTime;  
    4. import org.quartz.JobExecutionContext;  
    5. import org.quartz.JobExecutionException;  
    6. import org.slf4j.Logger;  
    7. import org.slf4j.LoggerFactory;  
    8. import org.springframework.scheduling.quartz.QuartzJobBean;  
    9. import org.springframework.scheduling.quartz.SchedulerFactoryBean;  
    10.   
    11. /** 
    12.  * 测试继承QuartzJobBean的java类配置定时器 
    13.  * @author javaw 
    14.  * 
    15.  */  
    16. public class TestQuartzExtendsJobBean extends QuartzJobBean{  
    17.         
    18.        private static Logger logger = LoggerFactory.getLogger(TestQuartzExtendsJobBean. class);  
    19.         
    20.        @Override  
    21.        protected void executeInternal(JobExecutionContext context)  
    22.                    throws JobExecutionException {  
    23.             logger.info("Auto Execute TestQuartzExtendsJobBean start! Date={}",new DateTime().toString( "YYYY-MM-DD HH:mm:ss"));  
    24.             logger.info("**********"+content.getMergedJobDataMap().get("descString")+"************");  
    25.             logger.info("Auto Execute TestQuartzExtendsJobBean end! Date={}",new DateTime().toString( "YYYY-MM-DD HH:mm:ss"));  
    26.       }  
    27. }  

    2.配置文件:

    1. <!--  
    2.       第二种:为继承Quartz的java类实现跑批  
    3.       **********1.JobDetailBean  
    4.       **********2.CronTriggerBean  
    5.       **********3.SchedulerFactoryBean  
    6.  -->  
    7. <bean id= "testJobDetailBean"  
    8.      class="org.springframework.scheduling.quartz.JobDetailBean">     
    9.       <property name="name" value="exampleJob" />     
    10.       <property name="jobClass"  
    11.           value="com.xy.utils.quartz.TestQuartzExtendsJobBean"/>  
    12.       <!-- 可以封装各种数据到JobExecutionContext里 -->     
    13.       <property name="jobDataAsMap">    
    14.        <map>    
    15.          <entry key="descString" value="测试跑批"/>  
    16.        </map>    
    17.      </property>    
    18.   </bean >   
    19.    
    20. <bean id= "testTaskTrigger"  
    21.      class="org.springframework.scheduling.quartz.CronTriggerBean">  
    22.        <property name="jobDetail" ref="testJobDetailBean" />   
    23.       <property name="cronExpression" value="0 0/1 * * * ?" />   
    24. </bean>  
    25.   
    26. <bean id= "testSchedulerFactoryBean"  
    27.     class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    28.        <property name="triggers" >  
    29.              <list>  
    30.                    <ref bean="testTaskTrigger" />  
    31.              </list>  
    32.        </property>  
    33. </bean>  

    第三种:定时任务持久化(JobDetailTx)

    优势:

    集群部署定时器通过故障切换和负载均衡的功能,提高调度器的可用性和扩展性。

    本质:

    集群上的所有节点通过共享一个数据库来来工作的。所有节点quartz通过启动两个维护线程来维护数据库状态实现集群管理,一个是检测节点状态线程,一个是恢复任务线程。一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。

    模式:

    1.获取任务

    负载均衡是自动完成的,集群的每个节点会尽快触发任务。当第一个节点获取到任务,会通过锁定,阻止其他线程获取到该任务。

    2.故障切换

    当一个节点执行任务失败(服务down掉或其他原因),其他节点会检测到并标识在失败节点上正在执行的数据库中的任务。任何标记为可恢复(任务详细里的requests recovery属性)的任务都会被其他节点继续执行。没有标记可恢复的任务会被释放掉。

    1. CREATE TABLE qrtz_job_details  
    2.   (  
    3.   ....  
    4.   JOB_NAME VARCHAR2(80) NOT NULL,  
    5.   JOB_GROUP VARCHAR2(80) NOT NULL,  
    6.   REQUESTS_RECOVERY VARCHAR2(1) NOT NULL, --可恢复标记  
    7.   );  


    1. SchedulerFactoryBean  
    2. JobDetail  
    3. Trigger  
    4. Job  

    将定时任务持久化可以解决分布式跑批的问题,避免服务器重启信息丢失。

    定时任务定义需要实例化JobDetail和Trigger,然后使用Scheduler进行调度。这个需要使用到Quartz的jar包。

    每个jar包创建任务的方式都不相同。具体需要查看官方api。

    quartz2.2.1中给出的示例:

    1. JobDetail job = newJob(MyJob.class)  
    2.              .withIdentity("myJob")  
    3.              .build();  
    4.                
    5. Trigger trigger = newTrigger()   
    6.              .withIdentity(triggerKey("myTrigger", "myTriggerGroup"))  
    7.              .withSchedule(simpleSchedule()  
    8.                  .withIntervalInHours(1)  
    9.                  .repeatForever())  
    10.              .startAt(futureDate(10, MINUTES))  
    11.              .build();  
    12.            
    13. scheduler.scheduleJob(job, trigger);  

    导入jar包后,写如下测试类:

    1. package com.xy.utils.scheduler;  
    2.   
    3. import org.quartz.JobBuilder;  
    4. import org.quartz.JobDetail;  
    5. import org.quartz.Scheduler;  
    6. import org.quartz.SchedulerFactory;  
    7. import org.quartz.SimpleScheduleBuilder;  
    8. import org.quartz.Trigger;  
    9. import org.quartz.TriggerBuilder;  
    10. import org.quartz.impl.StdSchedulerFactory;  
    11.   
    12. public class quartzTest {  
    13.   
    14.     public static void main(String args[]) throws Exception {  
    15.         JobDetail jobDetail= JobBuilder.newJob(TestJob.class)  
    16.                 .withIdentity("job","group")  
    17.                 .build();  
    18.    
    19.         Trigger trigger= TriggerBuilder.newTrigger().withIdentity("job","group").startNow().withSchedule(  
    20.                 SimpleScheduleBuilder.simpleSchedule()  
    21.                         .withIntervalInSeconds(10)   //时间间隔  
    22.                         .withRepeatCount(10)        //重复次数n+1  
    23.                         )  
    24.                 .build();  
    25.         SchedulerFactory sf = new StdSchedulerFactory();  
    26.         Scheduler sched = sf.getScheduler();  
    27.         sched.scheduleJob(jobDetail, trigger);  
    28.           
    29.         sched.start();  
    30.     }  
    31. }  

    定时执行的任务类:

    1. package com.xy.utils.scheduler;  
    2.   
    3. import org.quartz.Job;  
    4. import org.quartz.JobExecutionContext;  
    5. import org.quartz.JobExecutionException;  
    6.   
    7. public class TestJob implements Job {  
    8.     public void execute(JobExecutionContext arg0) throws JobExecutionException {  
    9.         System.out.println("*****执行批处理任务******");  
    10.     }  
    11. }  

    这种任务并没有持久化到数据库中。

    在Spring中配置SchedulerFactoryBean:

    1. <!--   
    2. 第三种:从数据库中读取跑批任务(适合集群部署跑批)  
    3. **********1.SchedulerFactoryBean  
    4. -->  
    5. <bean id="schedulerBeanFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    6. <!-- 注入数据源,包含任务执行表 -->  
    7. <property name="dataSource" ref="dataSource"/>  
    8. <!--applicationContextSchedulerContextKey:   
    9.     把spring上下文以key/value的方式存放在了quartz的上下文中了,  
    10.     可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文-->    
    11. <property name="applicationContextSchedulerContextKey" value="applicationContext"/>     
    12. <!-- 读取配置文件 -->  
    13. <property name="configLocation" value="classpath:/properties/quartz.properties"/>  
    14. <property name="autoStartup" value="true"/>  
    15. </bean>  

    配置quartz.properties:

    下载了quartz.jar后,在quartz-2.2.1srcorgquartz目录下有个quartz.properties的文件,可以根据自己的需要更改其中的配置内容。

    1. #批处理常量表 QUARTZ2.2.1  
    2. #============================================================================  
    3. # Configure Main Scheduler Properties  
    4. #============================================================================  
    5. org.quartz.scheduler.instanceName = MyQuartzScheduler  
    6. org.quartz.scheduler.instanceId = AUTO  
    7. #============================================================================  
    8. # Configure ThreadPool  
    9. #============================================================================  
    10. org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
    11. org.quartz.threadPool.threadCount = 10  
    12. org.quartz.threadPool.threadPriority = 5  
    13. org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread:true  
    14. #============================================================================  
    15. # Configure JobStore  
    16. #============================================================================  
    17. org.quartz.jobStore.misfireThreshold = 10000  
    18. org.quartz.jobStore.class = org.springframework.scheduling.quartz.LocalDataSourceJobStore  
    19. org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate  
    20. org.quartz.jobStore.isClustered = true --是否集群部署  
    21. #任务表前缀  
    22. org.quartz.jobStore.tablePrefix = test_qrtz_  

    创建任务表:

    jar包文件中,给出了所有数据库的建表语句。可以根据给出的sql语句创建表。

    调度类:

    1. package com.xy.utils.scheduler;  
    2.   
    3. import org.quartz.JobBuilder;  
    4. import org.quartz.JobDetail;  
    5. import org.quartz.Scheduler;  
    6. import org.quartz.SimpleScheduleBuilder;  
    7. import org.quartz.Trigger;  
    8. import org.quartz.TriggerBuilder;  
    9.   
    10. import com.xy.utils.SpringUtils.SpringUtilsFromClassPathXml;  
    11.   
    12. public class quartzTest {  
    13.     //从Spring中获取调度bean工厂  
    14.     public static Scheduler scheduler = (Scheduler)SpringUtilsFromClassPathXml.getBean("schedulerBeanFactory");  
    15.       
    16.     public static void main(String args[]) throws Exception {  
    17.         JobDetail jobDetail= JobBuilder.newJob(TestJob.class)  
    18.                 .withIdentity("job","group")  
    19.                 .build();  
    20.    
    21.         Trigger trigger= TriggerBuilder.newTrigger().withIdentity("job","group").startNow().withSchedule(  
    22.                 SimpleScheduleBuilder.simpleSchedule()  
    23.                         .withIntervalInSeconds(10) //时间间隔  
    24.                         .repeatForever()  
    25.                         )  
    26.                 .build();  
    27.         scheduler.scheduleJob(jobDetail, trigger);  
    28.         scheduler.start();  
    29.     }  
    30. }  

    任务类(需要实现job接口):

    1. package com.xy.utils.scheduler;  
    2.   
    3. import org.quartz.Job;  
    4. import org.quartz.JobExecutionContext;  
    5. import org.quartz.JobExecutionException;  
    6.   
    7. public class TestJob implements Job {  
    8.     public void execute(JobExecutionContext arg0) throws JobExecutionException {  
    9.         System.out.println("*****执行批处理任务******");  
    10.     }  
    11. }  

    此时执行该类就会将任务数据写入数据库中。


    调度任务工具类:

    自定义任务调度工具类:

    1. package com.xy.utils.scheduler;  
    2.   
    3. import java.text.ParseException;  
    4. import java.text.SimpleDateFormat;  
    5. import java.util.Date;  
    6.   
    7. import org.quartz.CronScheduleBuilder;  
    8. import org.quartz.CronTrigger;  
    9. import org.quartz.DateBuilder;  
    10. import org.quartz.Job;  
    11. import org.quartz.JobBuilder;  
    12. import org.quartz.JobDetail;  
    13. import org.quartz.Scheduler;  
    14. import org.quartz.SchedulerException;  
    15. import org.quartz.SimpleScheduleBuilder;  
    16. import org.quartz.Trigger;  
    17. import org.quartz.TriggerBuilder;  
    18. import org.quartz.TriggerKey;  
    19. import org.quartz.DateBuilder.IntervalUnit;  
    20. import org.slf4j.Logger;  
    21. import org.slf4j.LoggerFactory;  
    22.   
    23. import com.xy.common.SysContent;  
    24.   
    25. public class SchedulerJobUtils {  
    26.     private static Logger logger = LoggerFactory.getLogger(SchedulerJobUtils.class);  
    27.       
    28.     public static Scheduler scheduler = (Scheduler)SysContent.applicationContext.getBean("schedulerBeanFactory");  
    29.     //public static Scheduler scheduler = (Scheduler)SpringUtilsFromClassPathXml.getBean("schedulerBeanFactory");  
    30.     public static String dateFormate = "ss mm HH dd MM ? yyyy";  
    31.     public static SimpleDateFormat cronSdf = new SimpleDateFormat(dateFormate);  
    32.     public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    33.       
    34.     /** 
    35.      * 数据库放入一个指定时间的任务,任务只执行一次 
    36.      * @see 适合对数据进行定时删除,修改等等 
    37.      * @param <T> 
    38.      * @param clazz  要执行任务类class,任务类必须继承Job类 
    39.      * @param jobName 任务名称 
    40.      * @param groupName 分组名称 
    41.      * @param executeTime 执行时间,格式:yyyy-MM-dd HH:mm:ss 
    42.      * @return 
    43.      */  
    44.     public static<T> boolean putSpecifyTimeSchedulerJobToDB(Class<? extends Job> clazz,String jobName,String groupName,String executeTime){  
    45.         //定义一个job  
    46.         JobDetail job = JobBuilder.newJob(clazz).withIdentity(jobName, groupName).build();  
    47.         //定义一个TriggerKey  
    48.         TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);  
    49.           
    50.         SchedulerJob schedulerJob = new SchedulerJob();  
    51.         schedulerJob.setJobName(jobName);  
    52.         schedulerJob.setGroupName(groupName);  
    53.         job.getJobDataMap().put("schedulerJob", schedulerJob);  
    54.           
    55.         Date executeDate = null;  
    56.           
    57.         try {  
    58.             executeDate = sdf.parse(executeTime);  
    59.         } catch (ParseException e) {  
    60.             logger.info("method putSchedulerJobToDB execute error!exception={}",e);  
    61.         }  
    62.         String dbExecuteTime = cronSdf.format(executeDate);  
    63.         CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(dbExecuteTime)).build();  
    64.           
    65.         try {  
    66.             scheduler.scheduleJob(job, cronTrigger);  
    67.         } catch (SchedulerException e) {  
    68.             logger.info("method putSchedulerJobToDB execute error!exception={}",e);  
    69.         }  
    70.         return true;  
    71.     }  
    72.       
    73.     /** 
    74.      * 数据库放入一条指定开始时间,指定间隔时间,指定次数的任务 
    75.      * @param <T>  
    76.      * @param clazz 任务类 
    77.      * @param jobName  任务名 
    78.      * @param groupName 分组名 
    79.      * @param seconds   间隔时间,以秒为单位 
    80.      * @param count 执行次数,0为一直执行 
    81.      * @param startSecondsToNow 开始时间(距离现在?秒) 
    82.      * @return 
    83.      * @throws SchedulerException  
    84.      */  
    85.     @SuppressWarnings("unchecked")  
    86.     public static<T> boolean putPeriodSchedulerJobToDB(Class<? extends Job> clazz,String jobName,String groupName,  
    87.             int seconds,int count,int startSecondsToNow){  
    88.         JobDetail jobDetail= JobBuilder.newJob(clazz).withIdentity(jobName,groupName).build();  
    89.         TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger().withIdentity(jobName,groupName);  
    90.         if(startSecondsToNow==0){  
    91.             triggerBuilder.startNow();  
    92.         }else{  
    93.             triggerBuilder.startAt(DateBuilder.futureDate(startSecondsToNow,IntervalUnit.SECOND));  
    94.         }  
    95.         SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(seconds);  
    96.         if(count==0){  
    97.             scheduleBuilder.repeatForever();  
    98.         }else{  
    99.             scheduleBuilder.withRepeatCount(count);  
    100.         }  
    101.         Trigger trigger = triggerBuilder.withSchedule(scheduleBuilder).build();  
    102.         try {  
    103.             scheduler.scheduleJob(jobDetail,trigger);  
    104.         } catch (SchedulerException e) {  
    105.             logger.info("put putPeriodSchedulerJobToDB error,error={}",e);  
    106.         }  
    107.         return true;  
    108.     }  
    109. }  

    任务类:

    1. package com.xy.utils.scheduler;  
    2.   
    3. import org.joda.time.DateTime;  
    4. import org.quartz.Job;  
    5. import org.quartz.JobExecutionContext;  
    6. import org.quartz.JobExecutionException;  
    7. import org.slf4j.Logger;  
    8. import org.slf4j.LoggerFactory;  
    9.   
    10. public class TestSchedulerTask implements Job{  
    11.     private static Logger logger = LoggerFactory.getLogger(TestSchedulerTask.class);  
    12.   
    13.     public void execute(JobExecutionContext context) throws JobExecutionException {  
    14.         logger.info("**********TestSchedulerTask1 start at={}",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));  
    15.         logger.info("**********I'm Ok!************");  
    16.         logger.info("**********TestSchedulerTask1 end at={}",new DateTime().toString("yyyy-MM-dd HH:mm:ss"));  
    17.     }  
    18.       
    19.     /** 
    20.      * 调度任务工具类测试 
    21.      * 10秒执行一次,无限次数,30秒后开始 
    22.      * @param args 
    23.      */  
    24.     public static void main(String[] args) {  
    25.         System.out.println(SchedulerJobUtils.putPeriodSchedulerJobToDB(TestSchedulerTask.class, "myJob", "myGroup", 10, 0, 30));  
    26.     }  
    27. }  

    数据库里的任务表:


    打印出的日志:
    2016-01-10 00:37:34,810  INFO TestSchedulerTask1:14 - **********TestSchedulerTask1 start at=2016-01-10 00:37:34
    2016-01-10 00:37:34,810  INFO TestSchedulerTask1:15 - **********I'm Ok!************
    2016-01-10 00:37:34,811  INFO TestSchedulerTask1:16 - **********TestSchedulerTask1 end at=2016-01-10 00:37:34

    2016-01-10 00:37:44,690  INFO TestSchedulerTask1:14 - **********TestSchedulerTask1 start at=2016-01-10 00:37:44
    2016-01-10 00:37:44,691  INFO TestSchedulerTask1:15 - **********I'm Ok!************
    2016-01-10 00:37:44,691  INFO TestSchedulerTask1:16 - **********TestSchedulerTask1 end at=2016-01-10 00:37:44

    2016-01-10 00:37:54,697  INFO TestSchedulerTask1:14 - **********TestSchedulerTask1 start at=2016-01-10 00:37:54
    2016-01-10 00:37:54,697  INFO TestSchedulerTask1:15 - **********I'm Ok!************
    2016-01-10 00:37:54,697  INFO TestSchedulerTask1:16 - **********TestSchedulerTask1 end at=2016-01-10 00:37:54

  • 相关阅读:
    19-1 在页面中渲染基本的组件
    19 使用Vue实例的render方法渲染组件
    17 webpack中babel的配置
    前端待复习汇总
    301,302,303,307重定向区别
    尾递归
    Binary-to-text ecoding:
    object Object {} any unknown
    Vue中的model
    全局namespace与模块内的namespace
  • 原文地址:https://www.cnblogs.com/zhangtan/p/7605394.html
Copyright © 2011-2022 走看看