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实现,费时费力,扩展性,易用性等也会差很多。


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