zoukankan      html  css  js  c++  java
  • Spring3.0.6定时任务task:scheduled

    项目使用的spring版本比较旧是3.0.6版本,由于需要进行定时任务,就决定使用Spring自带的scheduled task。

    在网上找了很多文章,也查看了Spring3.0.6的官方文档,按照网上和文档所说,可以使用注解或者配置两种方法之一都行,但是我发现单独使用两种方法都不行,怎么配置任务都无法运行。

    最后看到一篇文章说两种方法同时用,才成功执行定时任务,可能是个Bug,我试了下,同时使用注解和XML配置后,任务确实成功执行了。

    XML配置中,只需要配置一个方法即可,其他方法也能跟着运行了,而且XML中配置的定时时间会被注解覆盖掉,只能先这么做了,期待高手解答原因。

    难道真的是Spring3.0.6的Bug??

    Spring配置如下:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    3.        xmlns:jee="http://www.springframework.org/schema/jee"  
    4.        xmlns:tx="http://www.springframework.org/schema/tx"  
    5.        xmlns:context="http://www.springframework.org/schema/context"  
    6.        xmlns:aop="http://www.springframework.org/schema/aop"  
    7.        xmlns:task="http://www.springframework.org/schema/task"  
    8.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
    9.        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
    10.        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd  
    11.        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  
    12.        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
    13.        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"  
    14.        default-lazy-init="true" default-autowire="byName">  
    15.   
    16.     <!-- 配置注解扫描 -->  
    17.     <context:annotation-config />  
    18.   
    19.     <!-- 自动扫描的包名 -->  
    20.     <context:component-scan base-package="com.demo" />  
    21.   
    22.     <!-- Spring定时器注解开关-->  
    23.     <task:annotation-driven />  
    24.     <!-- 此处对于定时时间的配置会被注解中的时间配置覆盖,因此,以注解配置为准 -->  
    25.     <task:scheduled-tasks scheduler="myScheduler">  
    26.         <task:scheduled ref="scheduledTaskManager" method="autoCardCalculate" cron="1/5 * * * * *"/>  
    27.     </task:scheduled-tasks>  
    28.     <task:scheduler id="myScheduler" pool-size="10"/>  
    29.   
    30.     <aop:aspectj-autoproxy />  
    31.   
    32.     <!-- 加载配置文件 -->  
    33.     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    34.         <property name="locations">  
    35.             <list>  
    36.                 <value>classpath:config.properties</value>  
    37.             </list>  
    38.         </property>  
    39.     </bean>  
    40. </beans>  

    执行任务的POJO类如下:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. package com.demo.schedule;  
    2.   
    3. import org.apache.log4j.Logger;  
    4. import org.springframework.beans.factory.annotation.Autowired;  
    5. import org.springframework.scheduling.annotation.Scheduled;  
    6. import org.springframework.stereotype.Component;  
    7. import java.util.Date;  
    8. /** 
    9.  * Created with IntelliJ IDEA. 
    10.  * Author:  
    11.  * Date: 2013-10-09 14:39 
    12.  * Function: Spring定时任务管理 
    13.  */  
    14. @Component("scheduledTaskManager")  
    15. public class ScheduledTaskManager {  
    16.     /** 
    17.      * cron表达式:* * * * * *(共6位,使用空格隔开,具体如下) 
    18.      * cron表达式:*(秒0-59) *(分钟0-59) *(小时0-23) *(日期1-31) *(月份1-12或是JAN-DEC) *(星期1-7或是SUN-SAT) 
    19.      */  
    20.   
    21.     /** 
    22.      * 定时卡点计算。每天凌晨 02:00 执行一次 
    23.      */  
    24.     @Scheduled(cron = "0 0 2 * * *")  
    25.     public void autoCardCalculate() {  
    26.         System.out.println("定时卡点计算... " + new Date());  
    27.     }  
    28. }  


    对于这个问题,期待高手解答,也希望大家能一起讨论下。

    替换成Sping3.2.2之后,就可以直接在XML中配置,而不需要在方法上使用注解配置时间了。

    感谢4楼,5楼解答

    问题在于Spring全局配置:default-lazy-init="true"
    加上这一句启动的时候还怎么初始化,如果不想改这个配置,那在bean上加个注解
    @Component("scheduledTaskManager") 
    @Lazy(value="false")
    public class ScheduledTaskManager { 
      //TODO 
    }

                               来源:http://blog.csdn.net/zht666/article/details/12518711

    //---------------------------------------------------------

    【Spring】Spring的定时任务

     

    > 参考的优秀文章

    Task Execution and Scheduling

    > 版本说明

    复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.2.14.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.webflow</groupId>
            <artifactId>spring-webflow</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.0</version>
        </dependency>
    </dependencies>
    复制代码

    > 搭建最简单的Spring定时任务工程

    Spring定时任务,给人的第一感觉就是简洁(>_<)

    所需要的JAR,参考以上“版本说明”的POM文件,当然,不嫌麻烦,也可以一个个去下载。

    把Spring通过web.xml注册进来

    复制代码
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/spring.xml</param-value>
    </context-param>
    
    <listener>
        <description>Spring Context</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    复制代码

    当然,需要告诉Spring去哪儿扫描组件。对了,也要告诉Spring我们是使用注解方式注册任务的

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:task="http://www.springframework.org/schema/task"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
               http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
               http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
    
        <context:component-scan base-package="com.nicchagil.*"/>
        <task:annotation-driven/>
        
    </beans>
    复制代码

    附logback的配置

    复制代码
    <configuration>
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder 
                by default -->
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <appender name="FILE" class="ch.qos.logback.core.FileAppender">
            <file>D:/logs/application.log</file>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
                </pattern>
            </encoder>
        </appender>
    
        <root level="debug">
            <appender-ref ref="STDOUT" />
            <appender-ref ref="FILE" />
        </root>
    </configuration>
    复制代码

    好了,注册一个简单的任务,它每逢0秒执行,打印一个语句

    复制代码
    package com.nicchagil.springtask;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;

    @Component
    public class MyFirstSpringJob {
        
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
        
        @Scheduled(cron = "0 * * * * ?")
        public void run() {
            logger.info("MyFirstSpringJob trigger...");
        }

    }
    复制代码

    如无意外,启动项目后,可见日志大致如下

    22:42:00.024 [pool-1-thread-1] INFO  c.n.springtask.MyFirstSpringJob - MyFirstSpringJob trigger...
    22:43:00.002 [pool-1-thread-1] INFO  c.n.springtask.MyFirstSpringJob - MyFirstSpringJob trigger...

    > 如果你同时执行多个任务,且某些任务耗时较长,要配线程池哦(>_<)

    如题。比如,你设置了12:00触发A任务、12:05触发B任务,如果A任务需耗时10分钟,并且没设置线程池,那么B任务有可能会被推迟到12:10以后再执行哦。

    所以,这些情况,我们需设置线程池

    <task:annotation-driven scheduler="myScheduler"/>
    <task:scheduler id="myScheduler" pool-size="20"/>

    :具体池的大小,视项目情况而定

    将任务改为如下测试

    第一个任务

    复制代码
    package com.nicchagil.springtask;
    
    import java.util.concurrent.TimeUnit;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyFirstSpringJob {
        
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
        
        @Scheduled(cron = "0 * * * * ?")
        public void run() {
            logger.info("MyFirstSpringJob trigger...");
            
            /* 模拟此Job需耗时5秒 */
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    复制代码

    第二个任务

    复制代码
    package com.nicchagil.springtask;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MySecondSpringJob {
        
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
        
        @Scheduled(cron = "3 * * * * ?")
        public void run() {
            logger.info("MySecondSpringJob trigger...");
        }
    
    }
    复制代码

    由日志可以看出,第一个任务由一个线程执行;而第二个任务启动时,由于第一个任务还未完成,则由另外一个线程执行

    22:49:00.023 [myScheduler-1] INFO  c.n.springtask.MyFirstSpringJob - MyFirstSpringJob trigger...
    22:49:03.002 [myScheduler-2] INFO  c.n.springtask.MySecondSpringJob - MySecondSpringJob trigger...
    作者:Nick Huang 博客:http://www.cnblogs.com/nick-huang/ 本博客为学习、笔记之用,以笔记形式记录学习的知识与感悟。学习过程中可能参考各种资料,如觉文中表述过分引用,请务必告知,以便迅速处理。如有错漏,不吝赐教。
     
     
    来源:http://www.cnblogs.com/nick-huang/p/4864737.html
     
     
     
    ==================
    ==================
    ==================
     定时任务的方法不能有参数。
  • 相关阅读:
    Hibernate与JPA的区别是什么
    11 吐司 Toast 代码案例
    万众瞩目之下,ANGULAR 2终于正式发布啦!
    Sencha EXTJS6的 Eclipse 插件安装指南
    安卓6.0新特性在Fragment申请运行时权限
    NDK环境配置
    18 UI美化之level(等级显示显示)
    ABAP SY-SUBRC 使用过程中返回值的几种含义
    SAP中给当前指定的活动用户发系统信息的函数
    SAP中的Currency Converting Factor
  • 原文地址:https://www.cnblogs.com/kongxc/p/6858706.html
Copyright © 2011-2022 走看看