spring&quartz的项目应用总结

 

一.名词简介:
       
Quartz是一个完全由java编写的开源作业调度框架。Spring 为创建Quartz的Scheduler、Trigger和JobDetail提供了便利的FactoryBean类,以便能够在 Spring 容器中享受注入的好处。此外Spring还提供了一些便利工具类直接将Spring中的Bean包装成合法的任务。Spring进一步降低了使用 Quartz的难度,能以更具Spring风格的方式使用Quartz。概括来说它提供了两方面的支持:
    1)为Quartz的重要组件类提供更具Bean风格的扩展类;
    2)提供创建Scheduler的BeanFactory类,方便在Spring环境下创建对应的组件对象,并结合Spring容器生命周期进行启动和停止的动作。

二。项目实践

情景一: 集群部署,持久化,动态创建schedule配置
1.spring-schedule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
 <bean id="GMTZone" class="java.util.TimeZone" factory-method="getTimeZone">
        <constructor-arg value="GMT"/>
 </bean>

 <!--业务job生成工厂,该工厂注入了scheduleManager --> 
 <bean id="pharmaskyJobFactory " class="com.infowarelab.pharmasky.service.schedule.PharmaskyJobFactory "/>

 <!--schedule管理器,用于动态添加,修改,删除schedule  --> 
 <bean id="scheduleManager" class="com.infowarelab.pharmasky.service.schedule.ScheduleManager">
        <property name="scheduler" ref="scheduleFactoryBean"/>
 </bean>
 
 <!--持久化,集群schedule工厂配置信息,实际可以在classpath下附加quartz.properties定义这些属性值 -->
 <bean id="scheduleFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="quartzProperties">
         <props>
                <prop key="org.quartz.scheduler.instanceName">PharmaskyClusteredScheduler</prop>
                <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                <prop key="org.quartz.threadPool.threadCount">25</prop>
                <prop key="org.quartz.threadPool.threadPriority">5</prop>
                <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
                <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
                <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
                <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
                <prop key="org.quartz.jobStore.isClustered">true</prop>
                <prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
         </props>
        </property>
        <property name="triggers">
                 <list>
                         <ref local="orderConversionCronTrigger"/>
                 </list>
         </property>
 </bean>
 
  <!--固定jobDetail, org.quartz.JobDetail类型的JobDetail必须实现指定接口方法来执行job-->
 <bean id="autoOrderStatusConversionJob" class="org.quartz.JobDetail ">
        <property name="jobClass">
                  <value>com.infowarelab.pharmasky.service.schedule.job.HisAutoOrderConversionJob</value>
        </property>
        <property name="name" value="PMS-SYS-JOB-HIS-ORDER-CONVERSION"/>
        <property name="group" value="PMS-GROUP"/>
        <property name="requestsRecovery" value="true"/>
 </bean>
 
 <!--job触发器,绑定上面的jobDetail --> 
 <bean id="orderConversionCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
         <property name="beanName" value="PMS-SYS-JOB-HIS-ORDER-CONVERSION-Trigger"/>
         <property name="jobDetail" ref="autoOrderStatusConversionJob" />
         <property name="cronExpression" value="0 0/20 * * * ?" />
         <property name="timeZone" ref="GMTZone"/>
  </bean>
</beans>
2.ScheduleManager.java动态管理schedule工具类


package  com.infowarelab.pharmasky.service.schedule;

import  java.text.ParseException;
import  java.util.ArrayList;
import  java.util.Date;
import  java.util.List;

import  org.apache.commons.lang.StringUtils;
import  org.quartz.CronTrigger;
import  org.quartz.JobDetail;
import  org.quartz.Scheduler;
import  org.quartz.SchedulerException;
import  org.quartz.Trigger;

import  com.infowarelab.common.log.Log;
import  com.infowarelab.common.log.LogFactory;
import  com.infowarelab.pharmasky.util.Config;


public   class  ScheduleManager  {

    
private   static   final  Log log  =  LogFactory.getLog(ScheduleManager. class );

    
private  Scheduler scheduler;

    
public   void  start()  throws  SchedulerException  {
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        
if  (scheduler.isShutdown()  ||  scheduler.isInStandbyMode())  {
            scheduler.start();
        }

    }


    
public   void  pause()  throws  SchedulerException  {
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        
if  (scheduler.isStarted())  {
            scheduler.standby();
        }

    }


    
public   void  stop()  throws  SchedulerException  {
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        
if  (scheduler.isStarted()  ||  scheduler.isInStandbyMode())  {
            scheduler.shutdown();
        }

    }


    
public  List listJobDetails()  throws  SchedulerException  {
        List rstList 
=   new  ArrayList < JobDetail > ();
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        String[] groupNames 
=  scheduler.getJobGroupNames();
        log.info(
" [INFO] the groups in current scheduler is :  "
                
+  groupNames.length);
        
for  ( int  i  =   0 ; i  <  groupNames.length; i ++ {
            String[] jobNames 
=  scheduler.getJobNames(groupNames[i]);
            
for  ( int  j  =   0 ; j  <  jobNames.length; j ++ {
                JobDetail jobDetail 
=  scheduler.getJobDetail(jobNames[j],
                        groupNames[i]);
                
if  (jobDetail  !=   null {
                    rstList.add(jobDetail);
                }

            }

        }

        
return  rstList;
    }


    
public  JobDetail getJobDetail(String jobName, String jobGroupName)
            
throws  SchedulerException  {
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        JobDetail job 
=  scheduler.getJobDetail(jobName, jobGroupName);

        
if  (job  ==   null {
            log.info(
" [INFO]none object relative the jobName :  "   +  jobName
                    
+   "  and jobGroupName :  "   +  jobGroupName);
        }

        
return  job;
    }


    
public  List < JobDetail >  getJobDetailByGroup(String jobGroupName)
            
throws  SchedulerException  {
        List
< JobDetail >  list  =   new  ArrayList < JobDetail > ();
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        String[] jobNames 
=  scheduler.getJobNames(jobGroupName);

        log.debug(
" [DEBUG] jobNames with / ""  + jobGroupName
                 +   " / "  as groupName :  "  + jobNames);

        
for  ( int  i  =   0 ; i  <  jobNames.length; i ++ {
            JobDetail jobDetail 
=  getJobDetail(jobNames[i], jobGroupName);
            
if  (jobDetail  !=   null {
                list.add(jobDetail);
            }
  else   {
                log
                        .debug(
" [DEBUG] JobDetail with {/ ""
                                 +  jobNames[i]
                                
+   " / "  , / ""
                                
+  jobGroupName
                                
+   " / " }
 as the jobName and jobGroupName can not be found  ! " );
            }

        }

        
return  list;
    }


    
public   boolean  addJobDetail(JobDetail jobDetail, String cronExpress)
            
throws  SchedulerException, ParseException  {
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        
if  (jobDetail  !=   null   &&  cronExpress  !=   null {

            Trigger trigger 
=   new  CronTrigger(jobDetail.getName(), jobDetail.getGroup(),
                    jobDetail.getName(), jobDetail.getGroup(), cronExpress);

            Date jobDate 
=  scheduler.scheduleJob(jobDetail, trigger);
            log
                    .info(
" [INFO]jobDetail :  "
                            
+  jobDetail.getFullName()
                            
+   "  has been added into the scheduler , and the firstFiredTime is :  "
                            
+  jobDate);
            
return  (jobDate  ==   null ?   false  :  true ;
        }
  else   {
            log
                    .info(
" [INFO]add jobDetail failure, the parameters on jobDetail or trigger has null value ! " );
        }

        
return   false ;
    }


    
public  Trigger[] getJobTrigger(String jobName, String jobGroupName)
            
throws  SchedulerException  {
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        
return  scheduler.getTriggersOfJob(jobName, jobGroupName);
    }


    
public  List < Trigger >  listTrigger()  throws  SchedulerException  {
        List
< Trigger >  triggerList  =   new  ArrayList < Trigger > ();
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }

        String[] triggerGroupNames 
=  scheduler.getTriggerGroupNames();
        log
                .info(
" [INFO] the trigger groups amounts which is registed within the system is :  "
                        
+  triggerGroupNames.length);
        
for  (String triggerGroupName : triggerGroupNames)  {
            
if  (triggerGroupName  !=   null {
                String[] triggerNames 
=  scheduler
                        .getTriggerNames(triggerGroupName);
                
for  (String triggerName : triggerNames)  {
                    Trigger trigger 
=  scheduler.getTrigger(triggerName,
                            triggerGroupName);
                    
if  (trigger  !=   null
                            
&&  scheduler.getTriggerState(triggerName,
                                    triggerGroupName) 
==  Trigger.STATE_NORMAL)  {
                        triggerList.add(trigger);
                    }
  else   {
                        log.info(
" [INFO] the trigger :  "
                                
+  ((trigger  ==   null ?  trigger.getFullName()
                                        : 
"  null " +   " , not exists  "
                                
+   " or has the not normal status " );
                    }

                }

            }

        }

        
return  triggerList;
    }


    
public   boolean  reScheduleJob(String jobName, String jobGroupName,
            String computedStr) 
throws  SchedulerException, ParseException  {
        
if  (scheduler  ==   null {
            scheduler 
=  getScheduler();
        }


        Trigger newTrigger 
=   new  CronTrigger(jobName, jobGroupName, jobName,
                jobGroupName, computedStr);

        newTrigger.setJobName(jobName);
        newTrigger.setJobGroup(jobGroupName);


        Date triggerDate 
=  scheduler.rescheduleJob(jobName, jobGroupName, newTrigger);
        log.info(
" [INFO] the job  "   +  jobName
                
+   "  has been update to fired on :  "   +  triggerDate);

        
return  (triggerDate  ==   null ?   false  :  true ;
    }


    
public  String genScheduleTimeStr( byte  type, Short  scheduleTimeParams)  {
        String pattern 
=   null //  variable for cron express
         switch  (type)  {
        
case   1 :
            
//  auto order creation job , the parameter turn is : weekInterval ,
            
//  weekday, hour, minute
            
//  "0 minute hour ? * weekDay/weekInterval"
            pattern  =  Config
                    .getString(
" schedule.cron.express.his.order.creation " );
            log.info(
" [INFO] parttern for his order creation cron express :  "
                    
+  pattern);
            
for  ( int  i  =   0 ; i  <  scheduleTimeParams.length; i ++ {
                
switch  (i)  {
                
case   0 //  minute
                    pattern  =  StringUtils.replace(pattern,  " minute " ,
                            scheduleTimeParams[
0 ].toString());
                    
break ;
                
case   1 //  hour
                    pattern  =  StringUtils.replace(pattern,  " hour " ,
                            scheduleTimeParams[
1 ].toString());
                    
break ;
                
case   2 //  weekDay
                    pattern  =  StringUtils.replace(pattern,  " weekDay " ,
                            getWeekIdentify(scheduleTimeParams[
2 ]));
                    
break ;
                
case   3 //  weekInterval
                    pattern  =  StringUtils.replace(pattern,  " weekInterval " ,
                            scheduleTimeParams[
3 ].toString());
                    
break ;
                
default :
                    
break ;
                }

            }

            
break ;

        
case   2 :
            
//  his stock sync job , the parameter turn is : dayInterval, hour,
            
//  minute
            
//  "0 minute hour */dayInterval * ?"
            pattern  =  Config.getString( " schedule.cron.express.his.stock.sync " );
            log.info(
" [INFO] parttern for his order creation cron express :  "
                    
+  pattern);
            
for  ( int  i  =   0 ; i  <  scheduleTimeParams.length; i ++ {
                
switch  (i)  {
                
case   0 //  minute
                    pattern  =  StringUtils.replace(pattern,  " minute " ,
                            scheduleTimeParams[
0 ].toString());
                    
break ;
                
case   1 //  hour
                    pattern  =  StringUtils.replace(pattern,  " hour " ,
                            scheduleTimeParams[
1 ].toString());
                    
break ;
                
case   2 //  dayInterval
                    pattern  =  StringUtils.replace(pattern,  " dayInterval " ,
                            scheduleTimeParams[
2 ].toString());
                    
break ;
                
default :
                    
break ;
                }

            }

            
break ;

        
default :
            
break ;
        }


        log.info(
" [INFO] schedule job cron express is :  "   +  pattern);
        
return  (pattern  ==   null ?   null  : pattern.trim();
    }


    
/**  **********************************************************************  */
    
/**  helper method or getters and setters *  */
    
/**  **********************************************************************  */

    
/**
     * get the week day's identify like "SUN","MON" and so on. In this method
     * the data "1" equals "SUN", so the "7" equals "SAT";
     * 
     * 
@param  short
     *            the numeric data for week day
     * 
@return  String the week day identify with correct numeric data
     
*/

    
private  String getWeekIdentify( short  weekDay)  {
        String value 
=   null ;
        
switch  (weekDay)  {
        
case   1 :
            value 
=   " SUN " ;
            
break ;
        
case   2 :
            value 
=   " MON " ;
            
break ;
        
case   3 :
            value 
=   " TUE " ;
            
break ;
        
case   4 :
            value 
=   " WED " ;
            
break ;
        
case   5 :
            value 
=   " THU " ;
            
break ;
        
case   6 :
            value 
=   " FRI " ;
            
break ;
        
case   7 :
            value 
=   " SAT " ;
            
break ;
        
default :
            
break ;
        }

        
return  value;
    }


    
public  Scheduler getScheduler()  {
        
return  scheduler;
    }


    
public   void  setScheduler(Scheduler scheduler)  {
        
this .scheduler  =  scheduler;
    }

}

 

情景二:单机部署,固定触发规则多个schedule,不用持久化
1.spring-schedule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
 <!-- Job Bean -->
 <bean name="autoOrderAuditService" class="com.infowarelab.sam.service.job.AutoOrderAuditService"></bean>
 <bean name="sendAuditedOrderService" class="com.infowarelab.sam.service.job.SendAuditedOrderService"></bean>
 
 <!-- Job由于以上job bean具有相同的触发规则,所以统一集中在这个管理器执行-->
 <bean id="timerJobManagerJob"  class="com.infowarelab.sam.service.job.SamJobManager"  autowire="no">
       <property name="tasks">
             <list>
                    <ref bean="autoOrderAuditService"/>
                    <ref bean="sendAuditedOrderService"/>
              </list>
        </property>
         <property name="samBaseInfoService" ref="samBaseInfoService"></property>
 </bean>

 <bean id="timerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean " autowire="no">
        <property name="targetObject" ref="timerJobManagerJob" />
        <property name="targetMethod" value="jobExpires" />
 </bean>

 <bean id="timerCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" autowire="no">
        <property name="jobDetail" ref="timerJobDetail" />
        <property name="cronExpression">
               <value>0 0/15 * * * ?</value>
        </property>
 </bean>

 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">
        <property name="triggers">
              <list>
                <ref bean="timerCronTrigger" />
              </list>
        </property>
 </bean>
</beans>

 

 参考资料:
cronExpression表达式:
http://hi.baidu.com/the_space_of_programmer/blog/item/725759f78d383e27720eec80.html  (cronExpression
quartz介绍:
http://hi.baidu.com/alliance_alex/blog/item/5c998d64241173f2f73654b0.html
集群及quartz配置说明:
http://hi.baidu.com/jiangyou001/blog/item/5196d990862d5789a977a4af.html
http://gocom.primeton.com/modules/newbb/forumtopic19180_9963_40.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值