spring 定時操作

Java代碼 
  1. public class DoJob{  
  2.   //...  
  3.   public void execute(){...}  
  4. }  


配置也很簡單 

Java代碼 
  1. <bean id="doJobDetail(對應類起個名)"           class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
  2. <property name="targetObject">  
  3.         <ref bean="doJobBean(DoJob對應配置的bean)"/>  
  4.         </property>  
  5.         <property name="targetMethod">  
  6.         <value>executeUpdate</value>  
  7.         </property>  
  8. </bean>  
  9. <bean id="doJobCronTrigger(觸發器)"     class="org.springframework.scheduling.quartz.CronTriggerBean">  
  10.     <property name="jobDetail">  
  11.         <ref bean="doJobDetail(對應上面的bean)" />  
  12.     </property>  
  13.     <property name="cronExpression">  
  14.         <value>0 5 0 * * ?</value> //數字分別對應秒、分、時、日、月、星期、年(可選)  
  15.     </property>  
  16. </bean>  
  17.           
  18. <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  19.     <property name="triggers">  
  20.         <list>  
  21.             <ref local="voteCronTrigger" />  
  22.             <ref local="updateLotteryCronTrigger" />  
  23.         </list>  
  24.   
  25.     </property>  
  26. </bean> 



















spring定時器用Annotation實現

 

由於項目中需要定時更新一些數據,所以用到了spring的定時器,在使用Quartz過程中,遇到了一些麻煩,最終牽扯的錯誤太多:

1、我的一個Service類中需要加入定時執行即Service extends QuartzJobBean,但是Service類中使用@Autowired注入了屬性:dao對象

2、在executeInternal方法執行過程中,dao對象一直爲null。

3、嘗試了各種辦法,最終在配置文件中這樣配置(這種配置網上多的是)

使用jobDataAsMap這個屬性

<bean id="quartzClock" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass">
            <value>org.wapgame.service.charts.Service</value>
        </property>
        <property name="jobDataAsMap">
            <map>
                  <entry key="dao" value-ref="Dao"/>
                  <entry key="test" value="30"/>
             </map>
        </property>
 </bean>

4、executeInternal方法中使用其參數來獲得值。

protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
    // TODO Auto-generated method stub
    JobDataMap map=arg0.getMergedJobDataMap();
    int test = Integer.parseInt(map.get("test").toString());
    log.debug("test:"+test);
    playerDao=(PlayerDao)map.get("playerDao");
  }

這樣就解決了注入的對象爲null的問題。網上找了好多找不到解決的辦法,最終還得靠自己。

5、解決是解決了,但是過程中我需要用到事務操作。隨之帶來了很大的麻煩,畢竟項目用的都是Annotaion,再加上自己在ApplicationContext.xml中配置,造成了很多麻煩和異常。

6、放棄,轉Annotation

 


通過 註解 來調度任務 
1、
AnnotationQuartz類:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class AnnotationQuartz {
  @Scheduled(cron="0,10,20,30,40,50 * * * * ?")   //需要注意@Scheduled這個註解,它可配置多個屬性:cron\fixedDelay\fixedRate
  public void test()
  {
    System.out.println("0.0");
  }
}

2、
spring的ApplicationContext.xml中的配置:
只需要加上
<!--  定時器開關  開始-->
    <task:annotation-driven/>
<!--  定時器開關  結束-->


3、(如果是web應用,那麼需要再web.xml中加入)
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

通過 配置文件 來調度任務 
1、
AnnotationQuartz類:
import org.springframework.stereotype.Component;

@Component(如果你的項目使用的是註解而不是配置文件中寫bean,那麼需要加上@Component,確保這個類已經注入)
public class AnnotationQuartz {
  public void test()
  {
    System.out.println("0.0");
  }
}
2、
spring的ApplicationContext.xml中的配置:
<task:scheduled-tasks>  
    <task:scheduled ref="chartsService" method="test" cron="0 0,15,30,45 * * * ?"/>  
</task:scheduled-tasks>

最後請注意 :(ApplicationContext.xml)
a)、需要在xmlns裏面加入:
xmlns:task="http://www.springframework.org/schema/task" 

b)、在xsi:schemaLocation中加入
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd(別忘了最後的引號)

 

 

cron表達式去搜吧,好多,我搜到了一些,如下:

<!--

一個cron表達式有到少6個(也可能是7個)由空格分隔的時間元素.從左到右,這些元素的定義如下:  
              1.秒(0-59)  
              2.分鐘(0-59)  
              3.小時(0-23)  
              4.月份中的是期(1-31)  
              5.月份(1-12或SUN-DEC)  
              6.星期中的日期(1-7或SUN-SAT)  
              7.年份(1970-2099)   
                 例子:  
                  0 0 10,14,16 * * ? 每天上午10點,下午2點和下午4點  
                  0 0,15,30,45 * 1-10 * ? 每月前10天每隔15分鐘  
                  30 0 0 1 1 ? 2012 在2012年1月1日午夜過30秒時  
                  0 0 8-5 ? * MON-FRI 每個工作日的工作時間  
              - 區間  
              * 通配符  
              ? 你不想設置那個字段 

-->















package  com.bankcomm.cache;

 

 import  org.apache.commons.logging.Log;

 import  org.apache.commons.logging.LogFactory;

 import  org.springframework.context.ApplicationContext;

 import  org.springframework.context.support.ClassPathXmlApplicationContext;

 

 import  com.bankcomm.util.ContextUtil;

 

 public   class  QuartzCacheHandler  {

        private   static  ApplicationContext actx;

 

       Log log  =  LogFactory.getLog( this .getClass());

 

        /** 
 
        * 程序載入配置文件<br>

        * Author:pesome<br>

        * Time:2006-12-8 上午10:29:26<br>

         */ 
 
         public   static   void  init()  {

               try   {

                     actx  =   new  ClassPathXmlApplicationContext(

                                    new  String[]  {  " quartzCache*.xml "  } );

              }   catch  (Exception e)  {

                     e.printStackTrace();

                      throw   new  RuntimeException();

              } 
 
       } 
 
 

        private  QuartzCacheHandler()  {

       } 
 
 

        /** 
 
        * 在程序載入配置文件時使用<br>

        * Author:pesome<br>

        * Time:2006-12-8 上午10:28:07<br>

        * 

        *  @param  beanName

        *  @param  key

        *  @return 
 
         */ 
 
         public   static  Object getSe(String beanName, String key)  {

               return  ((QuartzCache) actx.getBean(beanName)).get(key);

       } 
 
 

        /** 
 
        * 在web容器中,初始化時載入配置文件時使用<br>

* Author:pesome<br>

        * Time:2006-12-8 上午10:28:40<br>

        * 

        *  @param  beanName

        *  @param  key

        *  @return 
 
         */ 
 
         public   static  Object get(String beanName, String key)  {

               return  ((QuartzCache) ContextUtil.getBean(beanName)).get(key);

       } 
 

 

 

-----------------------------------QuartzCache-----------------------------------------------

 package  com.bankcomm.cache;

 

 import  java.util.HashMap;

 import  java.util.Map;

 

 import  org.apache.commons.logging.Log;

 import  org.apache.commons.logging.LogFactory;

 

 public   abstract   class  QuartzCache  {

        private  Log log  =  LogFactory.getLog( this .getClass());

 

        protected  Map cacheMap  =   new  HashMap();

 

        /** 
 
        * 抽象方法由具體的cache類實現,一般爲調用put方法<br>

        * Author:pesome<br>

        * Time:2006-12-7 下午05:47:26<br>

         */ 
 
        public   abstract   void  refresh();

 

        public  Object get(String key)  {

               return  cacheMap.get(key);

       } 
 
 

        public   void  put(String key, Object value)  {

              cacheMap.put(key, value);

              log.info( " put to quartz cache key= "   +  key  +   " ,value= "   +  value);

       } 
 

 

---------------------------------------------------------------------------------------------------------

Web.xml 中只需加 2 句:

 

 < context-param > 
         < param-name > contextConfigLocation </ param-name > 
         < param-value > /WEB-INF/applicationContext*.xml </ param-value > 
     </ context-param > 
 
     < listener > 
         < listener-class > 
            com.bankcomm.util.MyContextLoaderListener
         </ listener-class > 
     </ listener > 

 

最後是applicationContext_quartzCache.xml配置文件,就是標準的spring結合quartz的配置文件:

 <? xml version="1.0" encoding="GB2312" ?> 
 
 <! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

                       "http://www.springframework.org/dtd/spring-beans.dtd" > 
 
 < beans > 
 
      < bean

          class ="org.springframework.scheduling.quartz.SchedulerFactoryBean" > 
 
          < property  name ="triggers" > 
 
               < list > 
 
                    < ref  local ="simpleTrigger"   /> 
 
               </ list > 
 
          </ property > 
 
      </ bean > 
 
 

      < bean  id ="methodInvokingJobDetail" 
 
         class ="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" > 
 
          < property  name ="targetObject" > 
 
               < ref  bean ="simpleCache"   /> 
 
          </ property > 
 
          < property  name ="targetMethod" > 
 
               < value > refresh </ value > 
 
          </ property > 
 
      </ bean > 
 
 

      < bean  id ="simpleTrigger" 
 
         class ="org.springframework.scheduling.quartz.SimpleTriggerBean" > 
 
          < property  name ="jobDetail" > 
 
               <!--  see the example of method invoking job above  --> 
 
               < ref  bean ="methodInvokingJobDetail"   /> 
 
          </ property > 
 
          < property  name ="startDelay" > 
 
               < value > 0 </ value > 
 
          </ property > 
 
          <!--  set the refresh interval,millisecond  --> 
 
          < property  name ="repeatInterval" > 
 
               < value > 2000 </ value > 
 
          </ property > 
 
      </ bean > 
 
     

      <!--  custom job beans  --> 
 
     < bean  id ="simpleCache"  class ="com.bankcomm.cache.SimpleCache" ></ bean > 
 
 </ beans > 

 

寫自己的QuartzCache子類並實現refresh方法,然後在配置文件中定義bean和相應的trigger就能方便的實現定時cache了。示例中使用了SimpleTriggerBean ,每2s更新一次。也可以使用CronTriggerBean,每天定時更新。 使用 cache ,只需調用 QuartzCacheHandler 的 get 和 getSe就行, get 是在由 web 容器啓動 quartz 的場合使用, getSe 在使用 init 方法啓動時使用。 Get 中調用了自己寫的一個 ContextUtil ,它包含一個靜態的 applicationContex 的引用,在 spring 容器啓動後由 MyContextLoaderListener (重載 spring 的 ContextLoaderListener )填充。

這些東西也就幾個小時搞定,多虧了spring,quartz這些開源軟件啊。要自己用timer實現,費時費力,擴展性,易用性等也會差很多。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章