zoukankan      html  css  js  c++  java
  • 原生quartz、spring整合quartz笔记

     

    首先网络上的很多教程经常有错(信息过载了),很多时候主要原因是版本发生了变化,例如quartz1和2之间还是有不少差别的,导致查找资料的人浪费了不少时间。所以无论教程如何写,都建议读者首先学习官网的教程,如果有一些资料官网没有,例如扩展的东西或者和其他框架整合的东西,再去参考其他资料。

    本文仅为我个人学习记录。

    建议重点参考:

    quartz官网:www.quartz-scheduler.org

    spring framework文档:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#scheduling-quartz

    quartz版本:2.2.1

    spring版本:4.3.7

    JDK:1.7

    原生quartz:

    基本思路:

      通过工厂创建一个Scheduler

      创建一个实现Job接口的实现类(就是要具体做的事情,可以具体调用自己写的service)

        定义一个Job,并绑定我们自己实现Job接口的实现类(例如通过JobBuilder的方式)

      创建Trigger,并设置相关参数,如启动时间等。

      将job和trigger绑定到scheduler对象上,并启动

    简易案例:

    import java.io.File;
    import java.io.IOException;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    
    public class HelloWorld implements Job {
        public void execute(JobExecutionContext context)
            throws JobExecutionException {
    
            File file2 = new File("*****/test/HelloJob1.java");
            if (file2.exists()) {  
                System.out.println("存在文件夹或者文件");  
            } else {  
                try {  
                    file2.createNewFile(); 
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            
        }
        
    }
    //注意以下几个导入很重要
    import
    static org.quartz.DateBuilder.evenMinuteDate; import static org.quartz.JobBuilder.newJob; import static org.quartz.TriggerBuilder.newTrigger; import java.util.Date; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerFactory; import org.quartz.Trigger; import org.quartz.impl.StdSchedulerFactory; public class TestQuartz { public static void main(String[] args) throws Exception { // First we must get a reference to a scheduler SchedulerFactory sf = new StdSchedulerFactory(); Scheduler sched = sf.getScheduler(); // computer a time that is on the next round minute Date runTime = evenMinuteDate(new Date()); // define the job and tie it to our HelloJob class JobDetail job = newJob(HelloWorld.class).withIdentity("job1", "group1").build(); // Trigger the job to run on the next round minute Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build(); // Tell quartz to schedule the job using our trigger sched.scheduleJob(job, trigger); // Start up the scheduler (nothing can actually run until the // scheduler has been started) sched.start(); // wait long enough so that the scheduler as an opportunity to // run the job! try { Thread.sleep(600); // executing... } catch (Exception e) { // } } }

    OK,一个简单的应用就搞定了

    其他关键点(我们可以参考下自己手机上闹钟都有哪些设置)

    设定开始和结束时间:

    quartz提供了一个DataBuilder类,该类中有很多的方法,例如nextGivenSecondDate(Date date, int secondBase),基本通过这个方法可以定义到日历中的任何时间点

    具体还有哪些方法,可以通过API查看:http://www.quartz-scheduler.org/api/2.2.1/index.html

    再通过如下方法设置startAt和endAt,基本上就能实现开始和结束时间

    Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();这里的runTime我们可以定义为指定时间

    Trigger trigger = newTrigger().withIdentity("trigger1", "group1").endAt(runTime).build();

     

    设定重复次数

    SimpleScheduleBuilder类中有一个静态方法simpleSchedule(),通过它创建SimpleScheduleBuilder对象,该对象可以设置重复次数和重复时间点,具体可以看API,以下是举例

    import static org.quartz.SimpleScheduleBuilder.*;

    trigger = newTrigger().withIdentity("trigger2", "group1").startAt(runTime).withSchedule(simpleSchedule().withIntervalInSeconds(10).withRepeatCount(10)).build();//每十秒重复一次,重复10次,总计执行11次

     

    还有一些其他案例,例如:

    trigger = newTrigger().withIdentity("trigger6", "group1").startAt(startTime)
    .withSchedule(simpleSchedule().withIntervalInSeconds(40).repeatForever()).build();//每40秒重复一次,一直重复下去,设定86400秒不就是每天固定时间执行一次了吗?

    其实可选择的方案特别多,包括在某个时间段触发、每个月某日固定时间触发等等,官网上的example基本都有对应的方案,我就不在此穷举了,官网全量包中有,如下是2.2.3的下载地址:http://d2zwv9pap9ylyd.cloudfront.net/quartz-2.2.3-distribution.tar.gz

    如果使用了quartz的時候想要獲取Spring容器中的bean,必須將兩者整合,或者手動調用Spring容器,否則是獲取不到bean的。

    spring和quartz整合

    参考:http://blog.csdn.net/defonds/article/details/49496895和http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/

    思路基本和原生Quartz差不多

    如下代码中写了2个创建job,都有注释

     spring的xml配置文件applicationContext.xml(可以将Quartz配置部分独立出来另写一个xml文件,让后引入到applicationContext.xml中)(我印象中jar中的bean不能通过注解的方式注入,只能是xml方式,如果错误,请指出)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
                                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
        <context:component-scan base-package="com.zml.*" />
        <bean id="dateFormat" class="java.text.SimpleDateFormat">
            <constructor-arg value="yyyy-MM-dd HH:mm:ss" />
        </bean>
    
        <!-- 第一种方式定义job,此方式合适仅仅需要调用特定类对象的某个方法。通过SimpleTriggerFactoryBean创建job(顾名思义,JobDetail的bean工厂的方法反射类,FactoryBean<JobDetail>的实现类),由它的对象调用我们要执行的类的方法 -->
        <bean id="simpleJobDetail"
            class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <property name="targetObject" ref="quartzService" /><!-- 具体要执行的类,此处的quartzService采用注解的方式注入 -->
            <property name="targetMethod" value="printMessage" /><!-- 具体要执行的方法 -->
        </bean>
        <!-- 第一种方式定义简单触发器类 -->
        <bean id="simpleTrigger"
            class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"><!-- 可以看该类源码,都有哪些属性和方法 -->
            <property name="jobDetail" ref="simpleJobDetail" /><!-- 定义触发器触发的job -->
            <!-- <property name="startTime"> 定义触发开始时间
                <bean factory-bean="dateFormat" factory-method="parse">
                    <constructor-arg value="2017-03-25 22:21:00" />
                </bean>
            </property>
             -->
             <property name="startDelay" value="10" />
            <property name="repeatInterval" value="2000" />
        </bean>
    
        <!-- 第二种方式定义job,高级方式,更加灵活,可以通过xml方式为QuartzService2注入属性(包括其他类的对象)等操作。如果仅仅是注入其他service类的对象,基本上第一种方式配合注解也能实现 -->
        <!-- 通过JobDetailFactoryBean创建Job,也是FactoryBean<JobDetail>的实现类. -->
        <bean name="complexJobDetail"
            class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
            <property name="jobClass" value="com.***.service.impl.QuartzService2" /> <!--好像必须得写类路径,不能用ref。注意xml注入一定要写set方法 -->
            <property name="jobDataMap">
                <map>
                    <entry key="sgtPeppers" value-ref="sgtPeppers" /><!-- 设置QuartzService2中的属性sgtPeppers,该属性是一个类对象-->
                    <entry key="timeout" value="5" /><!-- 设置QuartzService2中的属性timeout,该属性是一个int类型 -->
                </map>
            </property>
            <property name="durability" value="true" />
        </bean>
    
        <!-- 第二种方式定义计划触发器 -->
        <!-- Run the job every 5 seconds -->
        <bean id="cronTrigger"
            class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <property name="jobDetail" ref="complexJobDetail" />
            <!--<property name="cronExpression" value="0/5 * * ? * SAT-SUN" /> -->
            <property name="cronExpression" value="0/5 * * ? * *" />
    
        </bean>
        
        <!-- 定义调度类 -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="jobDetails"><!--这个好像可以不用,可以看SchedulerFactoryBean-->
                <list>
                    <ref bean="simpleJobDetail" />
                    <ref bean="complexJobDetail" />
                </list>
            </property>
    
            <property name="triggers">
                <list>
                    <ref bean="simpleTrigger" />
                    <ref bean="cronTrigger" />
                </list>
            </property>
        </bean>
    </beans>
    注:平常我们都是用simpleJobDetail和cronTrigger

    此处附上常见示例:

    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分每分触发 
    0 0/5 14 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发) 
    0 0/5 14,18 * * ? 每天下午的 2点到2点59分(整点开始,每隔5分触发) 
    0 0-5 14 * * ? 每天下午的 2点到2点05分每分触发 
    0 10,44 14 ? 3 WED     3月分每周三下午的 2点10分和2点44分触发 (特殊情况,在一个时间设置里,执行两次或两次以上的情况) 
    0 59 2 ? * FRI    每周5凌晨2点59分触发; 
    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 每月的第三周的星期五开始触发 
    0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次 
    0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节)
     

    各个位置定义参考:https://www.cnblogs.com/skyblue/p/3296350.html 

    QuartzService类:

    package com.***.service.impl;
    
    import java.io.File;
    import java.io.IOException;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service("quartzService")
    public class QuartzService {
        @Autowired
        private SgtPeppers sgtPeppers;
        
        public void printMessage(){
            sgtPeppers.play();
    //        File file2 = new File("***/src/main/java/com/***/test/HelloWorld2.txt");  
    //        if (file2.exists()) {  
    //            System.out.println("存在文件夹或者文件test");  
    //        } else {  
    //            try {  
    //                file2.createNewFile(); // 文件的创建,注意与文件夹创建的区别  
    //            } catch (IOException e) {  
    //                // TODO Auto-generated catch block  
    //                e.printStackTrace();  
    //            }  
    //        }  
    //        System.out.println("quartzService is doing");
        }
    }
    SgtPeppers类:
    package com.zml.service.impl;
    
    import org.springframework.stereotype.Component;
    
    import com.zml.service.CompactDisc;
    
    @Component
    public class SgtPeppers implements CompactDisc {
        private String title="this a title";
        private String artist="The beatles";
    
        @Override
        public void play() {
            System.out.println("Playing"+title+"by " +artist);
        }
    
    }
    QuartzService2类:
    package com.***.service.impl;
    
    import java.io.File;
    import java.io.IOException;
    
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    import org.springframework.stereotype.Service;
    
    @Service("quartzService2")
    public class QuartzService2 extends QuartzJobBean{
        private int timeout;
        private SgtPeppers sgtPeppers;
    //    public void printMessage(){
    //        File file2 = new File("***/src/main/java/com/***/test/HelloWorld2.txt");  
    //        if (file2.exists()) {  
    //            System.out.println("存在文件夹或者文件test");  
    //        } else {  
    //            try {  
    //                file2.createNewFile(); // 文件的创建,注意与文件夹创建的区别  
    //            } catch (IOException e) {  
    //                // TODO Auto-generated catch block  
    //                e.printStackTrace();  
    //            }  
    //        }  
    //        System.out.println("quartzService is doing");
    //    }
    
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            // TODO Auto-generated method stub
            System.out.println("timeout:"+timeout);
            sgtPeppers.play();
        }
    
        //注意xml注入一定要写set方法
        public SgtPeppers getSgtPeppers() {
            return sgtPeppers;
        }
    
        public void setSgtPeppers(SgtPeppers sgtPeppers) {
            this.sgtPeppers = sgtPeppers;
        }
    
        public int getTimeout() {
            return timeout;
        }
    
        public void setTimeout(int timeout) {
            this.timeout = timeout;
        }
        
    
    }
  • 相关阅读:
    lecture 11.4
    lecture 10.30
    boolean functions and beyon
    lecture10.21
    golang hex to string
    golang中 将string转化为json
    ubuntu16报错: add-apt-repository command not found
    ubuntu16的防火墙关闭
    ubuntu 16 解决错误 manpath: can't set the locale; make sure $LC_* and $LANG are correct
    go get 安装时报 (https fetch: Get https://golang.org/x/crypto/acme/autocert?go-get=1: dial tcp 220.255.2.153:443: i/o timeout)
  • 原文地址:https://www.cnblogs.com/javac/p/6616732.html
Copyright © 2011-2022 走看看