欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot系列:Spring Boot集成定时任务Quartz

程序员文章站 2023-04-04 13:47:29
一、关于Quartz Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。在java企业级应用中,Quartz是使用最广泛的定时调度框架。 在Quartz中的主要概念: Scheduler:调度任务的 ......

一、关于quartz

quartz是opensymphony开源组织在job scheduling领域又一个开源项目,它可以与j2ee与j2se应用程序相结合也可以单独使用。在java企业级应用中,quartz是使用最广泛的定时调度框架。

在quartz中的主要概念:

  • scheduler:调度任务的主要api
  • schedulebuilder:用于构建scheduler,例如其简单实现类simpleschedulebuilder
  • job:调度任务执行的接口,也即定时任务执行的方法
  • jobdetail:定时任务作业的实例
  • jobbuilder:关联具体的job,用于构建jobdetail
  • trigger:定义调度执行计划的组件,即定时执行
  • triggerbuilder:构建trigger

一、quartz演示示例

在springboot中,我们需要引入quartz的依赖。

 <dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-web</artifactid>
</dependency>

<!--quartz定时调度依赖-->
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-quartz</artifactid>
</dependency>

首先定义定时具体执行逻辑job,创建类quartzjob1,这里集继承quartzjobbean实现executeinternal即可,该方法即定时执行任务逻辑,这里简单打印了下当前时间。

public class quartzjob1 extends quartzjobbean {

    @override
    protected void executeinternal(jobexecutioncontext jobexecutioncontext) throws jobexecutionexception {
        simpledateformat sdf=new simpledateformat("yyyy-mm-dd hh:mm:ss");
        system.out.println("quartzjob1----" + sdf.format(new date()));
    }

}

然后创建quartzconfig,接着定义jobdetail,jobdetail由jobbuilder构建,同时关联了任务quartzjob1。

@configuration
public class quartzconfig {

    @bean
    public jobdetail jobdetail1(){
        return jobbuilder.newjob(quartzjob1.class).storedurably().build();
    }
    
}

最后我们需要定义定时调度trigger,简单实现类simpleschedulebuilder用于构建scheduler,triggerbuilder则用于构建trigger,

@configuration
public class quartzconfig {

    @bean
    public jobdetail jobdetail1(){
        return jobbuilder.newjob(quartzjob1.class).storedurably().build();
    }

    @bean
    public trigger trigger1(){
        simpleschedulebuilder schedulebuilder = simpleschedulebuilder.simpleschedule()
                .withintervalinseconds(1) //每一秒执行一次
                .repeatforever(); //永久重复,一直执行下去
        return triggerbuilder.newtrigger()
                .forjob(jobdetail1())
                .withschedule(schedulebuilder)
                .build();
    }
    
}

这样一个quartz定时任务就配置完成了。

其实job的定义也可以使用内部类,这样可以省去job类的创建,例如下面定时任务2 jobdetail2和trigger2。

@bean
public jobdetail jobdetail2(){
    quartzjobbean quartzjob2 = new quartzjobbean() {
        @override
        protected void executeinternal(jobexecutioncontext jobexecutioncontext) throws jobexecutionexception {
            simpledateformat sdf=new simpledateformat("yyyy-mm-dd hh:mm:ss");
            system.out.println("内部类quartzjob2----" + sdf.format(new date()));
        }
    };
    return jobbuilder.newjob(quartzjob2.getclass()).storedurably().build();
}

@bean
public trigger trigger2(){
    //jobdetail的bean注入不能省略
    //jobdetail jobdetail3 = jobbuilder.newjob(quartzjob2.class).storedurably().build();
    simpleschedulebuilder schedulebuilder = simpleschedulebuilder.simpleschedule()
            .withintervalinseconds(2) //每2秒执行一次
            .repeatforever(); //永久重复,一直执行下去
    return triggerbuilder.newtrigger()
            .forjob(jobdetail2())
            .withschedule(schedulebuilder).build();
}

启动程序,我们就可以看到控制台的时间输出了。

SpringBoot系列:Spring Boot集成定时任务Quartz

同时quartz是支持数据持久化的,可以将定时调度信息持久化到数据库。

选择持久化到数据库,我们需要创建对应的表,建表语句可以在quartz官网进行下载,解压后在docs\dbtables目录下寻找对应数据库的sql脚本。

为了方便,我也将该文件放在了项目源码resources里。

操作数据库,我们引入相关的依赖。若有orm框架,例如mybatis,hibernate或者jpa,则无需再引入jdbc依赖。

<!--mysql连接-->
<dependency>
    <groupid>mysql</groupid>
    <artifactid>mysql-connector-java</artifactid>
    <scope>runtime</scope>
</dependency>

<!--druid连接池-->
<dependency>
    <groupid>com.alibaba</groupid>
    <artifactid>druid-spring-boot-starter</artifactid>
    <version>1.1.10</version>
</dependency>

<!--jdbc依赖-->
<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-jdbc</artifactid>
</dependency>

在application.yml配置文件中,我们对quartz持久化方式进行声明。

server:
  port: 10900

spring:
  profiles:
    active: dev
  quartz:
    job-store-type: jdbc #持久化到数据库
    properties:
      org:
        quartz:
          datasource:
            # 新版驱动从com.mysql.jdbc.driver变更为com.mysql.cj.jdbc.driver
            driver-class-name: com.mysql.cj.jdbc.driver
            # 数据源需要添加时间标准和指定编码格式解决乱码 you must configure either the server or jdbc driver (via the servertimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
            url: jdbc:mysql://localhost:3306/springboot?useunicode=true&characterencoding=utf-8&servertimezone=utc
            username: root
            password: 1234
          scheduler:
            instancname: clusteredscheduler
            instanceid: auto
          jobstore:
            class: org.quartz.impl.jdbcjobstore.jobstoretx
            driverdelegateclass: org.quartz.impl.jdbcjobstore.stdjdbcdelegate #stdjdbcdelegate说明支持集群
            tableprefix: qrtz_
            isclustered: true
            clustercheckininterval: 1000
            useproperties: false
          threadpool:
            class: org.quartz.simpl.simplethreadpool
            threadcount: 20
            threadpriority: 5

这里主要就是job-store-type: jdbc,表示持久化到数据库,然后就是数据源,由于该演示项目没有其他orm的数据源,所以这里将数据源信息定义在了quartz节点下的datasource节点,如果已经存在,可使用同一个属性配置,当然最关键的是quartzdatasource声明。

这里关键的是@quartzdatasource,这个要和项目中已经存在的数据源区分开。

//error:embeddeddatabasetype class not found,druid数据源初始化需要引入spring-jdbc依赖,jpa或mybatis依赖已经包含该依赖
@bean
@quartzdatasource
@configurationproperties(prefix = "spring.quartz.properties.org.quartz.datasource")
datasource quartzdatasource(){
    return druiddatasourcebuilder.create().build();
}

这样持久化就已经配置好了,我们执行sql,再启动项目,启动完成后,我们可以看到数据库中已经有我们的定时调度数据了。

SpringBoot系列:Spring Boot集成定时任务Quartz

源码地址: