> 參考的優秀文章
> 版本說明
<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...