SpringMVC Cron定時器Demo常見問題解決方案
該技術(shù)的不適用的場景
如果在集群環(huán)境下,多臺服務(wù)器中只希望有一臺執(zhí)行,那 Spring 自帶的這種定時器方式可能不太符合你的需要。
但是,如果每臺服務(wù)器都需要獨立執(zhí)行該定時器任務(wù),且相互之間不存在同步,那么還是可以考慮的
SpringMVC 定時器
本文著重介紹的是 SpringMVC 配置定時器的方式,而不是 SpringBoot 配置定時器的方式。
注解方式
首先,在 Clock 類上添加 @Component,然后,在需要定時執(zhí)行的方法上面加上 @Scheduled,最后指定 cron 表達(dá)式。
項目結(jié)構(gòu):
Clock.java
package coderead.spring.scheduled; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.Date; @Component public class Clock { // 每5秒鐘執(zhí)行一次 @Scheduled(cron = "*/5 * * * * ?") public void testTime() { System.out.println(new Date()); } }
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <mvc:annotation-driven /> <context:component-scan base-package="coderead.spring.*" /> <!-- 定時任務(wù)支持注解 --> <task:annotation-driven /> </beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--配置多個上下文會導(dǎo)致多次執(zhí)行--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mvc.xml</param-value> </context-param> <!-- ================================== listener ================================== --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- ================================== servlet ================================== --> <!-- 前端控制器 --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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"> <modelVersion>4.0.0</modelVersion> <groupId>coderead.spring</groupId> <artifactId>spring-scheduled-test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <spring.version>5.1.6.RELEASE</spring.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.33.v20201020</version> </plugin> </plugins> </build> </project>
如果你不知道怎么用 jetty 啟動項目,你可以考慮參考 使用maven-Jetty9-plugin插件運行第一個Servlet
xml 配置方式
如果你需要使用 xml 配置,你會發(fā)現(xiàn) @Scheduled 注解和 <task:scheduled> 有著相同的屬性。因此我們將上一節(jié)的代碼稍稍改動一下:
Clock.java 去掉注解
package coderead.spring.scheduled; import java.util.Date; public class Clock { public void testTime() { System.out.println(new Date()); } }
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <mvc:annotation-driven /> <context:component-scan base-package="coderead.spring.*" /> <!--用 xml 方式注入 Clock Bean--> <bean id="clock" class="coderead.spring.scheduled.Clock" /> <!--用 xml 方式設(shè)置定時器--> <task:scheduled-tasks> <task:scheduled ref="clock" method="testTime" cron="*/5 * * * * ?"/> </task:scheduled-tasks> </beans>
常見問題
@Scheduled 定時任務(wù)不生效
@Scheduled定時任務(wù)不生效???
- 此方法不能有參數(shù)
- 此方法不能有返回值
- 此類中不能包含其他帶任何注解的方法(發(fā)現(xiàn)新大陸)
還有一種可能就是沒有在 spring-mvc.xml 文件中加入 <task:annotation-driven /> 而不僅僅是加入 <mvc:annotation-driven />
@Scheduled 定時任務(wù)執(zhí)行兩次
@Scheduled Spring定時任務(wù)每次執(zhí)行兩次解決方案
主要原因是 web.xml 同時設(shè)置了 <context-param> 和 <init-param> 都設(shè)置了 contextConfigLocation,兩次加載配置文件
<web-app ....> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mvc.xml</param-value> </context-param> ... <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> ... </web-app>
cron 表達(dá)式
cron 表達(dá)式是用來規(guī)定代碼執(zhí)行周期的一種表達(dá)式,cron表達(dá)式詳解 這篇文章詳細(xì)的講解了 cron 表達(dá)式的使用細(xì)節(jié)。
以我的淺陋的經(jīng)驗,我對 cron 表達(dá)式的記憶是:
常用的 cron 表達(dá)式由 6 個域組成,域和域之間以空格分開
域從左到右,時間單位從秒開始逐步增大。他們分別是 "秒 分 時 日期 月份 星期"
因為日期和星期會相互影響,通常如果其中一個用 非? 表示任意,則另一個必須用 ? 表示“任意”。
原因:通常,在指定日期條件之后,我們雖然希望“任意星期幾”,但是實際上,此時星期需要根據(jù)日期的變化而相應(yīng)變化,做不到完全任意。
你還可以通過 在線 Cron 表達(dá)式 來幫助你理解前人代碼中的 cron 表達(dá)式的含義,或者根據(jù)你的需求生成一個新的 cron 表達(dá)式。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java?SSM實現(xiàn)前后端協(xié)議聯(lián)調(diào)詳解下篇
首先我們已經(jīng)知道,在現(xiàn)在流行的“前后端完全分離”架構(gòu)中,前后端聯(lián)調(diào)是一個不可能避免的問題,這篇文章主要介紹了Java?SSM實現(xiàn)前后端協(xié)議聯(lián)調(diào)過程2022-08-08詳解JDK自帶javap命令反編譯class文件和Jad反編譯class文件(推薦使用jad)
這篇文章主要介紹了JDK自帶javap命令反編譯class文件和Jad反編譯class文件(推薦使用jad),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09SpringBoot應(yīng)用War包形式部署到外部Tomcat的方法
這篇文章主要介紹了SpringBoot應(yīng)用War包形式部署到外部Tomcat的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08