SpringBoot 整合Quarz

SpringBoot 整合Quarz

1.数据库准备

Quartz 存储任务信息有两种方式,使用内存或者使用数据库来存储,这里我们采用 MySQL 数据库存储的方式,首先需要新建 Quartz 的相关表,sql 脚本下载地址:http://www.quartz-scheduler.org/downloads/,名称为 tables_mysql.sql,创建成功后数据库中多出 11 张表

2.数据库表介绍

表名说明
qrtz_blob_triggersTrigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore 并不知道如何存储实例的时候)
qrtz_calendars以Blob类型存储Quartz的Calendar日历信息, quartz可配置一个日历来指定一个时间范围
qrtz_cron_triggers存储Cron Trigger,包括Cron表达式和时区信息。
qrtz_fired_triggers存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息
qrtz_job_details存储每一个已配置的Job的详细信息
qrtz_locks存储程序的非观锁的信息(假如使用了悲观锁)
qrtz_paused_trigger_graps存储已暂停的Trigger组的信息
qrtzschedulerstate存储少量的有关 Scheduler的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)
qrtzsimpletriggers存储简单的 Trigger,包括重复次数,间隔,以及已触的次数
qrtz_triggers存储已配置的 Trigger的信息
qrztsimproptriggers

3. Maven 主要依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
        <!--mysql 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--pagehelper分页-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

这里使用 druid 作为数据库连接池,Quartz 默认使用 c3p0

4.配置文件

spring:
  datasource:
    name: mysql_test
    type: com.alibaba.druid.pool.DruidDataSource
    #druid相关配置
    druid:
      #监控统计拦截的filters
      filter: stat,config
#      driver-class-name: com.mysql.cj.jdbc.Driver
      #基本属性
      url: jdbc:mysql://localhost:3306/mydb
      username: root
      password: 123456
      #初始化连接数
      initial-size: 10
      #最小活跃连接数
      min-size: 5
      #最大活跃连接数
      max-active: 20
      #获取连接的等待时间
      max-wait: 60000
      #间隔多久进行一次检查,检查需要关闭的空闲连接
      time-between-eviction-runs-millis: 60000
      #一个连接在池中最小的生存时间(5分钟)
      min-evictable-idle-time-millis: 300000
      validation-query: SELECT 'X'
      # 验证空闲的连接,若无法验证,则删除连接
      test-while-idle: true
      # 不检测池中连接的可用性(默认false)
      # 导致的问题是,若项目作为服务端,数据库连接被关闭时,客户端调用就会出现大量的timeout
      test-on-borrow: false
      #在返回连接池之前是否验证对象
      test-on-return: false
      #打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
      #第三发连接池在使用的时候,获取到Connection后,使用完毕,调用关闭方法,并没有将Connection关闭,只是放回到连接池中
      #如果调用这个方法,而没有手动关闭PreparedStatement,就可能造成内存溢出,但是JDK1.7实现了AutoCloseable接口,就不需要关闭了
      pool-prepared-statements: false
      max-pool-prepared-statement-per-connection-size: 20
      # connection-properties:
      use-unfair-lock: true
  quartz:
    #相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            # 集群名,区分同一系统的不同实例,若使用集群功能,则每一个实例都要使用相同的名字
            instanceName: clusteredScheduler
            # 若是集群下,每个instanceId必须唯一
            instanceId: AUTO
          threadPool:
            #一般使用这个便可
            class: org.quartz.simpl.SimpleThreadPool
            #线程数量,不会动态增加
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
          jobStore:
            #选择JDBC的存储方式
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            useProperties: false
            isClustered: true
            clusterCheckinInterval: 15000
    job-store-type: jdbc
    #是否等待任务执行完毕后,容器才会关闭
    wait-for-jobs-to-complete-on-shutdown=false
    #配置的job是否覆盖已经存在的JOB信息
    overwrite-existing-jobs: false

1. 讲一下最后两个配置

  1. wait-for-jobs-to-complete-on-shutdown:Quartz默认false,是否等待任务运行完毕后关闭Spring容器,若是为false的情况下,可能出现**java.lang.IllegalStateException: JobStore is shutdown - aborting retry**异常,推荐开启。
  2. overwrite-existing-jobs:这个是配置文件的job是否会覆盖数据库正在运行的job。quartz启动之后,会以数据库的为准,若该属性为false,则配置文件修改后不会起作用。

5.Quartz的核心元素

Quartz调度依靠的三大核心元素就是:Scheduler、Trigger、Job。

1.job(任务)

作用:具体要执行的业务逻辑,比如:发送短信、发送邮件、访问数据库、同步数据等。2. 2.Trigger(触发器)

作用:用来定义Job(任务)触发条件、触发时间,触发间隔,终止时间等。
四大类型:SimpleTrigger、CornTrigger、DateIntervalTrigger、NthIncludedDayTrigger。

3. scheduler(调度器)

作用:Scheduler启动Trigger去执行Job。
类型:Scheduler由scheduler工厂创建:DirectSchedulerFactory 或者 StdSchedulerFactory。
第二种工厂StdSchedulerFactory使用较多,因为 DirectSchedulerFactory 使用起来不够方便,需要作许多详细的手工编码设置。
Scheduler 主要有三种:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。

6. job

实现 job类 重写 execute方法

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class EquipmentJob implements Job {

    public EquipmentJob() {
    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        System.out.println("-----------定时更新设备工作时间开始------------");
        EquipmentServer equipmentServer = SpringUtil.getBean(EquipmentServer.class);
        if (!equipmentServer.workingHours()) {
            equipmentServer.workingHours();
        }
        System.out.println("-----------定时更新设备工作时间结束------------");
    }
}

注解说明

@PersistJobDataAfterExecution:告诉Quartz在成功执行了Job实现类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据,使得该JobDetail实例在下一次执行的时候,JobDataMap中是更新后的数据,而不是更新前的旧数据

@DisallowConcurrentExecution:告诉Quartz不要并发地执行同一个JobDetail实例。

package com.spsw.erp.config;


import com.spsw.erp.job.*;
import com.spsw.erp.job.project.QualificationStartJob;
import com.spsw.erp.quartz.DynamicSchedulerFactory;
import org.quartz.Scheduler;
import org.quartz.Trigger;
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.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;

@Configuration
public class SchedulerConfig {

	//调度器
    @Bean
    public SchedulerFactoryBean getSchedulerFactoryBean(@Qualifier("dataSource") DataSource dataSource) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setAutoStartup(true);
        schedulerFactoryBean.setDataSource(dataSource);
        schedulerFactoryBean.setTriggers(configTriggersList());
        return schedulerFactoryBean;
    }

    @Bean
    public DynamicSchedulerFactory dynamicSchedulerFactory(Scheduler scheduler) {
        DynamicSchedulerFactory dynamicSchedulerFactory = new DynamicSchedulerFactory();
        dynamicSchedulerFactory.setScheduler(scheduler);
        return dynamicSchedulerFactory;
    }


    private Trigger[] configTriggersList() {
        return new Trigger[]{
                getQualificationJobDetailTrigger().getObject() 
        };
    }
    //gudin
    @Bean
    public JobDetailFactoryBean getQualificationJobDetail() {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(QualificationStartJob.class);
        factoryBean.setDurability(true);
        return factoryBean;
    }
	// cron 触发器
    @Bean
    public CronTriggerFactoryBean getQualificationJobDetailTrigger() {
        JobDetailFactoryBean jobDetailFactoryBean =getQualificationJobDetail();
        CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
        factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
//        String cron = "0 0 1 * * ?";//每天凌晨1点
         String cron = "0 0/5 * * * ?";//每5分钟
//        String cron = "0 0 */1 * * ?";//每个小时
//        String cron = "*/5 * * * * ?";//每5秒
        factoryBean.setCronExpression(cron);
        factoryBean.setMisfireInstruction(2);
        return factoryBean;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值