1. 程式人生 > >Quarz完成定時任務(非註解版)

Quarz完成定時任務(非註解版)

Quartz作業排程框架(附整合Spring)

https://img-blog.csdnimg.cn/20181229105815618

QuartzOpenSymphony開源組織在Job scheduling領域又一個開源專案,它可以與J2EEJ2SE應用程

​​​

https://img-blog.csdnimg.cn/20181229105815671

QuartzOpenSymphony開源組織在Job scheduling領域又一個開源專案,它可以與J2EEJ2SE應用程式相結合也可以單獨使用。Quartz可以用來建立簡單或為執行十個,百個,甚至是好幾萬個Jobs這樣複雜的程式。Jobs可以做成標準的Java元件或 EJBsQuartz的最新版本為Quartz 2.3.0

1.  結構

 

Quartz是一個完全由java編寫的開源作業排程框架。不要讓作業排程這個術語嚇著你。儘管Quartz框架整合了許多額外功能, 但就其簡易形式看,你會發現它易用得簡直讓人受不了!。簡單地建立一個實現org.quartz.Job介面的java類。Job介面包含唯一的方法:

public void execute(JobExecutionContext context)

throws JobExecutionException;

在你的Job介面實現類裡面,新增一些邏輯到execute()方法。一旦你配置好Job實現類並設定好排程時間表,Quartz將密切注意剩餘時間。當排程程式確定該是通知你的作業的時候,

Quartz框架將呼叫你Job實現類(作業類)上的execute()方法並允許做它該做的事情。無需報告任何東西給排程器或呼叫任何特定的東西。僅僅執行任務和結束任務即可。如果配置你的作業在隨後再次被呼叫,Quartz框架將在恰當的時間再次呼叫它。

 

1.  框架特徵

編輯

Quartz框架有一個豐富的特徵集。事實上,Quartz有太多特性以致不能在一種情況中全部領會,下面列出了一些有意思的特徵,但沒時間在此詳細討論。

監聽器和外掛

每個人都喜歡監聽和外掛。今天,幾乎下載任何開源框架,你必定會發現支援這兩個概念。監聽是你建立的

java類,當關鍵事件發生時會收到框架的回撥。例如,當一個作業被排程、沒有排程或觸發器終止和不再觸發時,這些都可以通過設定來通知你的監聽器。Quartz框架包含了排程器監聽、作業和觸發器監聽。你可以配置作業和觸發器監聽為全域性監聽或者是特定於作業和觸發器的監聽。

一旦你的一個具體監聽被呼叫,你就能使用這個技術來做一些你想要在監聽類裡面做的事情。例如,你如果想要在每次作業完成時傳送一個電子郵件,你可以將這個邏輯寫進作業裡面,也可以寫進JobListener裡面。寫進JobListener的方式強制使用鬆耦合有利於設計上做到更好。

Quartz外掛是一個新的功能特性,無須修改Quartz原始碼便可被建立和新增進Quartz框架。他為想要擴充套件Quartz框架又沒有時間提交改變給Quartz開發團隊和等待新版本的開發人員而設計。如果你熟悉Struts外掛的話,那麼完全可以理解Quartz外掛的使用。

與其Quartz提供一個不能滿足你需要的有限擴充套件點,還不如通過使用外掛來擁有可修整的擴充套件點。

叢集Quartz應用

Quartz應用能被叢集,是水平叢集還是垂直叢集取決於你自己的需要。叢集提供以下好處:

·伸縮性

·高可用性

·負載均衡

Quartz可以藉助關係資料庫和JDBC作業儲存支援叢集。

Terracotta擴充套件quartz提供叢集功能而不需要資料庫支援

相關工具

Quartz經常會用到cron表示式,可以使用國外網站cronmaker輔助生成cron表示式。

 

1.  核心介面和類

1 Scheduler介面

它提供了對作業計劃的啟動、停止、恢復、刪除、對作業計劃的重新定製的方法

它通過JobDetailtrigger建立一個作業計劃

 

2 Job介面

只需要實現一個方法void execute(JobExecutionContext context)

程式中需要被執行的作業就需要在execute中實現。

 

3 JobDetail

通過JobDetail類可以設定具體執行的Job,並且給執行的Job設定名稱,組,描述等資訊,該類包括一個JobDetail(String name,String group,Class JobClass)構造器,它的引數

分別是job的名稱,組名,和實現了job介面的實現類

 

4 Trigger

主要是設定觸發Job執行的時間觸發規則,主要有SimpleTriggerCronTrigger這兩個子類。

 

SimpleTrigger擅長執行單次執行或者固定週期計劃任務執行。

CronTrigger則可以通過Cron表示式定義出各種複雜的時間規則的排程方案。

 

1.  Cron表示式

語法為 (可省略)

https://img-blog.csdnimg.cn/20181229105815709

1.  Cron表示式訓練

(1)   */5 ** ** ?  --每隔5秒執行一次

(2)   0 */1 *** ? –每隔1分鐘執行一次

(3)   00 23 ** ? – 每天23點執行一次

(4)   00 1? ** --每週日凌晨1點執行一次

(5)   00 11 *? 每月1號凌晨1點執行一次

(6)   0 26,29,33 ***? 26分,29分,33分執行一次

 

1. Spring整合QuartZ框架

 

一個普通的java類,配置JobDetailTriggerScheduler

1.  依賴的jar

Spring-context-support.jar

Spring-tx.jar

Quartz.jar

 


<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>


<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.0.6.RELEASE</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.3</version>
</dependency>

​

1.  搭建專案

https://img-blog.csdnimg.cn/20181229105815747

https://img-blog.csdnimg.cn/20181229105815789

https://img-blog.csdnimg.cn/20181229105815829

https://img-blog.csdnimg.cn/20181229105815865

​​

3.  配置檔案

https://img-blog.csdnimg.cn/20181229105815907


<?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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <context:component-scan base-package="com.cxl.scheduler"/>

    <bean id="myJob" class="com.cxl.scheduler.MyJob"/>
    <!--指定需要定時執行的方法-->
    <bean id="myJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="myJob"/>
        <property name="targetMethod" value="mockCallService"/>
    </bean>

    <!--按指定頻率執行-->
    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="myJobDetail"/>
        <!--啟動延時-->
        <property name="startDelay" value="0"></property>
        <!--執行評率,單位,毫秒-->
        <property name="repeatInterval" value="2000"/>
    </bean>
<!--
    &lt;!&ndash;按指定時間執行&ndash;&gt;
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="myJobDetail"/>
        <property name="cronExpression" value="0 26,27 16 * * ?"/>
    </bean>-->

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger"/>
                <!--<ref bean="cronTrigger"/>-->
            </list>
        </property>
    </bean>

https://img-blog.csdnimg.cn/20181229105815969


4.  執行專案(simpleTrigger來啟動)

https://img-blog.csdnimg.cn/2018122910581626

可以發現,它是每2秒使用這個方法一次

 

https://img-blog.csdnimg.cn/2018122910581670

按是制定時間來執行

https://img-blog.csdnimg.cn/20181229105816120

https://img-blog.csdnimg.cn/20181229105816198


1. QuartZ工具類

.

import static org.quartz.JobBuilder.newJob;

import static org.quartz.JobKey.jobKey;

import static org.quartz.TriggerBuilder.newTrigger;

import static org.quartz.CronScheduleBuilder.cronSchedule;

import static org.quartz.TriggerKey.triggerKey;



import java.util.Date;



import org.quartz.CronTrigger;

import org.quartz.JobDetail;

import org.quartz.Scheduler;

import org.quartz.SchedulerException;

import org.quartz.Trigger;



public class QuartzUtils {

    private static String JOB_NAME = "EXTJWEB_NAME";

    private static String JOB_GROUP_NAME = "EXTJWEB_JOBGROUP_NAME";

    private static String TRIGGER_NAME = "EXTJWEB_NAME";

    private static String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME";



    /**

     * @Description: 新增一個定時任務,使用預設的任務組名,觸發器名,觸發器組名

     * @param sched:排程器

     * @param jobClass:任務

     * @param time:時間設定,CronExpression表示式

     */

    public static void addJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time) {

        addJob(sched, jobClass,time,JOB_NAME,JOB_GROUP_NAME,TRIGGER_NAME,TRIGGER_GROUP_NAME);

    }



    /**

     * @Description: 新增一個定時任務

     * @param sched:排程器

     * @param jobClass:任務

     * @param time:時間設定,CronExpression表示式

     * @param jobName:任務名

     * @param jobGroupName:任務組名

     * @param triggerName:觸發器名

     * @param triggerGroupName:觸發器組名

     */

    public static void addJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time,

            String jobName, String jobGroupName, String triggerName, String triggerGroupName) {



        JobDetail job = newJob(jobClass).withIdentity(jobName, jobGroupName).build();

        CronTrigger trigger = newTrigger().withIdentity(triggerName, triggerGroupName)

                .withSchedule(cronSchedule(time)).build();

        try {

            // 返回為 null 新增失敗

            Date ft = sched.scheduleJob(job, trigger);

        } catch (SchedulerException e) {

            e.printStackTrace();

        }

    }



    /**

     * @Description: 定義一個任務之後進行觸發設定(使用預設的任務組名,觸發器名,觸發器組名)

     * @param sched:排程器

     * @param time

     */

    @SuppressWarnings("rawtypes")

    public static void addJObLaterUse(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time) {



        addJObLaterUse(sched,jobClass,time,JOB_NAME,JOB_GROUP_NAME);

    }



    /**

     * @Description: 定義一個任務之後進行觸發設定

     * @param sched:排程器

     * @param time

     * @param jobName:任務名

     * @param jobGroupName:任務組名

     */

    @SuppressWarnings("rawtypes")

    public static void addJObLaterUse(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time,

            String jobName,String jobGroupName) {



        JobDetail job = newJob(jobClass).withIdentity(jobName, jobGroupName).storeDurably().build();



        try {

            sched.addJob(job, false);

        } catch (SchedulerException e) {

            e.printStackTrace();

        }

    }



    /**

     * @Description: 對已儲存的任務進行scheduling(使用預設的任務組名,觸發器名,觸發器組名)

     * @param sched:排程器

     * @param time

     * @param jobName:任務名

     * @param jobGroupName:任務組名

     */

    @SuppressWarnings("rawtypes")

    public static void schedulingStoredJOb(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time) {

        schedulingStoredJOb(sched,jobClass,time,JOB_NAME,JOB_GROUP_NAME,TRIGGER_NAME,TRIGGER_GROUP_NAME);

    }



    /**

     * @Description: 對已儲存的任務進行scheduling

     * @param sched:排程器

     * @param time

     * @param jobName:任務名

     * @param jobGroupName:任務組名

     */

    @SuppressWarnings("rawtypes")

    public static void schedulingStoredJOb(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String time,

            String jobName,String jobGroupName,String triggerName, String triggerGroupName) {

        Trigger trigger = newTrigger().withIdentity(triggerName, triggerGroupName).startNow()

                .forJob(jobKey(jobName,jobGroupName))

                .build();

        try {

            sched.scheduleJob(trigger);

        } catch (SchedulerException e) {

            e.printStackTrace();

        }

    }



    /**

     * @Description: 修改一個任務的觸發時間(使用預設的任務組名,觸發器名,觸發器組名)

     * @param sched:排程器

     * @param time

     */

    @SuppressWarnings("rawtypes")

    public static void modifyJobTime(Scheduler sched, String time) {

        modifyJobTime(sched, TRIGGER_NAME, TRIGGER_GROUP_NAME, time);

    }



    /**

     * @Description: 修改一個任務的觸發時間

     * @param sched:排程器

     * @param triggerName

     * @param triggerGroupName

     * @param time

     */

    public static void modifyJobTime(Scheduler sched, String triggerName, String triggerGroupName, String time) {

        Trigger trigger = newTrigger().withIdentity(triggerName, triggerGroupName).withSchedule(cronSchedule(time)).startNow().build();



        try {

            sched.rescheduleJob(triggerKey(triggerName, triggerGroupName), trigger);

        } catch (SchedulerException e) {

            e.printStackTrace();

        }

    }



    /**

     * @Description: 修改一個任務(使用預設的任務組名,任務名)

     * @param sched:排程器

     */

    @SuppressWarnings("rawtypes")

    public static void modifyJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass) {

        modifyJob(sched,jobClass,JOB_NAME,JOB_GROUP_NAME);

    }



    /**

     * @Description: 修改一個任務

     * @param sched:排程器

     * @param jobName:任務名

     * @param jobGroupName:任務組名

     */

    public static void modifyJob(Scheduler sched, @SuppressWarnings("rawtypes") Class jobClass, String jobName,String jobGroupName) {

        JobDetail job1 = newJob(jobClass).withIdentity(jobName,jobGroupName).build();

        try {

            sched.addJob(job1, true);

        } catch (SchedulerException e) {

            e.printStackTrace();

        }

    }



    /**

     * @Description: 刪除一個任務的的trigger

     * @param sched:排程器

     * @param triggerName

     * @param triggerGroupName

     */

    public static void unschedulingJob(Scheduler sched,String triggerName, String triggerGroupName) {

        try {

            sched.unscheduleJob(triggerKey(triggerName,triggerGroupName));

        } catch (SchedulerException e) {

            e.printStackTrace();

        }

    }



    /**

     * @Description: 移除一個任務,以及任務的所有trigger

     * @param sched:排程器

     * @param jobName

     */

    public static void removeJob(Scheduler sched, String jobName,String jobGroupName) {

        try {

            sched.deleteJob(jobKey(jobName,jobGroupName));

        } catch (SchedulerException e) {

            e.printStackTrace();

        }

    }



    /**

     * @Description:啟動所有定時任務

     * @param sched:排程器

     */

    public static void startJobs(Scheduler sched) {

        try {

            sched.start();

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }



    /**

     * @Description:關閉所有定時任務

     * @param sched:排程器

     */

    public static void shutdownJobs(Scheduler sched) {

        try {

            if (!sched.isShutdown()) {

                //未傳參或false:不等待執行完成便結束;true:等待任務執行完才結束

                sched.shutdown();

            }

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

}