SpringMVC Cron定時器Demo常見問題解決方案
該技術的不適用的場景
如果在集群環(huán)境下,多臺服務器中只希望有一臺執(zhí)行,那 Spring 自帶的這種定時器方式可能不太符合你的需要。
但是,如果每臺服務器都需要獨立執(zhí)行該定時器任務,且相互之間不存在同步,那么還是可以考慮的
SpringMVC 定時器
本文著重介紹的是 SpringMVC 配置定時器的方式,而不是 SpringBoot 配置定時器的方式。
注解方式
首先,在 Clock 類上添加 @Component,然后,在需要定時執(zhí)行的方法上面加上 @Scheduled,最后指定 cron 表達式。
項目結構:

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.*" />
<!-- 定時任務支持注解 -->
<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">
<!--配置多個上下文會導致多次執(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 方式設置定時器-->
<task:scheduled-tasks>
<task:scheduled ref="clock" method="testTime" cron="*/5 * * * * ?"/>
</task:scheduled-tasks>
</beans>
常見問題
@Scheduled 定時任務不生效
@Scheduled定時任務不生效???
- 此方法不能有參數(shù)
- 此方法不能有返回值
- 此類中不能包含其他帶任何注解的方法(發(fā)現(xiàn)新大陸)
還有一種可能就是沒有在 spring-mvc.xml 文件中加入 <task:annotation-driven /> 而不僅僅是加入 <mvc:annotation-driven />
@Scheduled 定時任務執(zhí)行兩次
@Scheduled Spring定時任務每次執(zhí)行兩次解決方案
主要原因是 web.xml 同時設置了 <context-param> 和 <init-param> 都設置了 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 表達式
cron 表達式是用來規(guī)定代碼執(zhí)行周期的一種表達式,cron表達式詳解 這篇文章詳細的講解了 cron 表達式的使用細節(jié)。
以我的淺陋的經(jīng)驗,我對 cron 表達式的記憶是:
常用的 cron 表達式由 6 個域組成,域和域之間以空格分開
域從左到右,時間單位從秒開始逐步增大。他們分別是 "秒 分 時 日期 月份 星期"
因為日期和星期會相互影響,通常如果其中一個用 非? 表示任意,則另一個必須用 ? 表示“任意”。
原因:通常,在指定日期條件之后,我們雖然希望“任意星期幾”,但是實際上,此時星期需要根據(jù)日期的變化而相應變化,做不到完全任意。
你還可以通過 在線 Cron 表達式 來幫助你理解前人代碼中的 cron 表達式的含義,或者根據(jù)你的需求生成一個新的 cron 表達式。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Java?3年面試經(jīng)驗告訴你Mybatis是如何進行分頁的
這篇文章主要介紹了Java?3年面試經(jīng)驗告訴你Mybatis是如何進行分頁的,對于任何ORM框架,分頁的實現(xiàn)邏輯無外乎兩種,不管怎么包裝,最終給到開發(fā)者的,只是使用上的差異而已,本文給大家講解的很明白,感興趣的朋友一起看看吧2022-09-09
使用Java構造和解析Json數(shù)據(jù)的兩種方法(詳解二)
這篇文章主要介紹了使用Java構造和解析Json數(shù)據(jù)的兩種方法(詳解二)的相關資料,需要的朋友可以參考下2016-03-03
java學生管理系統(tǒng)界面簡單實現(xiàn)(全)
這篇文章主要為大家詳細介紹了java學生管理系統(tǒng)界面的簡單實現(xiàn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
Spring Boot + thymeleaf 實現(xiàn)文件上傳下載功能
最近同事問我有沒有有關于技術的電子書,我打開電腦上的小書庫,但是郵件發(fā)給他太大了,公司又禁止用文件夾共享,于是花半天時間寫了個小的文件上傳程序,部署在自己的Linux機器上,需要的朋友可以參考下2018-01-01

