原生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;
    }
    

}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM