SpringTask定時任務的使用


  實現定時任務簡單的有四種方式:Timer\ScheduledThreadPool線程池\quartz(常用),還有另一種就是springtask。

  都說springtask上手簡單,於是簡單的研究一下springtask的使用,並且運用到自己的項目中。其也有兩種配置方式,第一種是基於xml配置,第二種是基於注解。

  SprngTask沒有專門的包,其核心類位於spring-context包中。所以引入spring的核心包此功能即可使用。

  在實際的項目中,我們經常將job作為action層,在job中注入service去操作底層的dao,或者定時的向其他系統拉取數據,再或者向其他系統推送數據。

 

1.基於xml配置的簡單的使用

測試類:(每五秒鍾打印一次日志)

package cn.xm.exam.job;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class FirstTestJob {
    private static final Logger log = LoggerFactory.getLogger(FirstTestJob.class);
    private static int count;

    public void cron() {
        log.info("spring task execute times {}", count++);
    }
}

 

xml配置:(非常類似於quartz的cron表達式和linux定時的cron表達式)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    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/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

    <context:component-scan base-package="cn.xm.exam.job"></context:component-scan>

    <task:scheduled-tasks>
        <task:scheduled ref="firstTestJob" method="cron"
            cron="0/5 * * * * ?" />
    </task:scheduled-tasks>

</beans>

 

重點是引入task的schema:

xmlns:task="http://www.springframework.org/schema/task"
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd

結果:

...
2018-11-14 22:35:00 [cn.xm.exam.job.FirstTestJob]-[INFO] spring task execute times 59 2018-11-14 22:35:05 [cn.xm.exam.job.FirstTestJob]-[INFO] spring task execute times 60 2018-11-14 22:35:10 [cn.xm.exam.job.FirstTestJob]-[INFO] spring task execute times 61 2018-11-14 22:35:15 [cn.xm.exam.job.FirstTestJob]-[INFO] spring task execute times 62 2018-11-14 22:35:20 [cn.xm.exam.job.FirstTestJob]-[INFO] spring task execute times 63 2018-11-14 22:35:25 [cn.xm.exam.job.FirstTestJob]-[INFO] spring task execute times 64 ...

 

2.基於注解的使用

首先查看注解的源碼:

注解使用必須在xml中開啟注解任務,使注解生效:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    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/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

    <context:component-scan base-package="cn.xm.exam.job"></context:component-scan>

    <!-- 開啟注解任務 -->
    <task:annotation-driven />

</beans>

 

測試類:(每十秒鍾打印一次日志)

package cn.xm.exam.job;

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

@Component
public class FirstAnnotationJob {
    private static final Logger log = LoggerFactory.getLogger(FirstAnnotationJob.class);
    private static int count;

    @Scheduled(cron = "0/10 * * * * ?")
    public void cron() {
        log.info("spring anno task execute times {}", count++);
    }
}

結果:

2018-11-14 22:44:40 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 0
2018-11-14 22:44:50 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 1
2018-11-14 22:45:00 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 2
2018-11-14 22:45:10 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 3

 

查看@Scheduled的源碼:(位於spring-context包內)

/** <a href="http://www.cpupk.com/decompiler">Eclipse Class Decompiler</a> plugin, Copyright (c) 2017 Chen Chao. */
package org.springframework.scheduling.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scheduled {

    /**
     * A cron-like expression, extending the usual UN*X definition to include
     * triggers on the second as well as minute, hour, day of month, month
     * and day of week.  e.g. {@code "0 * * * * MON-FRI"} means once per minute on
     * weekdays (at the top of the minute - the 0th second).
     * @return an expression that can be parsed to a cron schedule
     * @see org.springframework.scheduling.support.CronSequenceGenerator
     */
    String cron() default "";

    /**
     * Execute the annotated method with a fixed period between the end
     * of the last invocation and the start of the next.
     * @return the delay in milliseconds
     */
    long fixedDelay() default -1;

    /**
     * Execute the annotated method with a fixed period between invocations.
     * @return the period in milliseconds
     */
    long fixedRate() default -1;

    /**
     * Number of milliseconds to delay before the first execution of a
     * {@link #fixedRate()} or {@link #fixedDelay()} task.
     * @return the initial delay in milliseconds
     * @since 3.2
     */
    long initialDelay() default 0;

}

 

參數解釋:(其實源碼的注釋也寫的非常清楚了)

cron:cron表達式

fixedDelay:表示從上一個任務完成開始到下一個任務開始的間隔,單位是毫秒

fixedRate:從上一個任務開始到下一個任務開始的間隔,單位是毫秒。

initialDelay:任務第一次被調用前的延時,單位毫秒。

需要注意的是上面的前三個屬性只能保留一個,不能同時出現,最后一個延時操作可以與上面三個參數搭配。否則會報異常如下:

java.lang.IllegalArgumentException: Exactly one of the 'cron', 'fixedDelay', or 'fixedRate' attributes is required.

 

接下來我們測試上面的參數: 

fixedDelay :方法中模擬處理用了2s
package cn.xm.exam.job;

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

@Component
public class FirstAnnotationJob {
    private static final Logger log = LoggerFactory.getLogger(FirstAnnotationJob.class);
    private static int count;

    @Scheduled(fixedDelay = 10000)
    public void cron() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            log.error("InterruptedException ", e);
        }
        log.info("spring anno task execute times {}", count++);
    }
}

結果:(實際每兩次任務中間相差12s,也就是第一次任務結束10s后開啟下次任務)

2018-11-14 23:02:04 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 1
2018-11-14 23:02:16 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 2
2018-11-14 23:02:28 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 3
2018-11-14 23:02:40 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 4

 

fixedRate測試:

package cn.xm.exam.job;

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

@Component
public class FirstAnnotationJob {
    private static final Logger log = LoggerFactory.getLogger(FirstAnnotationJob.class);
    private static int count;

    @Scheduled(fixedRate = 10000)
    public void cron() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            log.error("InterruptedException ", e);
        }
        log.info("spring anno task execute times {}", count++);
    }
}

結果:(每兩次任務相差10s,也就是本次任務開始之后10s后就開啟下次任務,不管中間處理花費多長時間)

2018-11-14 23:04:47 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 1
2018-11-14 23:04:57 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 2
2018-11-14 23:05:07 [cn.xm.exam.job.FirstAnnotationJob]-[INFO] spring anno task execute times 3

 

至此完成了springtask的測試,確實比quartz簡便的多,使用也簡單。

附一個在線cron表達式生成器:http://cron.qqe2.com/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM