Quartz 的基本使用 及 Spring與Quartz 的整合配置

Quartz 使用

Quartz 核心:調度器Scheduler,任務JobDetail,觸發器Trigger

這裏寫圖片描述

調度器 Scheduler

Scheduler 接口爲任務的調度者,相當於一個總指揮,由工廠模式(SchedulerFactory接口)創建,
SchedulerFactory接口有2個實現類:StdSchedulerFactory 和 DirectSchedulerFactory。
通常通過 StdSchedulerFactory實例的getScheduler() 方法創建調度器。

        SchedulerFactory schedulerFactory =new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.start();  //開啓任務
        scheduler.scheduleJob(jobDetail, trigger1);

任務 JobDetail

JobDetail是具體Job任務的包裝,包含一些描述信息和傳遞一些參數設置。
在設置自己的任務的時候需要實現Job接口:

package org.quartz;

public interface Job {
    void execute(JobExecutionContext var1) throws JobExecutionException;
}

JobExecutionContext 是任務執行的上下文對象,包含所有執行過程中的配置,類似於ServletContext容器

實現execute 方法爲具體的任務邏輯。

public class HelloQuartz implements Job{
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
        System.out.println("hello quartz at :" + sf.format(date));
    }
}

使用JobDetail 對 Job進行包裝,設置執行參數,如執行週期,分組,標識,要執行的任務等

JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
                .withIdentity("hello_job", "hello_group")
                .build();

觸發器 Trigger

SimpleTrigger 和 CronTrigger,SimpleTrigger設置一些簡單的條件,CronTrigger才能體現Quartz的強大之處。

SimpleTrigger作用:

在一個指定的時間段內執行一次作業
或是在指定的時間間隔內多次執行作業任務

示例:

任務:

public class HelloQuartz implements Job{
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
        System.out.println("hello quartz at :" + sf.format(date));
    }
}
public class HelloScheduler {
    public static void main(String[] args) throws SchedulerException, InterruptedException {

        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
        System.out.println("current time is:" + sf.format(date));

        JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
                .withIdentity("hello_job", "hello_group")
                .build();

        // TODO 1)在一個指定的時間段內執行一次作業
        //設置距離當前時間4秒後執行,切僅執行一次, 無scheduler.shutdown()
        date.setTime(date.getTime() + 4000L);
        SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                .withIdentity("hello_trigger")
                .startAt(date)
                .build();

        // TODO 2)在指定的時間間隔內多次執行作業任務
        //設置在4秒後執行,每隔2秒執行一次,執行4次,並且在6秒後結束執行
        //注意:一旦設置了 endAt 結束時間,到達時間時就會結束,剩餘次數不會執行
        Date endTime = new Date();
        endTime.setTime(endTime.getTime() + 6000L);
        SimpleTrigger trigger1 =(SimpleTrigger) TriggerBuilder.newTrigger()
                .withIdentity("trigger1")
                .startAt(date)
                .endAt(endTime)
                .withSchedule(SimpleScheduleBuilder
                        .simpleSchedule()
                        .withIntervalInSeconds(2)
                        .withRepeatCount(4))
                .build();

        SchedulerFactory schedulerFactory =new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

        scheduler.start();
        scheduler.scheduleJob(jobDetail, trigger1);

    }
}

這裏寫圖片描述
如圖,重複2次之後結束,因爲到達了endAt 指定時間

CronTrigger作用

基於日曆的作業調度器,不是像SimpleTrigger那樣精確指定間隔時間,更常用。

Cron表達式

用於配置CronTrigger 實例
由7個子表達式組成字符串
格式:[秒] [分] [小時] [日] [月] [周] [年]

Cron表達式對應字段含義

Cron表達式舉例

Cron表達式通配符說明

Cron表達式提示:
- ‘L’和’W’可以一組使用
比如:在日設置上,表示最後一個工作日(發工資?)
- 周字段英文不區分大小寫
- 在線工具生成Cron表達式

Spring 與 Quartz 的整合

  1. 添加maven依賴:
<!-- 其他省略-->
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
</dependency>
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
</dependency>
<dependency>
      <groupId>org.quartz-scheduler</groupId>
      <artifactId>quartz</artifactId>
      <version>2.2.3</version>
</dependency>
  1. 配置quartz 任務的2種方式:
    任務類一:
@Component("myBean")
public class MyBean {

    public void printMessage(){
        System.out.println("msssssssss..");
    }

}

任務類二:

@Component("anotherBean")
public class AnotherBean {
    public void printAnotherMessage() {
        System.out.println("AnotherMessage");
    }
}

任務類二注入的job:

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 Executes!" + sf.format(date));
        this.anotherBean.printAnotherMessage();
    }
}

xml 配置:

<!-- 1)配置quartz 作業方式一:使用MethodInvokingJobDetailFactoryBean-->
    <bean id="simpleJobDetail"         class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="myBean" />
        <property name="targetMethod" value="printMessage" />
    </bean>
<!-- 距離當前時間1秒之後執行,之後每隔兩秒鐘執行一次 -->
    <bean id="mySimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail"  ref="simpleJobDetail"/>
        <property name="startDelay"  value="1000"/>
        <property name="repeatInterval"  value="2000"/>
    </bean>


    <!-- 2)配置quartz 作業方式二:使用JobDetailFactoryBean-->
    <bean id="firstComplexJobDetail"
          class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass"
                  value="com.kay.quartz.FirstScheduledJob" />
        <property name="jobDataMap">
            <map>
                <entry key="anotherBean" value-ref="anotherBean" />
            </map>
        </property>
        <!-- job沒有綁定trigger 仍然保留在Scheduler中-->
        <property name="Durability" value="true"/>
    </bean>
    <!-- 每隔5秒鐘執行一次 -->
    <bean id="myCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail"  ref="firstComplexJobDetail"/>
        <property name="cronExpression"  value="0/5 * * ? * *"/>
    </bean>

<!-- 最後交給Scheduler 進行調度-->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="jobDetails">
            <list>
                <ref bean="simpleJobDetail"/>
                <ref bean="firstComplexJobDetail"/>
            </list>
        </property>
        <property name="triggers">
            <list>
                <ref bean="mySimpleTrigger"/>
                <ref bean="myCronTrigger"/>
            </list>
        </property>
    </bean>
2種方式比較:
  • MethodInvokingJobDetailFactoryBean
    配置簡單,使用方便
  • JobDetailFactoryBean
    傳遞數據等,更加靈活,jobClass的類要繼承QuartzJobBean

附:quartz.properties 配置文件

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
# ===========================================================================
# Configure Main Scheduler Properties 調度器屬性
# ===========================================================================
org.quartz.scheduler.instanceName= DefaultQuartzScheduler
org.quartz.scheduler.instanceid=AUTO
org.quartz.scheduler.rmi.export= false
org.quartz.scheduler.rmi.proxy= false
org.quartz.scheduler.wrapJobExecutionInUserTransaction= false
# ===========================================================================  
# Configure ThreadPool 線程池屬性  
# ===========================================================================
#線程池的實現類(一般使用SimpleThreadPool即可滿足幾乎所有用戶的需求)
org.quartz.threadPool.class= org.quartz.simpl.SimpleThreadPool
#指定線程數,至少爲1(無默認值)(一般設置爲1-100直接的整數合適)
org.quartz.threadPool.threadCount= 10
#設置線程的優先級(最大爲java.lang.Thread.MAX_PRIORITY 10,最小爲Thread.MIN_PRIORITY 1,默認爲5)
org.quartz.threadPool.threadPriority= 5
#設置SimpleThreadPool的一些屬性
#設置是否爲守護線程
#org.quartz.threadpool.makethreadsdaemons = false
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread= true
#org.quartz.threadpool.threadsinheritgroupofinitializingthread=false
#線程前綴默認值是:[Scheduler Name]_Worker
#org.quartz.threadpool.threadnameprefix=swhJobThead;
# 配置全局監聽(TriggerListener,JobListener) 則應用程序可以接收和執行 預定的事件通知
# ===========================================================================
# Configuring a Global TriggerListener 配置全局的Trigger監聽器
# MyTriggerListenerClass 類必須有一個無參數的構造函數,和 屬性的set方法,目前2.2.x只支持原始數據類型的值(包括字符串)
# ===========================================================================
#org.quartz.triggerListener.NAME.class = com.swh.MyTriggerListenerClass
#org.quartz.triggerListener.NAME.propName = propValue
#org.quartz.triggerListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configuring a Global JobListener 配置全局的Job監聽器
# MyJobListenerClass 類必須有一個無參數的構造函數,和 屬性的set方法,目前2.2.x只支持原始數據類型的值(包括字符串)
# ===========================================================================
#org.quartz.jobListener.NAME.class = com.swh.MyJobListenerClass
#org.quartz.jobListener.NAME.propName = propValue
#org.quartz.jobListener.NAME.prop2Name = prop2Value
# ===========================================================================  
# Configure JobStore 存儲調度信息(工作,觸發器和日曆等)
# ===========================================================================
# 信息保存時間 默認值60秒
org.quartz.jobStore.misfireThreshold= 60000
#保存job和Trigger的狀態信息到內存中的類
org.quartz.jobStore.class= org.quartz.simpl.RAMJobStore
# ===========================================================================  
# Configure SchedulerPlugins 插件屬性 配置
# ===========================================================================
# 自定義插件  
#org.quartz.plugin.NAME.class = com.swh.MyPluginClass
#org.quartz.plugin.NAME.propName = propValue
#org.quartz.plugin.NAME.prop2Name = prop2Value
#配置trigger執行歷史日誌(可以看到類的文檔和參數列表)
#org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin
#org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at= {4, date, HH=mm=ss MM/dd/yyyy}
#org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH=mm=ss MM/dd/yyyy} with resulting trigger instruction code= {9}
#配置job調度插件  quartz_jobs(jobs and triggers內容)的XML文檔  
#加載 Job 和 Trigger 信息的類   (1.8之前用:org.quartz.plugins.xml.JobInitializationPlugin)
#org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
#指定存放調度器(Job 和 Trigger)信息的xml文件,默認是classpath下quartz_jobs.xml
#org.quartz.plugin.jobInitializer.fileNames = my_quartz_job2.xml
#org.quartz.plugin.jobInitializer.overWriteExistingJobs = false  
#org.quartz.plugin.jobInitializer.failOnFileNotFound = true
#自動掃描任務單並發現改動的時間間隔,單位爲秒
#org.quartz.plugin.jobInitializer.scanInterval = 10
#覆蓋任務調度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情況
#org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
# ===========================================================================  
# Sample configuration of ShutdownHookPlugin  ShutdownHookPlugin插件的配置樣例
# ===========================================================================
#org.quartz.plugin.shutdownhook.class = \org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownhook.cleanShutdown = true
#
# Configure RMI Settings 遠程服務調用配置
#
#如果你想quartz-scheduler出口本身通過RMI作爲服務器,然後設置“出口”標誌true(默認值爲false)。
#org.quartz.scheduler.rmi.export = false
#主機上rmi註冊表(默認值localhost)
#org.quartz.scheduler.rmi.registryhost = localhost
#註冊監聽端口號(默認值1099)
#org.quartz.scheduler.rmi.registryport = 1099
#創建rmi註冊,false/never:如果你已經有一個在運行或不想進行創建註冊
# true/as_needed=第一次嘗試使用現有的註冊,然後再回來進行創建
# always=先進行創建一個註冊,然後再使用回來使用註冊
#org.quartz.scheduler.rmi.createregistry = never
#Quartz Scheduler服務端端口,默認是隨機分配RMI註冊表
#org.quartz.scheduler.rmi.serverport = 1098
#true=鏈接遠程服務調度(客戶端),這個也要指定registryhost和registryport,默認爲false
# 如果export和proxy同時指定爲true,則export的設置將被忽略
#org.quartz.scheduler.rmi.proxy = false
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章