SpringBoot 中实现定时任务的几种方式

这篇具有很好参考价值的文章主要介绍了SpringBoot 中实现定时任务的几种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

定时任务在我们项目开发中也是很重要的,对于某些场景必须要用定时任务 ,如定时发送邮件啊,定时统计数据等,这篇文章主要讲讲项目中实现定时任务的几种方式。

一、基于注解

这种方式很简单,主要就是先@EnableScheduling开启定时任务功能,然后在相应的方法上添加@Scheduled()中间写上相应的cron表达式即可。示例如下:

schedule.ScheduleTask:

java复制代码import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@EnableScheduling //开启定时任务
public class ScheduleTask {
    @Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
    public void testScheduleTask() {
        System.out.println("执行定时任务" + LocalDateTime.now());
    }
}

Cron表达式参数参考:

  • 秒(0~59) 例如0/5表示每5秒
  • 分(0~59)
  • 时(0~23)
  • 日(0~31)的某天,需计算
  • 月(0~11)
  • 周几( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)

建议:直接在线生成Cron表达式比较方便:www.matools.com/cron/

@Scheduled:除了支持灵活的参数表达式cron之外,还支持 fixedDelay,fixedRate,initialDelay 这些延时性的操作。

springboot 定时任务,java,spring boot,java,spring

启动测试就实现了基本的定时任务功能,但是如果我们修改了cron表达式,需要重启整个应用才能生效,不是很方便。想要实现修改cron表达式就生效就需要用到接口的方式来实现定时任务。

二、基于接口

接口的方式是我们把定时任务的信息放在数据库中,程序从数据库去拉取定时任务的信息如cron表达式来实现实时修改生效等功能。

1. 首先在数据库中创建一张用来记录定时任务的表

sql复制代码CREATE TABLE `scheduled` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NULL,
  `cron` varchar(255) NULL,
  PRIMARY KEY (`id`)
)
INSERT INTO `mydb`.`scheduled` (`id`, `name`, `cron`) VALUES (1, '定时任务1', '0/6 * * * * ?')

2. 在项目中引入mabatis-plus和mysql相应的依赖包

xml复制代码<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.5.3.1</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.32</version>
</dependency>

3. 在application.yml中进行连接数据库相应配置

yml复制代码spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?characterEncoding=utf-8&serverTimeZone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

4. 定义查询cron表达式的mapper

mapper.CronMapper:

java复制代码import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface CronMapper {
    @Select("select cron from scheduled where id=#{id}")
    String getCron(Long id);
}

5. 实现定时任务

java复制代码import com.jk.mapper.CronMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

@Component
@EnableScheduling //开启定时任务
public class ScheduleTask implements SchedulingConfigurer {
    @Autowired
    private CronMapper cronMapper;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                //添加任务内容
                () -> process(),
                //设置执行的周期
                triggerContext -> {
                    //查询cron表达式
                    String cron = cronMapper.getCron(1L);
                    if (cron.isEmpty()) {
                        System.out.println("cron is null");
                    }
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                });
    }

    private void process() {
        System.out.println("基于接口的定时任务");
    }
}

这种方式需要去实现SchedulingConfigurer接口并重写configureTasks方法,然后设置任务内容和执行周期等,启动测试就实现了基于接口的定时任务,此时我们改动数据库里的cron表达式也会实时生效

springboot 定时任务,java,spring boot,java,spring

三、多线程定时任务

但上面的方法定义的定时任务会有个问题,就是如果我一个定时任务里面执行了复杂逻辑,导致本身执行花的时间就已经超过了定时任务间隔的时间怎么办呢?这时候定时任务的执行就会出现一定的问题,具体如下,我用线程睡眠的方式模拟处理复杂逻辑

java复制代码import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@EnableScheduling //开启定时任务
public class ScheduleTask {
    @Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
    public void testScheduleTask1() throws InterruptedException {
        System.out.println("执行定时任务1 " + LocalDateTime.now());
        Thread.sleep(10 * 1000);
    }

    @Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
    public void testScheduleTask2() {
        System.out.println("执行定时任务2 " + LocalDateTime.now());
    }
}

springboot 定时任务,java,spring boot,java,spring

可以看到两个任务的执行时间都被影响了,和我们设置的5秒不对应。此时就可以使用多线程定时任务

java复制代码import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
@EnableScheduling //开启定时任务
@EnableAsync //开启多线程
public class ScheduleTask {
    @Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
    @Async
    public void testScheduleTask1() throws InterruptedException {
        System.out.println("执行定时任务1 " + LocalDateTime.now());
        Thread.sleep(10 * 1000);
    }

    @Scheduled(cron = "0/5 * * * * ?") //定时任务注解+cron表达式
    @Async
    public void testScheduleTask2() {
        System.out.println("执行定时任务2 " + LocalDateTime.now());
    }
}

springboot 定时任务,java,spring boot,java,spring

这样多线程的定时任务就实现了,每个定时任务之间不会互相影响,定时任务执行时间太长也不会影响。文章来源地址https://www.toymoban.com/news/detail-775896.html

到了这里,关于SpringBoot 中实现定时任务的几种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot接收参数的几种方式

    传参格式:?号传参,在地址栏上加参数 传参格式:请求体传参 form-data的请求是在body中,为key=value格式,同时可以传文件,Content-Type为multipart/form-data,后端可以用@RequestParam接收。 json传参也是在body当中,只不过json是一种数据格式,后端可以用@RequestBody接收。 地址栏传参,

    2024年02月10日
    浏览(29)
  • springboot接收前端参数的几种方式

    目录 第一种:直接在方法中指定参数 第二种:使用@requesrParam注解 第三种方法:基于@pathVariable  第四种方法:基于@ResquestBody 在开始之前,我们需要一下准备工作,创建数据库,springboot工程,添加依赖,配置文件,使用的技术有mybatisplus,springboot,maven,mysql。 首先,数据库

    2024年02月07日
    浏览(27)
  • SpringBoot实现异步调用的几种方式

    一、使用 CompletableFuture 实现异步任务 CompletableFuture 是 Java 8 新增的一个异步编程工具,它可以方便地实现异步任务。使用 CompletableFuture 需要满足以下条件: 异步任务的返回值类型必须是 CompletableFuture 类型; 在异步任务中使用 CompletableFuture.supplyAsync() 或 CompletableFuture.runAsy

    2024年02月08日
    浏览(35)
  • 【SpringBoot系列】接收前端参数的几种方式

    前言 在现代Web开发中,前后端分离的架构已经成为主流。前端负责展示页面和用户交互,而后端则负责处理业务逻辑和数据存储。在这种架构下,前端需要将用户输入的数据发送给后端进行处理。而Spring Boot作为一种快速开发框架,提供了多种方式来接收前端数据。 本文将介

    2024年02月05日
    浏览(34)
  • 【SpringBoot系列】实现跨域的几种方式

    前言 在Web开发中,跨域是一个常见的问题。由于浏览器的同源策略,一个Web应用程序只能访问与其自身同源(即,相同协议、主机和端口)的资源。 这种策略的存在是为了保护用户的安全,防止恶意网站读取或修改用户的数据。 然而,现代Web应用程序经常需要访问不同源的

    2024年02月01日
    浏览(40)
  • SpringBoot第45讲:SpringBoot定时任务 - Timer实现方式

    定时任务在实际开发中有着广泛的用途,本文是SpringBoot第45讲,主要帮助你构建定时任务的知识体系,同时展示Timer 的schedule和scheduleAtFixedRate例子;后续的文章中我们将逐一介绍其它常见的定时任务,并与SpringBoot的集成。

    2024年02月10日
    浏览(28)
  • 【SpringBoot系列】读取yml文件的几种方式

    前言 在Spring Boot开发中,配置文件是非常重要的一部分,而yml文件作为一种常用的配置文件格式,被广泛应用于Spring Boot项目中。Spring Boot提供了多种方式来读取yml文件中的属性值,开发者可以根据具体的需求和场景选择合适的方式。本文将介绍Spring Boot读取yml文件的主要方式

    2024年02月05日
    浏览(30)
  • SpringBoot 启动项目后执行方法的几种方式

    在项目开发中某些场景必须要用到启动项目后立即执行方式的功能,如我们需要去初始化数据到 redis 缓存、设置策略工厂,或者启动后读取相应的配置等,主要聊聊实现立即执行的几种方法。 这两者的实现方法一样,都是去继承相应的接口然后重写 run 方法即可,也都是 S

    2024年02月11日
    浏览(29)
  • SpringBoot中接收POST参数的几种方式

    今天在做一个vue前后端分离项目的过程中,踩了一个坑,记录一下 前端如下: 用户名字段: username 密码字段: password 提交后,发现后端怎么也收不到参数,总结如下: 常见的接收post参数,有三种 额外参数: 使用 required = false 标注参数是非必须的。 使用 defaultValue 给参数

    2024年02月15日
    浏览(35)
  • SpringBoot第47讲:SpringBoot定时任务 - Netty HashedWheelTimer方式

    timer 和 ScheduledExecutorService 是JDK内置的定时任务方案,而业内还有一个经典的定时任务的设计叫时间轮(Timing Wheel), Netty 内部基于时间轮实现了一个 HashedWheelTimer 来 优化百万量级I/O超时的检测 ,它是一个高性能,低消耗的数据结构,它适用于非准实时,延迟的短平快任务,例

    2024年02月09日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包