SpringMVC Cron定时器Demo常见问题解决方案

 更新时间:2020年11月23日 08:37:03   作者:剑道子羽  
这篇文章主要介绍了SpringMVC Cron定时器Demo常见问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

该技术的不适用的场景

如果在集群环境下,多台服务器中只希望有一台执行,那 Spring 自带的这种定时器方式可能不太符合你的需要。
但是,如果每台服务器都需要独立执行该定时器任务,且相互之间不存在同步,那么还是可以考虑的

SpringMVC 定时器

本文着重介绍的是 SpringMVC 配置定时器的方式,而不是 SpringBoot 配置定时器的方式。

注解方式

首先,在 Clock 类上添加 @Component,然后,在需要定时执行的方法上面加上 @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秒钟执行一次
  @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">
  <!--配置多个上下文会导致多次执行-->
  <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 配置,你会发现 @Scheduled 注解和 <task:scheduled> 有着相同的属性。因此我们将上一节的代码稍稍改动一下:

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定时任务不生效???

  • 此方法不能有参数
  • 此方法不能有返回值
  • 此类中不能包含其他带任何注解的方法(发现新大陆)

还有一种可能就是没有在 spring-mvc.xml 文件中加入 <task:annotation-driven /> 而不仅仅是加入 <mvc:annotation-driven />

@Scheduled 定时任务执行两次

@Scheduled Spring定时任务每次执行两次解决方案

主要原因是 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 表达式是用来规定代码执行周期的一种表达式,cron表达式详解 这篇文章详细的讲解了 cron 表达式的使用细节。
以我的浅陋的经验,我对 cron 表达式的记忆是:

常用的 cron 表达式由 6 个域组成,域和域之间以空格分开

域从左到右,时间单位从秒开始逐步增大。他们分别是 "秒 分 时 日期 月份 星期"

因为日期和星期会相互影响,通常如果其中一个用 非? 表示任意,则另一个必须用 ? 表示“任意”。

原因:通常,在指定日期条件之后,我们虽然希望“任意星期几”,但是实际上,此时星期需要根据日期的变化而相应变化,做不到完全任意。

你还可以通过 在线 Cron 表达式 来帮助你理解前人代码中的 cron 表达式的含义,或者根据你的需求生成一个新的 cron 表达式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Spring Boot指标监控及日志管理示例详解

    Spring Boot指标监控及日志管理示例详解

    Spring Boot Actuator可以帮助程序员监控和管理SpringBoot应用,比如健康检查、内存使用情况统计、线程使用情况统计等,这篇文章主要介绍了Spring Boot指标监控及日志管理,需要的朋友可以参考下
    2023-11-11
  • Nacos配置的多文件加载与共享配置方式

    Nacos配置的多文件加载与共享配置方式

    这篇文章主要介绍了Nacos配置的多文件加载与共享配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Springboot整合MongoDB的Docker开发教程全解

    Springboot整合MongoDB的Docker开发教程全解

    这篇文章主要介绍了Springboot整合MongoDB的Docker开发,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2020-07-07
  • Java实现多线程轮流打印1-100的数字操作

    Java实现多线程轮流打印1-100的数字操作

    这篇文章主要介绍了Java实现多线程轮流打印1-100的数字操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Spring根据XML配置文件注入属性的方法

    Spring根据XML配置文件注入属性的方法

    下面小编就为大家带来一篇Spring根据XML配置文件注入属性的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • Spring事务失效问题分析及解决方案

    Spring事务失效问题分析及解决方案

    这篇文章主要介绍了Spring事务失效问题分析及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • mybatis判断int是否为空的时候,需要注意的3点

    mybatis判断int是否为空的时候,需要注意的3点

    这篇文章主要介绍了mybatis判断int是否为空的时候,需要注意的3点,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 深入Java Final

    深入Java Final

    本篇文章,小编将为大家介绍Java Final,有需要的朋友可以参考一下
    2013-04-04
  • Java8生成时间方式及格式化时间的方法实例

    Java8生成时间方式及格式化时间的方法实例

    这篇文章主要给大家介绍了关于Java8生成时间方式及格式化时间的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java设计模式之装饰模式详解

    Java设计模式之装饰模式详解

    这篇文章主要介绍了Java设计模式中的装饰者模式,装饰者模式即Decorator Pattern,装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能,装饰模式又名包装模式。装饰器模式以对客户端透明的方式拓展对象的功能,是继承关系的一种替代方案
    2022-07-07

最新评论