目录

一、Quartz介绍

二、Quartz的组成

三、使用java实现一个简单的Quartz例子

四、使用Springboot整合Quartz定时任务框架

五、使用Springboot+mybatis整合Quartz定时任务框架实现定时向数据库插入一条数据

六、总结

七、参考资料


一、Quartz介绍

quartz是一种基于java实现的任务调度框架,可以定时自动的执行你想要执行的任何任务。

quartz官网:http://www.quartz-scheduler.org/

 

二、Quartz的组成

任务Job(你要做什么事?)

job就是你想要实现的任务类,每一个job必须实现org.quartz.job接口。

触发器Trigger(你什么时候去做?)

Trigger为你执行任务的触发器,比如你想每天定时3点发送一份统计邮件,Trigger将会设置3点进行执行该任务。

调度器Scheduler(你什么时候需要做什么事?)

Scheduler为任务的调度器,它会将任务job及触发器Trigger整合起来,负责基于Trigger设定的时间来执行Job。

 

 

三、使用java实现一个简单的Quartz例子

1、新建一个maven项目,并引入Quartz依赖    https://mvnrepository.com/search?q=quartz

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Quartz</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!--核心包-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
        </dependency>
        <!--工具-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>


</project>

 

2、编写一个Job类,用来编写定时任务要做什么

package quartz.job;

import javafx.scene.chart.PieChart;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.text.SimpleDateFormat;
import java.util.Date;

public class HelloJob implements Job {
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //输出当前时间
        Date date=new Date();
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString=dateFormat.format(date);
        //工作内容
        System.out.println("执行定时任务,时间是:"+dateString);
    }
}

 

3、编写触发器和调度器

package quartz.job;

import org.quartz.*;

import org.quartz.impl.StdSchedulerFactory;

public class HelloSchedulerDemo {
    public static void main(String[] args) throws Exception{
        //1、调度器(Schedular),从工厂中获取调度实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler= StdSchedulerFactory.getDefaultScheduler();
        //2、任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(HelloJob.class) //加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
                .withIdentity("job1","group1") //参数1:任务的名称(唯一实例);参数2:任务组的名称
               .build();
        //3、触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1","group1") //参数1:触发器的名称(唯一实例);参数2:触发器组的名称
                .startNow() //马上启动触发器
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)) //每5秒执行一次
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

 

执行结果:

Java定时器表达式详解 java定时器quartz的配置含义_Java定时器表达式详解

 

四、使用Springboot整合Quartz定时任务框架

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>Quartz</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>erp</name>
    <description>Quartz for Spring Boot</description>


    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--导入html依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--核心包-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--工具-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
           <!-- <scope>compile</scope>-->
        </dependency>
        <!--添加Scheduled坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!--Spring tx 坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
    </dependencies>
</project>

 

2、 job类

package quartz.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

public class QuartzDemo implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Execute..."+new Date());
    }
}

3、配置类,配置触发器与任务调度器

package quartz.job;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

/**
 * Quartz配置类
 */
@Configuration
public class QuartzConfig {
    /**
     * 1、创建Job对象
     */
    @Bean
    public JobDetailFactoryBean jobDetailFactoryBean(){
        JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();
        //关联我们自己的Job类
        factoryBean.setJobClass(QuartzDemo.class);
        return factoryBean;
    }

    /**
     * 2、创建Trigger对象
     */
    @Bean
    public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        SimpleTriggerFactoryBean factoryBean=new SimpleTriggerFactoryBean();
        //关联JobDetail对象
        factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
        //该参数表示一个执行的毫秒数
        factoryBean.setRepeatInterval(2000); //每隔2秒执行一次
        //重复次数
        factoryBean.setRepeatCount(5);
        return factoryBean;
    }

    /**
     * 3、创建Scheduler
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){
        SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
        //关联trigger
        factoryBean.setTriggers(simpleTriggerFactoryBean.getObject());
        return factoryBean;
    }
}

 

4、启动类

package quartz.job;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class QuartzApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(QuartzApplication.class, args);
    }
}

 

执行结果:

每隔2秒执行一次执行5次

Java定时器表达式详解 java定时器quartz的配置含义_xml_02

 

五、使用Springboot+mybatis整合Quartz定时任务框架实现定时向数据库插入一条数据

 

IDEA项目目录结构

Java定时器表达式详解 java定时器quartz的配置含义_xml_03

 

 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>Quartz</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>erp</name>
    <description>Quartz for Spring Boot</description>


    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--导入html依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--核心包-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--工具-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
           <!-- <scope>compile</scope>-->
        </dependency>
        <!--添加Scheduled坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!--Spring tx 坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>
</project>

application.yml

server:
  port: 8080
spring:
  datasource:
    name: mydb
    url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Hongkong
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: classpath:Mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径
  type-aliases-package: com.springboot.quartz.Entity # 注意:对应实体类的路径

 

QuartzDemoMapper类
package com.springboot.quartz.Mapper;

import com.springboot.quartz.Entity.QuartzDemo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;

@Mapper
@Component
public interface QuartzDemoMapper {
    @Insert("insert into QuartzDemo (op_time,operation) values (#{op_time},#{operation})")
    void insertQuartzDemo(java.sql.Timestamp op_time,String operation);

    @Insert("insert into QuartzDemo_1 (operation) values (#{operation})")
    void insertQuartzDemo_1(String operation);

   /* // @Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中
    QuartzDemo insertQuartzDemo(@Param("o_ptime") java.sql.Timestamp op_time, @Param("operation") String operation);*/
}

 

QuartzDemoService类
package com.springboot.quartz.Service;

import com.springboot.quartz.Mapper.QuartzDemoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class QuartzDemoService {
    @Autowired
    private QuartzDemoMapper quartzDemoMapper;

    public void insertQuartzDemo(java.sql.Timestamp op_time,String operation){
        quartzDemoMapper.insertQuartzDemo(op_time,operation);
    }

    public void insertQuartzDemo_1(String operation){
        quartzDemoMapper.insertQuartzDemo_1(operation);
    }
}

Job类

package com.springboot.quartz.job;

import com.springboot.quartz.Service.QuartzDemoService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class QuartzDemoJob implements Job {
    static int i = 0;
    @Autowired
    private QuartzDemoService quartzDemoService;

    public QuartzDemoJob() {
    }

    @Autowired   //这里不能直接注入,因为@Autowired注入是Spring的注入,要求注入对象与被注入对象都是在SpringIOC容器中存在,
    public QuartzDemoJob(QuartzDemoService quartzDemoService) {
        this.quartzDemoService = quartzDemoService;
    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String operation = "测试" + i++;
        Date current_time = new Date();
        String strDate = dateToStr(current_time, "yyyy-MM-dd HH:mm:ss");
        java.sql.Timestamp op_time = strToSqlDate(strDate, "yyyy-MM-dd HH:mm:ss");
        quartzDemoService.insertQuartzDemo(op_time, operation);
        System.out.println(op_time + "------" + operation);
    }

    public static String dateToStr(java.util.Date date, String strFormat) {
        SimpleDateFormat sf = new SimpleDateFormat(strFormat);
        String str = sf.format(date);
        return str;
    }

    public static java.sql.Timestamp strToSqlDate(String strDate, String dateFormat) {
        SimpleDateFormat sf = new SimpleDateFormat(dateFormat);
        java.util.Date date = null;
        try {
            date = sf.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        java.sql.Timestamp dateSQL = new java.sql.Timestamp(date.getTime());
        return dateSQL;
    }
}

 编写Job类时要注意,Job类默认是通过AdaptableJobFactory类的createJobInstance通过newInstance()反射进行实例化的,因此没有经过Spring的处理。所以QuartzDemoJob默认是不在SpringIOC容器中的,因此@Autowired注解无法在QuartzDemoJob类中直接注入到SpringIOC容器中。

注意:QuartzDemoJob类中一定要有无参构造方法,否则Job配置类中getObject()这块会报错!

Java定时器表达式详解 java定时器quartz的配置含义_maven_04

Java定时器表达式详解 java定时器quartz的配置含义_Java定时器表达式详解_05

Java定时器表达式详解 java定时器quartz的配置含义_Java定时器表达式详解_06

因此我们需要手动的把QuartzDemoJob类注入到SpringIOC容器中。

编写一个类MyAdaptableJobFactory继承AdaptableJobFactory,覆盖createJobInstance()方法。

MyAdaptableJobFactory类

package com.springboot.quartz.Config;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

@Component("myadaptableJobFactory")  //将该类实例化,使得可以直接用
public class MyadaptableJobFactory extends AdaptableJobFactory {
    //AutowireCapableBeanFactory可以将一个对象添加到Spring IOC容器中,并且完成该对象注入
    @Autowired
    private AutowireCapableBeanFactory autowireCapableBeanFactory;

    //该方法将实例化的任务对象手动的添加到SpringIOC容器中并且完成对象的注入
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object object = super.createJobInstance(bundle);
        //将object对象添加到Spring IOC容器中并完成注入
        this.autowireCapableBeanFactory.autowireBean(object);
        return object;
    }
}
Quartz配置类
package com.springboot.quartz.Config;

import com.springboot.quartz.job.QuartzDemoJob;
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 org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

/**
 * Quartz配置类
 */
@Configuration
public class QuartzConfig {
    /**
     * 1、创建Job对象
     */
    @Bean
    public JobDetailFactoryBean jobDetailFactoryBean(){
        JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();
        //关联我们自己的Job类
        factoryBean.setJobClass(QuartzDemoJob.class);  //QuartzDemoJob的实例化并没有经过Spring的处理,
        // Spring的注入是要求注入的对象和被注入的对象都要在Spring的IOC容器中
        return factoryBean;
    }

    /**
     * 2、创建Trigger对象
     * Cron Trigger
     */
    @Bean
    public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        CronTriggerFactoryBean factoryBean=new CronTriggerFactoryBean();
        //关联JobDetail对象
        factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
       //设置触发时间
        //factoryBean.setCronExpression("0/2 * * * * ?");  //每2秒触发一次, 分钟,小时,天,月,星期
        factoryBean.setCronExpression("0 0-59 0-22 * * ?");  //在每天0-22点期间的每1分钟触发
        return factoryBean;
    }

    /**
     * 3、创建Scheduler
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean, MyadaptableJobFactory myadaptableJobFactory){
        SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
        //关联trigger
        factoryBean.setTriggers(cronTriggerFactoryBean.getObject());
        factoryBean.setJobFactory(myadaptableJobFactory);  //调用myadaptableJobFactory把对象注入到SpringIOC容器中
        return factoryBean;
    }
}

 setCronExpression()方法可以设置定时器触发时间,具体设置规则可以参考下图

Java定时器表达式详解 java定时器quartz的配置含义_xml_07

 

 

启动类

package com.springboot.quartz;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@SpringBootApplication
/*@MapperScan("com.springboot.quartz.Mapper")*/
public class QuartzApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(QuartzApplication.class, args);
    }
}

 

执行结果:

Java定时器表达式详解 java定时器quartz的配置含义_Java定时器表达式详解_08

写入的数据库

Java定时器表达式详解 java定时器quartz的配置含义_spring_09

 

六、总结

quartz定时任务是由Job、Trigger和Scheduler三部分组成。Job里面写定时任务的具体做什么,Trigger设定定时任务的执行时间,Scheduler则负责整个定时任务的调度。java单一使用quartz框架比较简单。如果是Spring配置quartz则要注意Job的注入问题。因为默认Job是由AdaptableJobFactory类中的createJobInstance方法进行实例化因此不会在SpringIOC中的,所以需要覆盖AdaptableJobFactory类中的createJobInstance方法,手动将Job对象注入到SpringIOC容器中。