spring cron 定时任务

时间:2021-07-27 07:50:42

文章首发于个人博客:https://yeyouluo.github.io

  • 0 预备知识:cron表达式

    见 《5 参考》一节。

    1 环境

    eclipse mars2 + Maven3.3.9

    2 开发步骤

    项目码云地址

    2.1 建立一个maven工程

    POM如下:

    spring cron 定时任务spring cron 定时任务
      1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      2   <modelVersion>4.0.0</modelVersion>
      3   <groupId>com.yeyouluo.spring.timer</groupId>
      4   <artifactId>spring-timer-demo</artifactId>
      5   <version>0.0.1-SNAPSHOT</version>
      6   
      7   <properties>
      8         <spring.version>4.2.6.RELEASE</spring.version>
      9         <slf4j.version>1.7.2</slf4j.version>
     10         <log4j.version>1.2.17</log4j.version>
     11     </properties>
     12     <dependencies>
     13         <dependency>  
     14             <groupId>org.slf4j</groupId>  
     15             <artifactId>slf4j-api</artifactId>  
     16             <version>${slf4j.version}</version>  
     17         </dependency>  
     18         <dependency>  
     19             <groupId>org.slf4j</groupId>  
     20             <artifactId>slf4j-log4j12</artifactId>  
     21             <version>${slf4j.version}</version>  
     22         </dependency>  
     23         <!-- common-logging 实际调用slf4j -->  
     24         <dependency>  
     25             <groupId>org.slf4j</groupId>  
     26             <artifactId>jcl-over-slf4j</artifactId>  
     27             <version>${slf4j.version}</version>  
     28         </dependency>  
     29         <!-- java.util.logging 实际调用slf4j -->  
     30         <dependency>  
     31             <groupId>org.slf4j</groupId>  
     32             <artifactId>jul-to-slf4j</artifactId>  
     33             <version>${slf4j.version}</version>  
     34         </dependency>  
     35         <dependency>  
     36             <groupId>log4j</groupId>  
     37             <artifactId>log4j</artifactId>  
     38             <version>${log4j.version}</version>  
     39         </dependency>  
     40         <dependency>  
     41             <groupId>org.lazyluke</groupId>  
     42             <artifactId>log4jdbc-remix</artifactId>  
     43             <version>0.2.7</version>  
     44         </dependency> 
     45         <!-- spring核心包 -->
     46         <dependency>
     47             <groupId>org.springframework</groupId>
     48             <artifactId>spring-core</artifactId>
     49             <version>${spring.version}</version>
     50         </dependency>
     51         <dependency>
     52             <groupId>org.springframework</groupId>
     53             <artifactId>spring-web</artifactId>
     54             <version>${spring.version}</version>
     55         </dependency>
     56         <dependency>
     57             <groupId>org.springframework</groupId>
     58             <artifactId>spring-tx</artifactId>
     59             <version>${spring.version}</version>
     60         </dependency>
     61         <dependency>
     62             <groupId>org.springframework</groupId>
     63             <artifactId>spring-jdbc</artifactId>
     64             <version>${spring.version}</version>
     65         </dependency>
     66         <dependency>
     67             <groupId>org.springframework</groupId>
     68             <artifactId>spring-webmvc</artifactId>
     69             <version>${spring.version}</version>
     70         </dependency>
     71         <dependency>
     72             <groupId>org.springframework</groupId>
     73             <artifactId>spring-aop</artifactId>
     74             <version>${spring.version}</version>
     75         </dependency>
     76         <dependency>
     77             <groupId>org.springframework</groupId>
     78             <artifactId>spring-beans</artifactId>
     79             <version>${spring.version}</version>
     80         </dependency>
     81         <dependency>
     82             <groupId>org.springframework</groupId>
     83             <artifactId>spring-context</artifactId>
     84             <version>${spring.version}</version>
     85         </dependency>
     86         <dependency>
     87             <groupId>org.springframework</groupId>
     88             <artifactId>spring-context-support</artifactId>
     89             <version>${spring.version}</version>
     90         </dependency>
     91         <dependency>
     92             <groupId>org.springframework</groupId>
     93             <artifactId>spring-expression</artifactId>
     94             <version>${spring.version}</version>
     95         </dependency>
     96         <dependency>
     97               <groupId>org.springframework</groupId>
     98               <artifactId>spring-messaging</artifactId>
     99               <version>${spring.version}</version>
    100         </dependency>
    101         <dependency>
    102              <groupId>org.springframework.integration</groupId>
    103               <artifactId>spring-integration-core</artifactId>
    104               <version>4.2.5.RELEASE</version>
    105         </dependency>
    106         
    107     </dependencies>
    108     
    109     <packaging>jar</packaging>
    110 </project>
    POM.xml

    pom文件中可能加入了很多没有使用的jar,比如和mybatis、druid、mysql-connector相关的jar,以备后用。

    2.2 添加配置文件

    ①log4j.properties

    spring cron 定时任务spring cron 定时任务
     1 log4j.rootLogger=INFO, Console, RollingFile
     2 #Console
     3 log4j.appender.Console=org.apache.log4j.ConsoleAppender
     4 log4j.appender.Console.layout=org.apache.log4j.PatternLayout
     5 log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
     6  
     7 #RollingFile
     8 log4j.appender.RollingFile=org.apache.log4j.DailyRollingFileAppender
     9  
    10 log4j.appender.RollingFile.File=logs/log.log
    11 log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout
    12 log4j.appender.RollingFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
    log4j.xml

    ②spring-base.xml

    spring cron 定时任务spring cron 定时任务
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4 xmlns:task="http://www.springframework.org/schema/task"
     5 xmlns:context="http://www.springframework.org/schema/context"
     6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     7 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
     8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
     9  
    10 <bean id="readDBTask" class="com.yeyouluo.spring.timer.service.ReadDBTask"></bean>
    11  
    12 <task:scheduled-tasks>
    13 <task:scheduled ref="readDBTask" method="doSomething" cron="0/3 * * * * ?"/>
    14 </task:scheduled-tasks>
    15  
    16 </beans>
    spring-base.xml

    注意引入命名空间
    xmlns:task=”http://www.springframework.org/schema/task“ 和
    http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task/spring-task-3.0.xsd

    2.3 创建定时任务ReadDBTask

    spring cron 定时任务spring cron 定时任务
    1 package com.yeyouluo.spring.timer.service;
    2 import org.apache.log4j.Logger;
    3 public class ReadDBTask {
    4     public static Logger log = Logger.getLogger(ReadDBTask.class);
    5     public void doSomething() {
    6         log.info("********");
    7         log.info("定时任务执行。");
    8     }
    9 }
    ReadDBTask.java

    2.4 添加启动函数Main

    spring cron 定时任务spring cron 定时任务
     1 package com.yeyouluo.spring.timer.start;
     2 import org.slf4j.Logger;
     3 import org.slf4j.LoggerFactory;
     4 import org.springframework.context.support.ClassPathXmlApplicationContext;
     5 public class Main {
     6     
     7     public static Logger logger = LoggerFactory.getLogger(Main.class);
     8     public static final String config = "spring-base.xml";
     9     
    10     public static void main(String[] args) {
    11         
    12         ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(config);
    13         logger.info("spring timer started");
    14         if( ctx != null ) {
    15             ctx.start();
    16         }
    17     }
    18 }
    Main.java

    3 流程分析

    在启动函数Main.java右键 –> run as –> Java Application。
    结果为:每3秒在控制台输出如下:
    2017-10-16 15:03:54,885 [main] INFO [com.yeyouluo.spring.timer.start.Main] - spring timer started
    2017-10-16 15:03:57,002 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - **
    2017-10-16 15:03:57,003 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - 定时任务执行。
    2017-10-16 15:04:00,001 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - **
    2017-10-16 15:04:00,001 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - 定时任务执行。
    2017-10-16 15:04:03,001 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - **
    2017-10-16 15:04:03,001 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - 定时任务执行。
    2017-10-16 15:04:06,002 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - **
    2017-10-16 15:04:06,002 [pool-1-thread-1] INFO [com.yeyouluo.spring.timer.service.ReadDBTask] - 定时任务执行。

    • 从入口函数开始,加载spring配置文件spring-base.xml。
    • spring-base.xml定义了 ,指向定时任务类com.yeyouluo.spring.timer.service.ReadDBTask的doSomething方法。
    • 执行doSomething方法中的逻辑。

    4 拓展:打成jar部署到单独的服务器上

    目标:用java命令拉起程序。
    步骤
    ①将依赖jar提取出来,放入D:\timer\lib
    ②maven打包程序,将生成的jar放入D:\timer\lib
    ③在D:\timer\lib下新建一个文件start.cmd,内容如下:
    java -Djava.ext.dirs=D:\timer\lib -Xms1024m -Xmx1024m com.yeyouluo.spring.timer.start.Main
    ④双击start.cmd。
    结果
    spring cron 定时任务

    部署在Linux上是一样的操作,仅仅是替换启动文件类型为.sh,并且内容中的路径改为Linux的路径。
    如果是部署在Linux服务器上,还可以编写如下文件:
    stop.sh
    jps | grep Main | awk '{print $1}' | xargs kill -9
    注:通过kill进程的方式实现,不优雅。尤其要注意还没有其他名称为Main的进程,防止误杀。

    clean-log.sh
    rm -f logs/*

    5 参考