博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Boot定时任务应用实践
阅读量:7065 次
发布时间:2019-06-28

本文共 10490 字,大约阅读时间需要 34 分钟。

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

一、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@EnableSchedulingpublic 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())));    }}

上述代码中,在一个类上添加@EnableScheduling注解,在方法上加上@Scheduled,配置下表达式,一个最最简单的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@EnableSchedulingpublic 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())));    }}

注意一下主要区别:

@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文件中新增如下配置:

 
cron-config

其实,我们完全可以不用配置,直接在代码里面写或者持久化在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;@DisallowConcurrentExecutionpublic 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())));    }}

任务2:

 
QuartzTaskB

定时发送邮件任务:

 
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;    }}

定义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;@Configurationpublic 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;    }}

接着配置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;@Configurationpublic 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;    }}

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

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

 

扩展阅读:

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

参考:

转载于:https://www.cnblogs.com/rianbowymail/p/8992632.html

你可能感兴趣的文章
清空回收站后怎么恢复文件?还是这个方法好
查看>>
java中的多线程你只要看这一篇就够了
查看>>
网站验证码突然无法显示
查看>>
配置DHCP
查看>>
shell 相关操作
查看>>
网络设备
查看>>
倒计时
查看>>
golang从腾讯 lbs 获取全国省市区及经纬度坐标
查看>>
再谈java乱码:GBK和UTF-8互转尾部乱码问题分析
查看>>
iOS绘图例2:增加Undo/Redo功能
查看>>
python字典操作总结
查看>>
QMake study(part 3)
查看>>
掌握python机器学习-读书笔记4(特征选择)
查看>>
服务器指示灯说明
查看>>
LumiSoft收取邮件(含邮件附件)
查看>>
oracle分页查询
查看>>
Hadoop 2.0 NameNode HA和Federation实践
查看>>
半自动化安装dns
查看>>
MySQL常用命令(转)
查看>>
Linux 下压缩与解压.zip和.rar及.7z文件
查看>>