• Quartz/Spring整合quartz


    来自 https://segmentfault.com/a/1190000009972187

    第一章:课程介绍

    1-1 初识Quartz

    Quartz概要

    OpenSymphony提供的强大的开源任务调度框架
    官网:http://www.quartz-scheduler.org
    纯Java实现,精细控制排程

    Quartz特点

    强大的调度功能
    灵活的应用方式
    分布式和集群能力

    Quartz的设计模式

    Builder模式
    Factory模式
    组件模式
    链式写法

    Quartz三个核心概念

    调度器:将任务和触发器一一对应
    任务:需要做什么,值Service
    触发器:定义时间

    Quartz体系结构

    JobDetail
    trigger
        SimpleTrigger
        CronTrigger
    scheduler
        start
        stop
        pause
        resume

    示意图

    clipboard.png

    Quartz重要组成

    Job
    JobDetail
    JobBuilder
    JobStore
    Trigger
    TriggerBuilder
    ThreadPool
    Scheduler
    Calendar:一个Trigger可以和多个Calendar关联,以排除或包含某些时间点
    监听器
        JobListener
        TriggerListener
        SchedulerListener

    第二章:Quartz详解

    2-1 第一个Quartz程序

    准备工作

    建立Maven项目工程
    引入Quartz包

    编写第一个Quartz任务

    让任务每隔两秒打印一次hellworld

    代码演示

    1.编写任务类

    package com.myimooc.helloquartz.one;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    
    /**
     * 编写 自定义任务
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloJob implements Job{
        
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Exec Time Is : " + sf.format(date));
            
            // 编写具体的业务逻辑
            System.out.println("Hello World!");
        }
        
    }

    2.编写任务调度类

    package com.myimooc.helloquartz.one;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;
    
    /**
     * 编写 任务调度类
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloScheduler {
        
        public static void main(String[] args) throws SchedulerException {
            
            // 创建一个 JobDetail 实例,将该实例与 HelloJob 实例绑定
            JobDetail jobDeatil = JobBuilder.newJob(HelloJob.class)
                    .withIdentity("myjob", "jobgroup1")// 定义标识符
                    .build();
            
            System.out.println("jobDetail's name : " + jobDeatil.getKey().getName());
            System.out.println("jobDetail's group : " + jobDeatil.getKey().getGroup());
            System.out.println("jobDetail's jobClass : " + jobDeatil.getJobClass().getName());
            
            // 创建一个 Trigger 实例,定义该 job 立即执行,并且每隔两秒重复执行一次,直到永远
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("myTrigger","trigroup1")// 定义标识符
                    .startNow()// 定义立即执行
                    .withSchedule(SimpleScheduleBuilder
                            .simpleSchedule()
                            .withIntervalInSeconds(2)
                            .repeatForever())// 定义执行频度
                    .build();
            
            // 创建 Scheduler 实例
            SchedulerFactory sfact = new StdSchedulerFactory();
            Scheduler scheduler = sfact.getScheduler();
            
            // 绑定 JobDetail 和 trigger
            scheduler.scheduleJob(jobDeatil, trigger);
            
            // 执行任务
            scheduler.start();
            
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Time Is : " + sf.format(date));
        }
        
    }

    2-2 浅谈Job&JobDetail

    Job定义

    实现业务逻辑的任务接口

    浅谈Job

    Job接口非常容易实现,只有一个execute方法,类似TimerTask的run方法,在里面编写业务逻辑
    Job接口源码
    public interface Job {
        void execute(JobExecutionContext context) throws JobExecutionException;
    }

    Job实例在Quartz中的生命周期

    每次调度器执行job时,它在调用execute方法前会创建一个新的job实例
    当调用完成后,关联的job对象实例会被释放,释放的实例会被垃圾回收机制回收

    浅谈JobDetail

    JobDetail为Job实例提供了许多设置属性,以及JobDetailMap成员变量属性,它用来存储特定Job实例的状态信息,调度器需要借助JobDetail对象来添加Job实例。

    JobDetail属性

    name:任务名称
    group:任务所属组
    jobClass:任务实现类
    jobDataMap:传参的作用
    

    2-3 浅谈JobExecutionContext&JobDataMap(上)

    JobExecutionContext是什么

    Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法;
    Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。

    JobDataMap是什么

    在进行任务调度时JobDataMap存储在JobExecutionContext中,非常方便获取
    JobDataMap可以用来装载任务可序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它
    JobDataMap实现了JDK的Map接口,并且添加了一些非常方便的方法用来存取基本数据类型
    

    2-4 浅谈JobExecutionContext&JobDataMap(下)

    获取JobDataMap的两种方式

    从Map中直接获取
    Job实现类中添加setter方法对应JobDataMap的键值
    (Quartz框架默认的JobFactory实现类在初始化job实例对象时会自动地调用这些setter方式)

    代码演示

    1.HelloScheduler类改造

    package com.myimooc.helloquartz.two;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;
    
    /**
     * 编写 任务调度类
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloScheduler {
        
        public static void main(String[] args) throws SchedulerException {
            
            // 创建一个 JobDetail 实例,将该实例与 HelloJob 实例绑定
            JobDetail jobDeatil = JobBuilder.newJob(HelloJob.class)
                    .withIdentity("myjob", "jobgroup1")// 定义标识符
                    .usingJobData("message", "hello myjob1")// 传入自定义参数
                    .usingJobData("floatJobValue", 3.14F)// 传入自定义参数
                    .build();
            
            System.out.println("jobDetail's name : " + jobDeatil.getKey().getName());
            System.out.println("jobDetail's group : " + jobDeatil.getKey().getGroup());
            System.out.println("jobDetail's jobClass : " + jobDeatil.getJobClass().getName());
            
            // 创建一个 Trigger 实例,定义该 job 立即执行,并且每隔两秒重复执行一次,直到永远
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("myTrigger","trigroup1")// 定义标识符
                    .usingJobData("message", "hello mytrigger1")// 传入自定义参数
                    .usingJobData("doubleTriggerValue", 2.0D)// 传入自定义参数
                    .startNow()// 定义立即执行
                    .withSchedule(SimpleScheduleBuilder
                            .simpleSchedule()
                            .withIntervalInSeconds(2)
                            .repeatForever())// 定义执行频度
                    .build();
            
            // 创建 Scheduler 实例
            SchedulerFactory sfact = new StdSchedulerFactory();
            Scheduler scheduler = sfact.getScheduler();
            
            // 绑定 JobDetail 和 trigger
            scheduler.scheduleJob(jobDeatil, trigger);
            
            // 执行任务
            scheduler.start();
            
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Time Is : " + sf.format(date));
        }
        
    }

    2.HelloJob类改造

    package com.myimooc.helloquartz.two;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.Job;
    import org.quartz.JobDataMap;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.quartz.JobKey;
    import org.quartz.TriggerKey;
    
    /**
     * 编写 自定义任务
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloJob implements Job{
        
        // 方式二:getter和setter获取
        // 成员变量 与 传入参数的key一致
        private String message;
        private Float floatJobValue;
        private Double doubleTriggerValue;
        
        public String getMessage() {
            return message;
        }
        public void setMessage(String message) {
            this.message = message;
        }
        public Float getFloatJobValue() {
            return floatJobValue;
        }
        public void setFloatJobValue(Float floatJobValue) {
            this.floatJobValue = floatJobValue;
        }
        public Double getDoubleTriggerValue() {
            return doubleTriggerValue;
        }
        public void setDoubleTriggerValue(Double doubleTriggerValue) {
            this.doubleTriggerValue = doubleTriggerValue;
        }
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Exec Time Is : " + sf.format(date));
            
            // 编写具体的业务逻辑
            //System.out.println("Hello World!");
            
            JobKey key = context.getJobDetail().getKey();
            System.out.println("My name and group are : " + key.getName() + " : " + key.getGroup());
            
            TriggerKey trkey = context.getTrigger().getKey();
            System.out.println("My Trigger name and group are : " + trkey.getName() + " : " + trkey.getGroup());
            
            // 方式一:Map中直接  获取自定义参数
            JobDataMap jdataMap = context.getJobDetail().getJobDataMap();
            JobDataMap tdataMap = context.getTrigger().getJobDataMap();
            String jobMsg = jdataMap.getString("message");
            Float jobFloatValue = jdataMap.getFloat("floatJobValue");
            
            String triMsg = tdataMap.getString("message");
            Double triDoubleValue = tdataMap.getDouble("doubleTriggerValue");
            
            System.out.println("jobMsg is : " + jobMsg);
            System.out.println("jobFloatValue is : " + jobFloatValue);
            System.out.println("triMsg is : " + triMsg);
            System.out.println("triDoubleValue is : " + triDoubleValue);
            
            // 方式一:Map中直接获取 获取自定义参数
            JobDataMap jobDataMap = context.getMergedJobDataMap();
            jobMsg = jobDataMap.getString("message");
            jobFloatValue = jobDataMap.getFloat("floatJobValue");
            
            triMsg = jobDataMap.getString("message");
            triDoubleValue = jobDataMap.getDouble("doubleTriggerValue");
            
            System.out.println("jobMsg is : " + jobMsg);
            System.out.println("jobFloatValue is : " + jobFloatValue);
            System.out.println("triMsg is : " + triMsg);
            System.out.println("triDoubleValue is : " + triDoubleValue);
            
            // 方式二:getter和setter获取
            System.out.println("message is : " + this.message);
            System.out.println("jobFloatValue is : " + this.floatJobValue);
            System.out.println("triDoubleValue is : " + this.doubleTriggerValue);
        }
        
    }

    2-5 浅谈Trigger

    Trigger是什么

    Quartz中的触发器用来告诉调度程序作业什么时候触发
    即Trigger对象时用来触发执行Job的

    Quartz框架中的Trigger示意图

    clipboard.png

    触发器通用属性

    JobKey:表示job实例的标识,触发器被触发时,该指定的job实例会执行
    StartTime:表示触发器的时间表首次被触发的时间,它的值的类型是Java.util.Date
    EndTime:指定触发器的不再被触发的时间,它的值的类型是Java.util.Date

    代码演示

    1.HelloJob类改造

    package com.myimooc.helloquartz.three;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.quartz.JobKey;
    import org.quartz.Trigger;
    
    /**
     * 自定义任务  触发器通用属性
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloJob implements Job{
        
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Exec Time Is : " + sf.format(date));
            
            Trigger currentTrigger = context.getTrigger();
            System.out.println("Start Time Is : " + sf.format(currentTrigger.getStartTime()));
            System.out.println("End Time Is : " + sf.format(currentTrigger.getEndTime()));
            
            JobKey jobKey = currentTrigger.getJobKey();
            System.out.println("JobKey info : " + " jobName : " + jobKey.getName()
                    + " jobGroup : " + jobKey.getGroup());
        }
        
    }

    2.HelloScheduler类改造

    package com.myimooc.helloquartz.three;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;
    
    /**
     * 任务调度类  触发器通用属性
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloScheduler {
        
        public static void main(String[] args) throws SchedulerException {
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Time Is : " + sf.format(date));
            
            // 创建一个 JobDetail 实例,将该实例与 HelloJob 实例绑定
            JobDetail jobDeatil = JobBuilder.newJob(HelloJob.class)
                    .withIdentity("myjob", "jobgroup1")// 定义标识符
                    .build();
            
            // 获取距离当前时间3秒后的时间
            date.setTime(date.getTime() + 3000);
            // 获取距离当前时间6秒后的时间
            Date endDate = new Date();
            endDate.setTime(endDate.getTime() + 6000);
            
            // 创建一个 Trigger 实例,定义该 job 立即执行,并且每隔两秒重复执行一次,直到永远
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("myTrigger","trigroup1")// 定义标识符
                    .startAt(date)// 定义3秒后执行
                    .endAt(endDate)// 定义6秒后结束
                    .withSchedule(SimpleScheduleBuilder
                            .simpleSchedule()
                            .withIntervalInSeconds(2)
                            .repeatForever())// 定义执行频度
                    .build();
            
            // 创建 Scheduler 实例
            SchedulerFactory sfact = new StdSchedulerFactory();
            Scheduler scheduler = sfact.getScheduler();
            
            // 绑定 JobDetail 和 trigger
            scheduler.scheduleJob(jobDeatil, trigger);
            
            // 执行任务
            scheduler.start();
        }
        
    }

    2-6 SimpleTrigger

    SimpleTrigger的作用

    在一个指定时间段内执行一次作业任务
    或是在指定的时间间隔内多次执行作业任务

    需要注意的点

    重复次数可以为0,正整数或是SimpleTrigger.REPEAT_INDEFINITELY常量值
    重复执行间隔必须为0或长整数
    一旦被指定了endTime参数,那么它会覆盖重复次数参数的效果

    代码演示

    1.HelloJob类改造

    package com.myimooc.helloquartz.four;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    
    /**
     * SimpleTrigger 演示
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloJob implements Job{
        
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Exec Time Is : " + sf.format(date));
            
            System.out.println("Hello World!");
        }
        
    }

    2.HelloScheduler类改造

    package com.myimooc.helloquartz.four;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.SimpleTrigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;
    
    /**
     * SimpleTrigger 演示
     * @author ZhangCheng on 2017-06-26
     *
     */
    public class HelloScheduler {
        
        public static void main(String[] args) throws SchedulerException {
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Time Is : " + sf.format(date));
            
            // 创建一个 JobDetail 实例,将该实例与 HelloJob 实例绑定
            JobDetail jobDeatil = JobBuilder.newJob(HelloJob.class)
                    .withIdentity("myjob", "jobgroup1")// 定义标识符
                    .build();
            
            // 获取距离当前时间4秒钟之后的具体时间
            date.setTime(date.getTime() + 4000);
            // 获取距离当前时间6秒钟之后的具体时间
            Date endDate = new Date();
            endDate.setTime(endDate.getTime() + 6000);
            
            // 距离当前时间4秒钟后首次执行任务,之后每隔2秒钟重复执行一次任务
            // 知道距离当前时间6秒钟之后为止
            SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder
                    .newTrigger()
                    .withIdentity("myTrigger","trigroup1")// 定义标识符
                    .startAt(date)
                    .endAt(endDate)
                    .withSchedule(SimpleScheduleBuilder
                            .simpleSchedule()
                            .withIntervalInSeconds(2)
                            .withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY))
                    .build();
             
            // 创建 Scheduler 实例
            SchedulerFactory sfact = new StdSchedulerFactory();
            Scheduler scheduler = sfact.getScheduler();
            scheduler.scheduleJob(jobDeatil, trigger);
            scheduler.start();
        }
        
    }

    2-7 CronTrigger

    CronTrigger的作用

    基于日历的作业调度器,而不是像SimpleTrigger那样精确指定间隔时间,比SimpleTrigger更常用

    Cron表达式

    用于配置CronTrigger实例
    是由7个子表达式组成的字符串,描述了时间表的详细信息
    格式:[秒][分][小时][日][月][周][年]

    Cron表达式特殊字符意义对应表

    clipboard.png

    特殊符号解释

    clipboard.png

    Cron表达式举例

    clipboard.png

    Cron表达式小提示

    L和W可以一组合使用
    周字段英文字母不区分大小写即MON与mon相同
    利用工具,在线生成
    

    2-8 浅谈Scheduler

    Scheduler工厂模式

    所有的Scheduler实例应该由SchedulerFactory来创建

    SchedulerFactory类图

    clipboard.png

    回顾Quartz三个核心概念

    调度器
    任务
    触发器

    示意图

    clipboard.png

    Scheduler的创建方式

    clipboard.png

    StdSchedulerFactory

    使用一组参数(Java.util.Properties)来创建和初始化Quartz调度器
    配置参数一般存储在quartz.properties中
    调用getScheduler方法就能创建和初始化调度器对象

    Scheduler的主要函数

    // 绑定 jobDetail 和 trigger,将它注册进 Scheduler 当中
    Date scheduleJob(JobDetail jobDetail, Trigger trigger)
    // 启动 Scheduler
    void start()
    // 暂停 Scheduler
    void standby()
    // 关闭 Scheduler
    void shutdown()
    

    2-9 QuartzProperties文件

    quartz.properties组成部分

    调度器属性
    线程池属性
    作业存储设置
    插件配置

    调度器属性

    clipboard.png

    线程池属性

    threadCount:工作线程数量
    threadPriority:工作线程优先级
    org.quartz.threadPool.class:配置线程池实现类

    作业存储设置

    描述了在调度器实例的生命周期中,Job和Trigger信息是如何被存储的

    插件配置

    满足特定需求用到的Quartz插件的配置
    

    第三章:Spring、Quartz大合体

    3-1 搭建工程

    基于Maven创建一个简单的SpringMVC工程,学习时,使用springboot框架。

    项目POM文件

    <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>com.myimooc</groupId>
      <artifactId>springquartz</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>springquartz</name>
      <url>http://maven.apache.org</url>
    
      <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.1.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
        
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
            
            <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.3.0</version>
            </dependency>
            
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
      
      <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        
    </project>

    项目目录结构

    clipboard.png

    3-2 Quartz和Spring大合体

    使用Quartz配置作业两种方式

    MethodInvokingJobDetailFactoryBean
    JobDetailFactoryBean

    方式一:使用MethodInvokingJobDetailFactoryBean

    1.调用myBean的printMessage方法

    clipboard.png

    2.MyBean类

    clipboard.png

    方式二:使用JobDetailFactoryBean

    1.需要给作业传递数据,想要更加灵活的话就是用这种方式

    clipboard.png

    2.FirstScheduleJob类

    clipboard.png

    3.AnotherBean类

    clipboard.png

    代码演示:

    演示说明:教学基于xml进行配置,学习时基于javaconfig进行配置。

    1.编写MyBean类

    package com.myimooc.springquartz.quartz;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.springframework.stereotype.Component;
    
    /**
     * 方式一:使用MethodInvokingJobDetailFactoryBean 演示
     * @author ZhangCheng on 2017-06-28
     *
     */
    @Component
    public class MyBean {
        
        public void printMessage(){
            
            // 打印当前的执行时间,格式为2017-01-01 00:00:00
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            
            System.out.println("MyBean Executes!" + sf.format(date));
        }
        
    }

    2.编写AnotherBean类

    package com.myimooc.springquartz.quartz;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.springframework.stereotype.Component;
    
    /**
     * 方式二:使用JobDetailFactoryBean 演示
     * @author ZhangCheng on 2017-06-28
     *
     */
    @Component
    public class AnotherBean {
        
        public void printAnotherMessage(){
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            
            System.out.println("I am AnotherBean." + sf.format(date));
        }
        
    }

    3.编写FirstScheduledJob类

    package com.myimooc.springquartz.quartz;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    /**
     * 方式二:使用JobDetailFactoryBean 演示
     * @author ZhangCheng on 2017-06-28
     *
     */
    public class FirstScheduledJob extends QuartzJobBean {
        
        private AnotherBean anotherBean;
        
        public void setAnotherBean(AnotherBean anotherBean) {
            this.anotherBean = anotherBean;
        }
    
        @Override
        protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
            Date date = new Date();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            
            System.out.println("FirstScheduledJob Excutes!" + sf.format(date));
            this.anotherBean.printAnotherMessage();
        }
    
    }

    4.编写QuartzConfig类

    package com.myimooc.springquartz.config;
    
    import org.quartz.JobDataMap;
    import org.quartz.JobDetail;
    import org.quartz.Trigger;
    import org.springframework.beans.factory.annotation.Autowired;
    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.MethodInvokingJobDetailFactoryBean;
    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
    
    import com.myimooc.springquartz.quartz.AnotherBean;
    import com.myimooc.springquartz.quartz.FirstScheduledJob;
    import com.myimooc.springquartz.quartz.MyBean;
    
    /**
     * Quartz 配置类
     * @author ZhangCheng on 2017-06-28
     *
     */
    @Configuration
    public class QuartzConfig {
        
        @Autowired
        private MyBean myBean;
        
        @Autowired
        private AnotherBean anotherBean;
        
        /**
         * 方式一:使用MethodInvokingJobDetailFactoryBean
         * @return
         */
        @Bean
        public MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean(){
            MethodInvokingJobDetailFactoryBean mb = new MethodInvokingJobDetailFactoryBean();
            mb.setTargetObject(myBean);// 指定要运行的类
            mb.setTargetMethod("printMessage");// 指定要允许类中的那个方法
            return mb;
        }
        
        /**
         * 方式二:使用JobDetailFactoryBean
         * @return
         */
        @Bean
        public JobDetailFactoryBean jobDetailFactoryBean(){
            JobDetailFactoryBean  jb= new JobDetailFactoryBean();
            jb.setJobClass(FirstScheduledJob.class);// 指定要运行的类
            JobDataMap jobDataMap = new JobDataMap();
            jobDataMap.put("anotherBean", anotherBean);
            
            jb.setJobDataMap(jobDataMap);// 设置传入自定义参数
            jb.setDurability(true);
            return jb;
        }
        
        /**
         * 配置 SimpleTriggerFactoryBean
         * @return
         */
        @Bean
        public SimpleTriggerFactoryBean simpleTriggerFactoryBean(){
            SimpleTriggerFactoryBean sb = new SimpleTriggerFactoryBean();
            sb.setJobDetail(methodInvokingJobDetailFactoryBean().getObject());// 设置需要绑定的 jobDetail
            sb.setStartDelay(1000L);// 距离当前时间1秒后执行
            sb.setRepeatInterval(2000L);// 之后每隔2秒执行一次
            return sb;
        }
        
        /**
         * 配置 SimpleTriggerFactoryBean
         * @return
         */
        @Bean
        public CronTriggerFactoryBean cronTriggerFactoryBean(){
            CronTriggerFactoryBean cb = new CronTriggerFactoryBean();
            cb.setJobDetail(jobDetailFactoryBean().getObject());// 设置需要绑定的 jobDetail
            cb.setStartDelay(1000L);// 距离当前时间1秒后执行
            cb.setCronExpression("0/5 * * ? * *");// 设置 Cron 表达式,之后每隔5秒执行一次
            return cb;
        }
        
        /**
         * 配置 SchedulerFactoryBean
         * @return
         */
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean(){
            SchedulerFactoryBean sb= new SchedulerFactoryBean();
            // 配置 JobDetails
            JobDetail[] jobDetails = new JobDetail[2];
            jobDetails[0] = methodInvokingJobDetailFactoryBean().getObject();
            jobDetails[1] = jobDetailFactoryBean().getObject();
            sb.setJobDetails(jobDetails);
            
            // 配置 Trigger
            Trigger[] triggers = new Trigger[2];
            triggers[0] = simpleTriggerFactoryBean().getObject();
            triggers[1] = cronTriggerFactoryBean().getObject();
            sb.setTriggers(triggers);
            return sb;
            
        }
    }

    第四章:课程总结

    4-1 课程总结

    课程回顾

     
    Timer
    Quartz
    Quartz&Spring融合

    第五章:Spring boot QuartzConfig另种写法

    从上面的例子QuartzConfig中看出autowired中注入了MyBean和AnotherBean。其实可以不用写这个,在方法中写也一样,因为方法中也是注入关系

    上面的图就列举了方法注入,同理可得其他,只是方法名称不能乱写,不要一一对应。

    下面就列举了2个不同的实例job。

    分别创建了2个job,名称分别为JobOneService和JobTwoService

    创建QuartzConfig.class

    @Configuration
    public class QuartzConfig
    {
        @Bean("jobOneDetail")
        public MethodInvokingJobDetailFactoryBean jobOneDetailFactoryBean(JobOneService jobOneService)
        {
            MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
            jobDetail.setTargetObject(jobOneService);
            // 是否并发执行
            jobDetail.setConcurrent(true);
            //需要执行的方法-对应JobOneService的方法
            jobDetail.setTargetMethod("task");
            return jobDetail;
        }
    
        @Bean("jobOneTrigger")
        public SimpleTriggerFactoryBean jobOneTrigger(JobDetail jobOneDetail)
        {
            SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
            trigger.setJobDetail(jobOneDetail);
            trigger.setRepeatCount(0);
            return trigger;
        }
    
        @Bean("jobTwoDetail")
        public MethodInvokingJobDetailFactoryBean jobTwoDetailFactoryBean(JobTwoService jobTwoService)
        {
            MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
            jobDetail.setTargetObject(jobTwoService);
            // 是否并发执行
            jobDetail.setConcurrent(true);
            //需要执行的方法-对应jobTwoService的方法
            jobDetail.setTargetMethod("task");
            return jobDetail;
        }
    
    
        @Bean("jobTwoTrigger")
        public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetail jobTwoDetail)
        {
            CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
            trigger.setJobDetail(jobTwoDetail);
            // cron表达式,每过10秒执行一次
            trigger.setCronExpression("0/5 * * * * ?");
            return trigger;
        }
    
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean(Trigger jobOneTrigger, Trigger jobTwoTrigger)
        {
            SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
            // 延时启动,应用启动5秒后
            schedulerFactoryBean.setStartupDelay(5);
            schedulerFactoryBean.setTriggers(jobOneTrigger, jobTwoTrigger);
            return schedulerFactoryBean;
        }
    }

    1、MethodInvokingJobDetailFactoryBean setTargetMethod 这个就是执行的方法,没有这个都不知道执行什么。

    2、看上面的Bean里面的名称都是一一对应的

    @Component
    @EnableScheduling
    public class JobOneService
    {
        public void task()
        {
            System.out.println("JobOneService" + new Date());
        }
    }
    
    @Component
    @EnableScheduling
    public class JobTwoService
    {
        public void task()
        {
            System.out.println("JobTwoService" + new Date());
        }
    }

    将任务进行配置,项目启动就会开始执行了。

     
  • 相关阅读:
    jenkins初始化启动报错导致进入web页面无法安装插件
    redis5.0.7集群搭建
    搭建redis哨兵模式
    Linux服务器安装python3.6
    MySQL绿色版安装
    OSChina中远程GIT仓库同步探索
    Android坡度计
    利用ADB获取APP资源
    实现两台路由器无线桥接
    新体能评定软件开发总结(一)
  • 原文地址:https://www.cnblogs.com/zjtao/p/12683790.html
Copyright © 2020-2023  润新知