【spring-boot】 springboot集成quartz实现定时任务

在做项目时有时候会有定时器任务的功能,比如某某时间应该做什么,多少秒应该怎么样之类的。

spring支持多种定时任务的实现。我们来介绍下使用spring的定时器和使用quartz定时器

  1.我们使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式。

  2.使用spring的定时器:

    spring自带支持定时器的任务实现。其可通过简单配置来使用到简单的定时任务。

@Component
@Configurable
@EnableScheduling
public class ScheduledTasks{

    @Scheduled(fixedRate = 1000 * 30)
    public void reportCurrentTime(){
        System.out.println ("Scheduling Tasks Examples: The time is now " + dateFormat ().format (new Date ()));
    }

    //每1分钟执行一次
    @Scheduled(cron = "0 */1 *  * * * ")
    public void reportCurrentByCron(){
        System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));
    }

    private SimpleDateFormat dateFormat(){
        return new SimpleDateFormat ("HH:mm:ss");
    }

}

没了,没错,使用spring的定时任务就这么简单,其中有几个比较重要的注解:

   @EnableScheduling:标注启动定时任务。

@Scheduled(fixedRate = 1000 * 30)  定义某个定时任务。

  3.使用quartz实现定时任务。
    Quartz设计者做了一个设计选择来从调度分离开作业。Quartz中的触发器用来告诉调度程序作业什么时候触发。框架提供了一把触发器类型,但两个最常用的是SimpleTrigger和CronTrigger。SimpleTrigger为需要简单打火调度而设计。典型地,如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业,那么SimpleTrigger适合你。另一方面,如果你有许多复杂的作业调度,那么或许需要CronTrigger。
    CronTrigger是基于Calendar-like调度的。当你需要在除星期六和星期天外的每天上午10点半执行作业时,那么应该使用CronTrigger。正如它的名字所暗示的那样,CronTrigger是基于Unix克隆表达式的。

    使用quartz说使用的maven依赖。

    

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

    由于我们使用的是spring-boot框架,其目的是做到零配置文件,所以我们不使用xml文件的配置文件来定义一个定时器,而是使用向spring容器暴露bean的方式。

    向spring容器暴露所必须的bean

    

@Configuration
public class SchedledConfiguration {

    // 配置中设定了
    // ① targetMethod: 指定需要定时执行scheduleInfoAction中的simpleJobTest()方法
    // ② concurrent:对于相同的JobDetail,当指定多个Trigger时, 很可能第一个job完成之前,
    // 第二个job就开始了。指定concurrent设为false,多个job不会并发运行,第二个job将不会在第一个job完成之前开始。
    // ③ cronExpression:0/10 * * * * ?表示每10秒执行一次,具体可参考附表。
    // ④ triggers:通过再添加其他的ref元素可在list中放置多个触发器。 scheduleInfoAction中的simpleJobTest()方法
    @Bean(name = "detailFactoryBean")
    public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduledTasks scheduledTasks){
        MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean ();
        bean.setTargetObject (scheduledTasks);
        bean.setTargetMethod ("reportCurrentByCron");
        bean.setConcurrent (false);
        return bean;
    }

    @Bean(name = "cronTriggerBean")
    public CronTriggerBean cronTriggerBean(MethodInvokingJobDetailFactoryBean detailFactoryBean){
        CronTriggerBean tigger = new CronTriggerBean ();
        tigger.setJobDetail (detailFactoryBean.getObject ());
        try {
            tigger.setCronExpression ("0/5 * * * * ? ");//每5秒执行一次
        } catch (ParseException e) {
            e.printStackTrace ();
        }
        return tigger;

    }

    @Bean
    public SchedulerFactoryBean schedulerFactory(CronTriggerBean[] cronTriggerBean){
        SchedulerFactoryBean bean = new SchedulerFactoryBean ();
        System.err.println (cronTriggerBean[0]);
        bean.setTriggers (cronTriggerBean);
        return bean;
    }}

    MethodInvokingJobDetailFactoryBean:此工厂主要用来制作一个jobDetail,即制作一个任务。由于我们所做的定时任务根本上讲其实就是执行一个方法。所以用这个工厂比较方便。

      注意:其setTargetObject所设置的是一个对象而不是一个类。

    CronTriggerBean:定义一个触发器。

      注意:setCronExpression:是一个表达式,如果此表达式不合规范,即会抛出异常。

    SchedulerFactoryBean:主要的管理的工厂,这是最主要的一个bean。quartz通过这个工厂来进行对各触发器的管理。

  4.对quartz的封装

    由上面代码可以看出来,此处我们设置的是一个固定的cronExpression,那么,做为项目中使用的话,我们一般是需要其动态设置比如从数据库中取出来。

    其实做法也很简单,我们只需要定义一个Trigger来继承CronTriggerBean。顶用其setCronExpression方法即可。

    那么另外一个问题,如果我们要定义两个定时任务则会比较麻烦,需要先注入一个任务工厂,在注入一个触发器。

       为了减少这样的配置,我们定义了一个抽象的超类来继承CronTriggerBean。

    具体代码如下:

    

public abstract class BaseCronTrigger extends CronTriggerBean implements Serializable {

    private static final long serialVersionUID = 1L;

    public void init(){
        // 得到任务
        JobDetail jobdetail = new JobDetail (this.getClass ().getSimpleName (),this.getMyTargetObject ().getClass ());
        this.setJobDetail (jobdetail);
        this.setJobName (jobdetail.getName ());
        this.setName (this.getClass ().getSimpleName ());
        try {
            this.setCronExpression (this.getMyCronExpression ());
        } catch (java.text.ParseException e) {
            e.printStackTrace ();
        }

    }

    public abstract String getMyCronExpression();

    public abstract Job getMyTargetObject();

}

    其init()方法,来为这个触发器绑定任务。其任务为一个Job类型的,也就是说其执行的任务为实现了Job接口的类,这个任务会有一个execute()方法,来执行任务题。

    

public class ScheduledTasks implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException{
        System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));
    }

   private SimpleDateFormat dateFormat(){
        return new SimpleDateFormat ("HH:mm:ss");
    }
}

    为了给触发器添加任务,我们需要在子类中调用init()方法,由于spring容器注入时是使用的空参的构造函数,所以我们在此构造函数中调用init()方法。

    

@Component
public class InitializingCronTrigger extends BaseCronTrigger implements Serializable {

    private static final long    serialVersionUID = 1L;

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    public InitializingCronTrigger() {
        init ();
    }

    @Override
    public String getMyCronExpression(){
        return "0/5 * * * * ?";
    }

    @Override
    public Job getMyTargetObject(){
        return new ScheduledTasks ();
    }

    public void parse(){
        try {
            schedulerFactoryBean.getObject ().pauseAll ();
        } catch (SchedulerException e) {
            e.printStackTrace ();
        }
    }

}

    此时我们只需要在配置类中加入一个配置就可以了。

    

  @Bean
    public SchedulerFactoryBean schedulerFactory(CronTriggerBean[] cronTriggerBean){
        SchedulerFactoryBean bean = new SchedulerFactoryBean ();
        System.err.println (cronTriggerBean[0]);
        bean.setTriggers (cronTriggerBean);

        return bean;
    }

  4.介绍一个cronExpression表达式。

    这一部分是摘抄的:

      

字段   允许值   允许的特殊字符
  0-59   , - * /
  0-59   , - * /
小时   0-23   , - * /
日期   1-31   , - *   / L W C
月份   1-12 或者 JAN-DEC   , - * /
星期   1-7 或者 SUN-SAT   , - *   / L C #
年(可选)   留空, 1970-2099   , - * /

  
如上面的表达式所示:

“*”字符被用来指定所有的值。如:”*“在分钟的字段域里表示“每分钟”。

“-”字符被用来指定一个范围。如:“10-12”在小时域意味着“10点、11点、12点”。
 
“,”字符被用来指定另外的值。如:“MON,WED,FRI”在星期域里表示”星期一、星期三、星期五”.

“?”字符只在日期域和星期域中使用。它被用来指定“非明确的值”。当你需要通过在这两个域中的一个来指定一些东西的时候,它是有用的。看下面的例子你就会明白。

“L”字符指定在月或者星期中的某天(最后一天)。即“Last ”的缩写。但是在星期和月中“L”表示不同的意思,如:在月子段中“L”指月份的最后一天-1月31日,2月28日,如果在星期字段中则简单的表示为“7”或者“SAT”。如果在星期字段中在某个value值得后面,则表示“某月的最后一个星期value”,如“6L”表示某月的最后一个星期五。

“W”字符只能用在月份字段中,该字段指定了离指定日期最近的那个星期日。

“#”字符只能用在星期字段,该字段指定了第几个星期value在某月中

每一个元素都可以显式地规定一个值(如6),一个区间(如9-12),一个列表(如9,11,13)或一个通配符(如*)。“月份中的日期”和“星期中的日期”这两个元素是互斥的,因此应该通过设置一个问号(?)来表明你不想设置的那个字段。表7.1中显示了一些cron表达式的例子和它们的意义:


表达式

  意义
"0 0 12 * * ?"   每天中午12点触发
"0 15 10 ? * *"   每天上午10:15触发
"0 15 10 * * ?"   每天上午10:15触发
"0 15 10 * * ? *"   每天上午10:15触发
"0 15 10 * * ? 2005"   2005年的每天上午10:15触发
"0 * 14 * * ?"   在每天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?"   在每天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?"   在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?"   在每天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED"   每年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI"   周一至周五的上午10:15触发
"0 15 10 15 * ?"   每月15日上午10:15触发
"0 15 10 L * ?"   每月最后一日的上午10:15触发
"0 15 10 ? * 6L"   每月的最后一个星期五上午10:15触发 
"0 15 10 ? * 6L 2002-2005"   2002年至2005年的每月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3"   每月的第三个星期五上午10:15触发

            每天早上6点 0 6 * * *

            每两个小时 0 */2 * * *

            晚上11点到早上8点之间每两个小时,早上八点 0 23-7/2,8 * * *

每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点 0 11 4 * 1-3

            1月1日早上4点 0 4 1 1 *

  

    

    

时间: 2024-10-14 09:20:24

【spring-boot】 springboot集成quartz实现定时任务的相关文章

SpringBoot集成Quartz动态定时任务

项目中需要用到定时任务,考虑了下java方面定时任务无非就三种: 用Java自带的timer类.稍微看了一下,可以实现大部分的指定频率的任务的调度(timer.schedule()),也可以实现关闭和开启(timer.cancle).但是用其来实现某天的某个时间或者某月的某一天调度任务有点不方便. 采用Quartz 调度器实现.这是一个功能很强大的开源的专门用于定时任务调度的框架,也很好的和springboot整合,缺点:配置复杂,需要花费一定的时间去了解和研究. spring3.0以后自带的s

Spring Boot集成quartz实现定时任务并支持切换任务数据源

org.quartz实现定时任务并自定义切换任务数据源 在工作中经常会需要使用到定时任务处理各种周期性的任务,org.quartz是处理此类定时任务的一个优秀框架.随着项目一点点推进,此时我们并不满足于任务仅仅是定时执行,我们还想要对任务进行更多的控制,随时能对任务进行人为干预,就需要对quartz有更深入的了解.而随着微服务的流行,项目中多数据源的情况也越来越常见,在定时任务中集成多数据源切换的功能也需要集成进来. 集成quartz实现定时任务 集成quartz实现定时任务 quartz中实现

spring boot 2 集成JWT实现api接口认证

JSON Web Token(JWT)是目前流行的跨域身份验证解决方案.官网:https://jwt.io/本文spring boot 2 集成JWT实现api接口验证. 一.JWT的数据结构 JWT由header(头信息).payload(有效载荷)和signature(签名)三部分组成的,用“.”连接起来的字符串.JWT的计算逻辑如下:(1)signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(

Spring Boot Admin 集成自定义监控告警

Spring Boot Admin 集成自定义监控告警 前言 Spring Boot Admin 是一个社区项目,可以用来监控和管理 Spring Boot 应用并且提供 UI,详细可以参考 官方文档. Spring Boot Admin 本身提供监控告警功能,但是默认只提供了 Hipchat.Slack 等国外流行的通讯软件的集成,虽然也有邮件通知,不过考虑到使用体检决定二次开发增加 钉钉 通知. 本文基于 Spring Boot Admin 目前最新版 1.5.7. 准备工作 Spring

spring boot admin 集成的简单配置随笔

和我并肩作战的同事也要相继离职了,心里还是有很多不舍得,现在业务也陆陆续续落在了肩头,上午项目经理让我把spring boot admin集成到现在的项目中,已遍后续的监控. 哇!我哪里搞过这个!心里好慌,好在我面向对象虽然不是很精通,但是面向百度我倒是很拿手,于是开启了,面向百度编程,现在已经成功过了~写个博客继续一下,方便以后使用以及分享. 注:此写法适用于 2.0以下版本 高于2.0请直接官方文档走起:http://codecentric.github.io/spring-boot-adm

ssh中使用spring的集成quartz 开发定时任务

之前没有使用框架开发时对于开发定时任务都是 使用java的原声timer类,重写线程的run方法跑要执行的任务.刚刚换的新公司,项目使用ssh2,目前该项目中的定时任务的使用spirng集成的quartz工具,非常方便.好了,废话不多说,说一下开发过程. 首先,需要建一个资源配置xml文件,一般以quartz结尾.如我项目中的该文件名为:applicationContext-bms-sendxml-quartz.xml,别忘了在applicationContext.xml文件中导入该文件.app

spring-boot实战【09】【转】:Spring Boot中使用@Scheduled创建定时任务

我们在编写Spring Boot应用中经常会遇到这样的场景,比如:我需要定时地发送一些短信.邮件之类的操作,也可能会定时地检查和监控一些标志.参数等. 创建定时任务 在Spring Boot中编写定时任务是非常简单的事,下面通过实例介绍如何在Spring Boot中创建定时任务,实现每过5秒输出一下当前时间. 在Spring Boot的主类中加入@EnableScheduling注解,启用定时任务的配置 1 2 3 4 5 6 7 8 9 10 @SpringBootApplication @E

springboot集成quartz

导入依赖 <!--添加quartz的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> application.yml配置文件 spring: quartz: #相关属性配置 properties: org: quart

spring boot Rabbitmq集成,延时消息队列实现

本篇主要记录Spring boot 集成Rabbitmq,分为两部分, 第一部分为创建普通消息队列, 第二部分为延时消息队列实现: spring boot提供对mq消息队列支持amqp相关包,引入即可: [html] view plain copy <!-- rabbit mq --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-