Spring Boot中实现定时任务应用实践

网友投稿 244 2023-02-06


Spring Boot中实现定时任务应用实践

前言

在Spring Boot中实现定时任务功能,可以通过Spring自带的定时任务调度,也可以通过集成经典开源组件Quartz实现任务调度。

本文将详细介绍关于Spring Boot实现定时任务应用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

一、Spring定时器

1、cron表达式方式

使用自带的定时任务,非常简单,只需要像下面这样,加上注解就好,不需要像普通定时任务框架那样继承任何定时处理接口 ,简单示例代码如下:

package com.power.demo.scheduledtask.simple;

import com.power.demo.util.DateTimeUtil;

import org.springframework.scheduling.annotation.EnableScheduling;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;

import java.util.Date;

@Component

@EnableScheduling

public class SpringTaskA {

/**

* CRON表达式参考:http://cron.qqe2.com/

**/

@Scheduled(cron = "*/5 * * * * ?", zone = "GMT+8:00")

private void timerCron() {

try {

Thread.sleep(100);

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(String.format("(timerCron)%s 每隔5秒执行一次,记录日志", DateTimeUtil.fmtDate(new Date())));

}

}

SpringTaskA

上述代码中,在一个类上添加@EnableScheduling注解,在方法上加上@Scheduled,配置下 cron 表达式,一个最最简单的cron定时任务就完成了。cron表达式的各个组成部分,可以参考下面:

@Scheduled(cron = "[Seconds] [Minutes] [Hours] [Day of month] [Month] [Day of week] [Year]")

2、fixedRate和fixedDelay

@Scheduled注解除了cron表达式,还有其他配置方式,比如fixedRate和fixedDelay,下面这个示例通过配置方式的不同,实现不同形式的定时任务调度,示例代码如下:

package com.power.demo.scheduledtask.simple;

import com.power.demo.util.DateTimeUtil;

import org.springframework.scheduling.annotation.EnableScheduling;

import org.springframework.scheduling.annotation.Scheduled;

import org.springframework.stereotype.Component;

import java.util.Date;

@Component

@EnableScheduling

public class SpringTaskB {

/*fixedRate:上一次开始执行时间点之后5秒再执行*/

@Scheduled(fixedRate = 5000)

public void timerFixedRate() {

try {

Thread.sleep(100);

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(String.format("(fixedRate)现在时间:%s", DateTimeUtil.fmtDate(new Date())));

}

/*fixedDelay:上一次执行完毕时间点之后5秒再执行*/

@Scheduled(fixedDelay = 5000)

public void timerFixedDelay() {

try {

Thread.sleep(100);

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(String.format("(fixedDelay)现在时间:%s", DateTimeUtil.fmtDate(new Date())));

}

/*第一次延迟2秒后执行,之后按fixedDelay的规则每5秒执行一次*/

@Scheduled(initialDelay = 2000, fixedDelay = 5000)

public void timerInitDelay() {

try {

Thread.sleep(100);

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(String.format("(initDelay)现在时间:%s", DateTimeUtil.fmtDate(new Date())));

}

}

SpringTaskB

注意一下主要区别:

@Scheduled(fixedRate = 5000)  :上一次开始执行时间点之后5秒再执行

@Scheduled(fixedDelay = 5000)  :上一次执行完毕时间点之后5秒再执行

@Scheduled(initialDelay=2000, fixedDelay=5000)  :第一次延迟2秒后执行,之后按fixedDelay的规则每5秒执行一次

有时候,很多项目我们都需要配置好定时任务后立即执行一次,initialDelay就可以不用配置了。

3、zone

@Scheduled注解还有一个熟悉的属性zone,表示时区,通常,如果不写,定时任务将使用服务器的默认时区;如果你的任务想在特定时区特定时间点跑起来,比如常见的多语言系统可能会定时跑脚本更新数据,就可以设置一个时区,如东八区,就可以设置为:

zone = "GMT+8:00"

二、Quartz

Quartz是应用最为广泛的开源任务调度框架之一,有很多公司都根据它实现自己的定时任务管理系统。Quartz提供了最常用的两种定时任务触发器,即SimpleTrigger和CronTrigger,本文以最广泛使用的CronTrigger为例。

1、添加依赖

org.quartz-scheduler

quartz

2.3.0

2、配置cron表达式

示例代码需要,在application.properties文件中新增如下配置:

## Quartz定时job配置

job.taska.cron=*/3 * * * * ?

job.taskb.cron=*/7 * * * * ?

job.taskmail.cron=*/5 * * * * ?

其实,我们完全可以不用配置,直接在代码里面写或者持久化在DB中然后读取也可以。

3、添加定时任务实现

任务1:

package com.power.demo.scheduledtask.quartz;

import com.power.demo.util.DateTimeUtil;

import org.quartz.DisallowConcurrentExecution;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import java.util.Date;

@DisallowConcurrentExecution

public class QuartzTaskA implements Job {

@Override

public void execute(JobExecutionContext var1) throws JobExecutionException {

try {

Thread.sleep(1);

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(String.format("(QuartzTaskA)%s 每隔3秒执行一次,记录日志", DateTimeUtil.fmtDate(new Date())));

}

}

QuartzTaskA

任务2:

package com.power.demo.scheduledtask.quartz;

import com.power.demo.util.DateTimeUtil;

import org.quartz.DisallowConcurrentExecution;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import java.util.Date;

@DisallowConcurrentExecution

public class QuartzTaskB implements Job {

@Override

public void execute(JobExecutionContext var1) throws JobExecutionException {

try {

Thread.sleep(100);

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(String.format("(QuartzTaskB)%s 每隔7秒执行一次,记录日志", DateTimeUtil.fmtDate(new Date())));

}

}

QuartzTaskB

定时发送邮件任务:

package com.power.demo.scheduledtask.quartz;

import com.power.demo.service.contract.MailService;

import com.power.demo.util.DateTimeUtil;

import com.power.demo.util.PowerLogger;

import org.joda.time.DateTime;

import org.quartz.DisallowConcurrentExecution;

import org.quartz.Job;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;

@DisallowConcurrentExecution

public class MailSendTask implements Job {

@Autowired

private MailService mailService;

@Override

public void execute(JobExecutionContext var1) throws JobExecutionException {

System.out.println(String.format("(MailSendTask)%s 每隔5秒发送邮件", DateTimeUtil.fmtDate(new Date())));

try {

//Thread.sleep(1);

DateTime dtNow = new DateTime(new Date());

Date startTime = dtNow.minusMonths(1).toDate();//一个月前

Date endTime = dtNow.plusDays(1).toDate();

mailService.autoSend(startTime, endTime);

PowerLogger.info(String.format("发送邮件,开始时间:%s,结束时间:%s"

, DateTimeUtil.fmtDate(startTime), DateTimeUtil.fmtDate(endTime)));

} catch (Exception e) {

e.printStackTrace();

PowerLogger.info(String.format("发送邮件,出现异常:%s,结束时间:%s", e));

}

}

}

MailSendTask

实现任务看上去非常简单,继承Quartz的Job接口,重写execute方法即可。

4、集成Quartz定时任务

怎么让Spring自动识别初始化Quartz定时任务实例呢?这就需要引用Spring管理的Bean,向Spring容器暴露所必须的bean,通过定义Job Factory实现自动注入。

首先,添加Spring注入的Job Factory类:

package com.power.demo.scheduledtask.quartz.config;

import org.quartz.spi.TriggerFiredBundle;

import org.springframework.beans.factory.config.AutowireCapableBeanFactory;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public final class AutowireBeanJobFactory extends SpringBeanJobFactory

implements ApplicationContextAware {

private transient AutowireCapableBeanFactory beanFactory;

/**

* Spring提供了一种机制让你可以获取ApplicationContext,即ApplicationContextAware接口

* 对于一个实现了ApplicationContextAware接口的类,Spring会实例化它的同时调用它的

* public voidsetApplicationContext(ApplicationContext applicationContext) throws BeansException;接口,

* 将该bean所属上下文传递给它。

**/

@Override

public void setApplicationContext(final ApplicationContext context) {

beanFactory = context.getAutowireCapableBeanFactory();

}

@Override

protected Object createJobInstance(final TriggerFiredBundle bundle)

throws Exception {

final Object job = super.createJobInstance(bundle);

beanFactory.autowireBean(job);

return job;

}

}

AutowireBeanJobFactory

定义QuartzConfig:

package com.power.demo.scheduledtask.quartz.config;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.scheduling.quartz.CronTriggerFactoryBean;

import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration

public class QuartzConfig {

@Autowired

@Qualifier("quartzTaskATrigger")

private CronTriggerFactoryBean quartzTaskATrigger;

@Autowired

@Qualifier("quartzTaskBTrigger")

private CronTriggerFactoryBean quartzTaskBTrigger;

@Autowired

@Qualifier("mailSendTrigger")

private CronTriggerFactoryBean mailSendTrigger;

//Quartz中的job自动注入spring容器托管的对象

@Bean

public AutowireBeanJobFactory autoWiringSpringBeanJobFactory() {

return new AutowireBeanJobFactory();

}

@Bean

public SchedulerFactoryBean schedulerFactoryBean() {

SchedulerFactoryBean scheduler = new SchedulerFactoryBean();

scheduler.setJobFactory(autoWiringSpringBeanJobFactory()); //配置Spring注入的Job类

//设置CronTriggerFactoryBean,设定任务Trigger

scheduler.setTriggers(

quartzTaskATrigger.getObject(),

qnAZgJuuartzTaskBTrigger.getObject(),

mailSendTrigger.getObject()

);

return scheduler;

}

}

QuartzConfig

接着配置job明细:

package com.power.demo.scheduledtask.quartz.config;

import com.power.demo.common.AppField;

import com.power.demo.scheduledtask.quartz.MailSendTask;

import com.power.demo.scheduledtask.quartz.QuartzTaskA;

import com.power.demo.scheduledtask.quartz.QuartzTaskB;

import com.power.demo.util.ConfigUtil;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.scheduling.quartz.CronTriggerFactoryBean;

import org.springframework.scheduling.quartz.JobDetailFactoryBean;

@Configuration

public class TaskSetting {

@Bean(name = "quartzTnAZgJuaskA")

public JobDetailFactoryBean jobDetailAFactoryBean() {

//生成JobDetail

JobDetailFactoryBean factory = new JobDetailFactoryBean();

factory.setJobClass(QuartzTaskA.class); //设置对应的Job

factory.setGroup("quartzTaskGroup");

factory.setName("quartzTaskAJob");

factory.setDurability(false);

factory.setDescription("测试任务A");

return factory;

}

@Bean(name = "quartzTaskATrigger")

public CronTriggerFactoryBean cronTriggerAFactoryBean() {

String cron = ConfigUtil.getConfigVal(AppField.JOB_TASKA_CRON);

CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();

//设置JobDetail

stFactory.setJobDetail(jobDetailAFactoryBean().getObject());

stFactory.setStartDelay(1000);

stFactory.setName("quartzTaskATrigger");

stFactory.setGroup("quartzTaskGroup");

stFactory.setCronExpression(cron);

return stFactory;

}

@Bean(name = "quartzTaskB")

public JobDetailFactoryBean jobDetailBFactoryBean() {

//生成JobDetail

JobDetailFactoryBean factory = new JobDetailFactoryBean();

factory.setJobClass(QuartzTaskB.class); //设置对应的Job

factory.setGroup("quartzTaskGroup");

factory.setName("quartzTaskBJob");

factory.setDurability(false);

factory.setDescription("测试任务B");

return factory;

}

@Bean(name = "quartzTaskBTrigger")

public CronTriggerFactoryBean cronTriggerBFactoryBean() {

String cron = ConfigUtil.getConfigVal(AppField.JOB_TASKB_CRON);

CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();

//设置JobDetail

stFactory.setJobDetail(jobDetailBFactoryBean().getObject());

stFactory.setStartDelay(1000);

stFactory.setName("quartzTaskBTrigger");

stFactory.setGroup("quartzTaskGroup");

stFactory.setCronExpression(cron);

return stFactory;

}

@Bean(name = "mailSendTask")

public JobDetailFactoryBean jobDetailMailFactoryBean() {

//生成JobDetail

JobDetailFactoryBean factory = new JobDetailFactoryBean();

factory.setJobClass(MailSendTask.class); //设置对应的Job

factory.setGroup("quartzTaskGroup");

factory.setName("mailSendTaskJob");

factory.setDurability(false);

factory.setDescription("邮件发送任务");

return factory;

}

@Bean(name = "mailSendTrigger")

public CronTriggerFactoryBean cronTriggerMailFactoryBean() {

String cron = ConfigUtil.getConfigVal(AppField.JOB_TASKMAIL_CRON);

CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();

//设置JobDetail

stFactory.setJobDetail(jobDetailMailFactoryBean().getObject());

stFactory.setStartDelay(1000);

stFactory.setName("mailSendTrigger");

stFactory.setGroup("quartzTaskGroup");

stFactory.setCronExpression(cron);

return stFactory;

}

}

TaskSetting

最后启动你的Spring Boot定时任务应用,一个完整的基于Quartz调度的定时任务就实现好了。

本文定时任务示例中,有一个定时发送邮件任务MailSendTask,下一篇将分享Spring Boot应用中以MongoDB作为存储介质的简易邮件系统。

扩展阅读:

很多公司都会有自己的定时任务调度框架和系统,在Spring Boot中如何整合Quartz集群,实现动态定时任务配置?

参考:

//jb51.net/article/139591.htm

//jb51.net/article/139597.htm

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Quartz集群原理以及配置应用的方法详解
下一篇:基于vue
相关文章

 发表评论

暂时没有评论,来抢沙发吧~