百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

SpringBoot扩展——定时任务!(基于springboot的校园宿舍管理系统的设计与实现)

ccwgpt 2025-07-27 19:14 1 浏览 0 评论

定时任务

项目开发中会涉及很多需要定时执行的代码,如每日凌晨对前一日的数据进行汇总,或者系统缓存的清理、对每日的数据进行分析和总结等需求,这些都是定时任务。单体系统和分布式系统的分布式任务有很大的区别,单体系统就一个任务执行类,非常简单,分布式系统则要保证定时任务执行的唯一性,不能让一个定时任务被执行多次。

实现定时任务的5种方式

Java定时任务目前主要有以下5种实现方式。

JDK自带的实现方式,如JDK自带的Timer和JDK 1.5+新增的ScheduledExecutor- Service;

elastic-job:功能完备的分布式定时任务框架;

Spring 3.0以后自带的task:可以将它看成一个轻量级的任务调度;

使用Quartz实现定时任务;

分布式任务调度:可以使用国产组件XXL-Job实现。

下面分别讲解不同的定时任务的实现。

实战:基于JDK方式实现简单定时

使用JDK方式实现定时任务有两种方法:

(1)第一种是使用Timer类进行实现,Timer是JDK自带的定时任务执行类,任何项目都可以直接使用Timer来实现定时任务,因此Timer的优点就是使用方便。但是Timer的缺点也很明显,这是个单线程的实现,如果任务执行时间太长或者发生异常,则会影响其他任务执行。在开发和测试环境中可以用Timer类进行测试,强烈建议在生产环境中谨慎使用,使用Timer实现的定时任务代码如下:

package com.example.springextenddemo.dingshi;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

import java.util.Timer;

import java.util.TimerTask;

public class TimerDemo {

//定义时间格式

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

public static void main(String[] args) {

Timer timer = new Timer();

/**

* 从当前时刻开始,每1s执行一次,方法的入参单位为毫秒(ms,1000毫秒即

1s)

*/

timer.schedule(new MyTask(),0,1000);

}

/**

* 自定义任务实现

*/

private static class MyTask extends TimerTask {

@Override

public void run() {

LocalDateTime now = LocalDateTime.now();

System.out.println("这是定时任务,时间

是:"+pattern.format(now));

}

}

}

执行当前的main()方法,可以看到控制台打印的定时任务日志如图6.10所示。

Timer类设定定时任务有以下3种重载方法:

schedule(TimerTask task, long delay):延迟delay毫秒再执行任务;

schedule(TimerTask task, Date time):在特定的时间执行任务;

schedule(TimerTask task, long delay, long period):延迟delay毫秒执行并每隔period毫秒执行一次。

(2)使用JDK实现定时任务的第二种方式就是使用ScheduledExecutorService类。该类是Java 1.5后新增的定时任务接口,主要有以下几种方法:

public interface ScheduledExecutorService extends ExecutorService {

public ScheduledFuture<?> schedule(Runnable command,

long delay, TimeUnit unit); public <V> ScheduledFuture<V> schedule(Callable<V> callable,

long delay, TimeUnit unit);

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,

long initialDelay,

long period,

TimeUnit unit);

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable

command,

long initialDelay,

long delay,

TimeUnit unit);

}

ScheduledExecutorService类的基本原理和Timer相似,下面使用ScheduledExecutor- Service实现和Timer一样的定时任务功能:

package com.example.springextenddemo.dingshi;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class ScheduledExecutorServiceDemo {

//时间格式

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

public static void main(String[] args) {

ScheduledExecutorService service =

Executors.newScheduledThreadPool(1);

service.scheduleAtFixedRate(() -> { LocalDateTime now = LocalDateTime.now();

System.out.println("schedule 这是定时任务,时间是:" +

pattern.format(now));

}, 0, 1000, TimeUnit.MILLISECONDS);

}

}

执行main()方法,控制台打印的日志如图6.11所示,与上面的Timer实现了相同的效果。在开发过程中,如果只是简单的定时任务,建议直接采用ScheduleExecutorsService类来处理,这是线程池技术,能够实现线程的复用。

实战:基于Spring Task实现定时任务

Spring Task的核心实现类位于spring-context包中,在Spring项目中可以直接使用该定时任务类。下面演示Spring Task定时任务的实现过程。添加一个新的类SpringTaskDemo,代码如下:

package com.example.springextenddemo.dingshi;

import org.springframework.scheduling.annotation.EnableScheduling;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

@EnableScheduling //开启定时任务

@Component

public class SpringTaskDemo {

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

/**

* 每秒钟执行一次

*/

@Scheduled(cron = "0/1 * * * * ?")

public void cron() {

LocalDateTime now = LocalDateTime.now();

System.out.println("spring task 这是定时任务,时间是:" +

pattern.format(now));

}

}

再次启动SpringBoot项目,然后就可以自动启动Spring Task了,定时任务执行结果如图6.12所示。@EnableScheduling注解表示开启SpringTask任务,如果不开启,就没有办法执行定时任务。@Scheduled(cron = "0/1 * ** * ?")注解表示每分钟执行一次,注解中的“0/1 * * * * ?”是cron表达式,cron表达式包括Seconds、Minutes、Hours、Day-of-Month、Month、Day-of-Week和Year(可选字段),它们之间以空隔分隔。读者可根据要实现的业务完成cron表达式的拼接。cron中一些特殊字符的含义如表6.3所示。


@Scheduled注解支持非常多的参数,以帮助开发者快速完成定时任务的开发,这些参数如下:

cron:cron表达式,指定任务在特定的时间执行;

fixedDelay:上一次任务执行完成后隔多长时间再次执行,参数类型为long,单位为ms;

fixedDelayString:与fixedDelay的含义一样,只是参数类型变为String;

fixedRate:按一定的频率执行任务,参数类型为long,单位为ms;fixedRateString:与fixedRate的含义一样,只是参数类型变为String;

initialDelay:第一次任务延迟多久再执行,参数类型为long,单位为ms;

initialDelayString:与initialDelay的含义一样,只是参数类型变为String;

zone:时区,默认为当前时区,一般不用。

基于Spring Task强大的功能和便捷性,在开发Spring项目时,笔者推荐

使用Spring Task完成定时任务的需求。

实战:基于Quartz实现定时调度

Quartz是一个由Java编写的开源任务调度框架,其通过触发器设置作业定时运行规则,控制作业的运行时间。Quartz还可以搭建成集群服务,其中,Quartz集群通过故障切换和负载平衡的功能,能给调度器带来高可用性和伸缩性。我们一般用Quartz来执行定时任务,如定时发送信息、定时生成报表等。在分布式系统中,也可以使用Quartz完成任务调度的需求。

Quartz框架的核心组件包括调度器、触发器和作业。调度器是作业的总指挥,触发器是作业的操作者,作业为应用的功能模块。

Quartz框架中的Job为任务接口,该接口只有一个方法voidexecute(JobExecution- Context context),自定义定时任务的类需要实现Job接口并重写execute()方法,在该方法中完成定时业务逻辑。

JobExecutionContext类提供了调度上下文的各种信息。每次执行Job时均需要重新创建一个Job实例。

下面再介绍几个Quartz常用的几个类:JobDetail类用来描述Job的实现类及其他相关的静态信息;Trigger类是定时任务的定时管理工具,一个Trigger只能对应一个定时任务,而一个定时任务却可对应多个触发器;

Scheduler类是定时任务的管理容器,是Quartz最上层的接口,它管理所有触发器和定时任务,使它们协调工作,每个Scheduler都保存有JobDetail和Trigger的注册信息,一个Scheduler类中可以注册多个JobDetail和多个Trigger。

基于以上介绍,使用Quartz重新实现6.2.2小节的定时任务。

(1)在pom.xml中添加Quartz的依赖,其坐标如下:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-quartz</artifactId>

</dependency>

(2)修改log4j2.xml的日志记录器,添加Quartz包的日志级别为INFO,不要打印DEBUG级别的日志。

<loggers>

<!--Spring和MyBatis的日志级别为INFO-->

<logger name="org.springframework" level="INFO"></logger>

<logger name="org.mybatis" level="INFO"></logger>

<logger name="org.quartz" level="INFO"></logger>

<!-- 自定义包设置为INFO,则可以看见输出的日志不包含DEBUG输出了 -->

<logger name="com.example.springextenddemo" level="INFO"/>

<root level="all">

<appender-ref ref="myAppender"/>

</root>

</loggers>

(3)自定义任务执行类,添加Quartz的任务类:

package com.example.springextenddemo.dingshi;import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.springframework.scheduling.quartz.QuartzJobBean;

import java.time.LocalDateTime;

import java.time.format.DateTimeFormatter;

public class MyQuartzTask extends QuartzJobBean{

private static DateTimeFormatter pattern =

DateTimeFormatter.ofPattern

("yyyy-MM-dd HH:MM:ss");

@Override

public void executeInternal(JobExecutionContext context) throws

JobExecutionException {

LocalDateTime now = LocalDateTime.now();

System.out.println("quartz 这是定时任务,时间是:" +

pattern.format(now));

}

}

(4)添加Quzrtz的配置类,配置定时任务的执行时间和频率。

package com.example.springextenddemo.dingshi;

import org.quartz.*;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class QuartzConfig {

@Bean

public JobDetail testQuartz1() {

return JobBuilder.newJob(MyQuartzTask.class).withIdentity

("myQuartzTask") .storeDurably().build();

}

@Bean

public Trigger testQuartzTrigger1() {

//1s执行一次

SimpleScheduleBuilder scheduleBuilder =

SimpleScheduleBuilder.simpleSchedule()

.withIntervalInSeconds(1)

.repeatForever();

return TriggerBuilder.newTrigger().forJob(testQuartz1())

.withIdentity("myQuartzTask")

.withSchedule(scheduleBuilder)

.build();

}

}

(5)启动当前项目会自动加载定时任务,通过控制台就能看到Quartz定时任务的执行情况,控制台打印的日志如图6.13所示。

至此,在项目中使用定时任务的例子便介绍完了,在开发中可以直接使用Timer或者ScheduledExecutorService进行定时任务的测试,在实际的生产环境中,应根据项目情况选择使用Spring Task或者Quartz来实现需求。

相关推荐

Spring框架基础知识-第四节内容(Spring基础配置)

Spring基础配置Spring框架本身有四大原则:(1)使用POJO进行轻量级和最小侵入式开发。(2)通过依赖注入和基于接口编程实现松耦合。(3)通过AOP和默认习惯进行声明式编程。(4)使...

SpringBoot项目开发实战销售管理系统——项目框架搭建!

项目框架搭建在完成项目的分析和数据库设计后,一般由架构师完成项目框架的搭建,包括项目依赖的添加、项目的配置和项目日志的配置,完成后再开始业务代码的编写。技术栈的搭建新建一个SpringBoot项目,...

从零到一:独立运行若依框架系统并进行本地二次开发

####一、环境准备1.**基础环境**:-JDK1.8+(推荐JDK17)-Maven3.6+-MySQL5.7+(推荐8.0)-Redis5.0+-Node.js16...

单片机时间片轮询程序架构(单片机如何实现精准的时间周期)

时间片轮询法有很多时候都是与操作系统一起被提到,也就是说很多时候是操作系统中使用了这一方法:STM32单片机开发中的RTOS。下文将参考别人的代码,演示建立的一个时间片轮询架构程序的...

Netty主要组件和服务器启动源码分析

1.Netty服务端启动代码publicclassNettyServer{publicstaticvoidmain(String[]args)throwsInterrup...

前端定时任务的神库!快把它加到你的项目中去!

我们常会遇到定时刷新数据、轮询接口、发送提醒等场景,我们常会遇到定时刷新数据、轮询接口、发送提醒等场景。为什么选择cron库?定时任务开发痛点原生setInterval的时间误差累积难以实现复杂的...

如何正确实现一个后台(定时)任务(后台定时任务怎么实现)

相信大家都知道如何在.NET中执行后台(定时)任务。首先我们会选择实现IHostedService接口或者继承BackgroundService来实现后台任务。然后注册到容器内,然后注册到容...

秒杀传统的Linux Crontab,这款开源的定时任务管理系统绝了!

Gocron是一款开源的定时任务管理系统,基于Go语言开发,旨在替代传统的LinuxCrontab。它通过Web界面提供直观的任务管理功能,支持精确到秒的Crontab时间表达式,并具备任务重试、超...

Python 定时任务:schedule 自动执行脚本太方便。

2025年了,还在为Python定时任务头疼?轻量级需求搞什么Celery,schedule三行代码就搞定。这库把定时任务简化到像说人话,但新手直接抄文档容易踩坑。文档只会告诉你怎么设置每10分钟执行...

SpringBoot扩展——定时任务!(基于springboot的校园宿舍管理系统的设计与实现)

定时任务项目开发中会涉及很多需要定时执行的代码,如每日凌晨对前一日的数据进行汇总,或者系统缓存的清理、对每日的数据进行分析和总结等需求,这些都是定时任务。单体系统和分布式系统的分布式任务有很大的区别,...

适合普通开发者和产品经理的PHP应用模板开发AI的SaaS应用框架

简单到傻!Liang_SaaS适合普通开发者和产品经理的PHP应用模板开发AI的SaaS应用框架,利用Php开发AI的SaaS应用框架,是一个强大的内容管理仪表板模板,基于Bootstrap和...

非常实用的15款开源PHP类库(php开源管理系统)

PHP库给开发者提供了一个标准接口,它帮助开发者在PHP里充分利用面向对象编程。这些库为特定类型的内置功能提供了一个标准的API,允许类可以与PHP引擎进行无缝的交互。此外,开发者使用这些类库还可以简...

蜂神榜苹果商店也凑热闹:“520”我爱玩家!

各位看官,今天被朋友圈各类“520”刷屏呢?有没有给你亲爱的家人一份“520”模式的红包呢?苹果商店也给了玩家一个“520”模式的惊喜---再一次提供了多款“1元”价格的游戏!并且此次降价的游戏品质都...

变成气球的猫咪《气球》十一正式推出

墨西哥游戏公司NoodlecakeGames曾开发过《致命框架》、《阿尔托冒险》等优秀佳作,而它旗下的最新游戏《气球》(TheBalloons)在十一的时候就要和大家见面了。游戏中,玩家要操控娃娃...

星座超游爱:狮子遇挑战,处女手抓牢~

teemo跟大家讲了三期太阳星座,也许有很多不热心的小伙伴并不知道是什么东西,今天就小科普一番~在出生的那一天,太阳所落的那个星座,就是每个人的太阳星座,而这恰好就是大家的性格中心,是权势驱力、人格的...

取消回复欢迎 发表评论: