温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在Spring Boot中实现定时任务

发布时间:2021-05-14 17:21:56 来源:亿速云 阅读:242 作者:Leah 栏目:编程语言

如何在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、添加依赖

 <dependency>  <groupId>org.quartz-scheduler</groupId>  <artifactId>quartz</artifactId>  <version>2.3.0</version>  </dependency>

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(),  quartzTaskBTrigger.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 = "quartzTaskA")  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

springboot是什么

springboot一种全新的编程规范,其设计目的是用来简化新Spring应用的初始搭建以及开发过程,SpringBoot也是一个服务于框架的框架,服务范围是简化配置文件。

看完上述内容,你们掌握如何在Spring Boot中实现定时任务的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI