Quartz快速入門

一、Quartz簡介

1.quartz是開源且具有豐富特性的"任務調度庫",能夠集成於任何的java應用。

2.quartz主要分爲三大組件,分別是任務Job、觸發器Trigger以及調度器Scheduler。

quartz體系架構圖:

 

二、quartz三大組件簡介

1.任務Job:即想要調用的任務類,需要實現org.quartz.job接口,並重寫execute()方法,任務調度時會執行execute()方法。

2.觸發器Trigger:即執行任務的觸發器,當滿足什麼條件時會去執行你的任務Job,主要分爲根據時長間隔執行的SimpleTrigger和根據日曆執行的CronTrigger。

3.調度器Scheduler:即將Trigger和Job綁定之後,根據Trigger中的設定,負責進行Job調度的組件。

其它:

    1.一個調度器可以讓多個觸發器Trigger和任務Job綁定,而一個任務Job實例只能和一個觸發器Trigger實例綁定,反過來也是如此。

 

三、案例入門

1.引入maven:

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.3.2</version>
        </dependency>

本文使用的是2.3.2版本,建議使用最新版本,如果需要日誌可自行引入。

2.測試代碼:

public class QuartzTest {


    public static void main(String[] args) throws SchedulerException {
        //1.調度器(Scheduler)
        SchedulerFactory schedulerfactory = new StdSchedulerFactory();
        //拿到調度器,調度器只需要一個即可,可以調度多個任務
        Scheduler scheduler = schedulerfactory.getScheduler();
        //2.Job實例(JobDetil)
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job", "default") //name:任務的名稱,group:分組名
                .build();
        //3.觸發器(Trigger)
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "default") //name:觸發器名稱,group:分組名
                .startNow() //馬上執行一次,默認
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(20,2))//使用Simple觸發器,執行20次,間隔2秒
                .build();
        //4.讓Job和觸發器關聯
        scheduler.scheduleJob(jobDetail,trigger);
        //5.進行任務調度
        scheduler.start();
    }

    
    public static class MyJob implements Job {
        
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            //打印當前時間
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date = dateFormat.format(new Date());
            System.out.println(date);
        }
    }
}

3.執行結果:

    每兩秒打印一次時間。

3.步驟說明:

通過上文,可以大概知道quartz的操作大概分爲六步:

1.通過SchedulerFactory獲取一個任務調度器Scheduler

2.實現org.quartz.job接口,並重寫execute()方法爲自己需要的任務調度邏輯。

3.通過JobBuilder.newJob()構建一個JobDetail(Job實例對象),並設置對應參數。

4.通過TriggerBuilder.newTrigger()構建一個觸發器Trigger,並設置對應的參數。

5.通過Scheduler將JobDetail和Trigger綁定。

6.通過Scheduler的start()方法開始進行任務的調度。

 

四、參數傳遞

1.測試代碼:

public class QuartzTest {


    public static void main(String[] args) throws SchedulerException{
        //1.調度器(Scheduler)
        SchedulerFactory schedulerfactory = new StdSchedulerFactory();
        //拿到調度器,調度器只需要一個即可,可以調度多個任務
        Scheduler scheduler = schedulerfactory.getScheduler();
        //2.Job實例(JobDetil)
        JobDataMap jobDetailMap = new JobDataMap();
        jobDetailMap.put("name","xuye");
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job", "default") //name:任務的名稱,group:分組名
                .usingJobData(jobDetailMap) //傳遞參數
                .build();
        //3.觸發器(Trigger)
        JobDataMap triggerMap = new JobDataMap();
        triggerMap.put("age",100);
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "default") //name:觸發器名稱,group:分組名
                .usingJobData(triggerMap)
                .startNow() //馬上執行一次,默認
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(1,2))//使用Simple觸發器,執行1次,間隔2秒
                .build();
        //4.讓調度器關聯Job和觸發器
        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();
    }

    public static class MyJob implements Job {



        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            //方式一,獲取JobDetail和Trigger傳遞的所有參數信息,使用此方式則不能對其進行設值。
            JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();
            //方式二,獲取JobDetail的Map參數
            JobDataMap jobDetailMap = jobExecutionContext.getJobDetail().getJobDataMap();
            //方式三,獲取Trigger的Map參數
            JobDataMap triggerMap = jobExecutionContext.getTrigger().getJobDataMap();
            System.out.println("getMergedJobDataMap()方法中能獲取到的key和value:\n"+getKeyAndValue(jobDataMap));
            System.out.println("getJobDetail().getJobDataMap()方法中能獲取到的key和value:\n"+getKeyAndValue(jobDetailMap));
            System.out.println("getTrigger().getJobDataMap()方法中能獲取到的key和value:\n"+getKeyAndValue(triggerMap));
        }

        private String getKeyAndValue(Map<String,Object> map) {
            StringBuilder sb = new StringBuilder();
            Set<Map.Entry<String, Object>> entries = map.entrySet();
            for(Map.Entry<String, Object> entry : entries) {
                sb.append(entry.getKey()+":"+entry.getValue().toString()+",");
            }
            return sb.toString();
        }
    }
}

2.執行結果:

3.說明:

    1.通過使用 JobDataMap對象,在JobBuilder和TriggerBuilder中調用usingJobData方法將JobDataMap設置進去。

    2.在org.quartz.job實現類中通過JobExecutionContext上文下環境獲取對應的參數,主要有以下3個方法,

        1)jobExecutionContext.getMergedJobDataMap():

             獲取JobBuilder和TriggerBuilder中兩個的Map參數,注意使用該方式只能獲取值,不能設置值,因爲是無效的。

        2)jobExecutionContext.getJobDetail().getJobDataMap():

             獲取JobDetail的Map參數,只能獲取JobDetail的。

        3)jobExecutionContext.getTrigger().getJobDataMap():

             獲取Trigger的Map參數,只能獲取Trigger的。

    3.建議:如果只獲取值,則使用jobExecutionContext.getMergedJobDataMap(),如果需要獲取值,並把值傳遞到下一個任務調度中,請使用JobDetail或Trigger的對應參數。

    4.jobExecutionContext.getMergedJobDataMap()不能設置原理說明:每次任務調度時,都會創建一個JobExecutionContext,而創建後會把JobDetail或Trigger的對應參數全部設置到一個新的Map中,如果進行設值,則下次創建的還是新創建一個Map,上一個JobExecutionContext的設值則變爲無效。

 

五、JobDataMap持久化

1.測試代碼:

public class QuartzTest {

    public static void main(String[] args) throws SchedulerException{
        //1.調度器(Scheduler)
        SchedulerFactory schedulerfactory = new StdSchedulerFactory();
        //拿到調度器,調度器只需要一個即可,可以調度多個任務
        Scheduler scheduler = schedulerfactory.getScheduler();
        //2.Job實例(JobDetil)
        JobDataMap jobDetailMap = new JobDataMap();
        jobDetailMap.put("count",0);
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job", "default") //name:任務的名稱,group:分組名
                .usingJobData(jobDetailMap) //傳遞參數
                .build();
        //3.觸發器(Trigger)
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "default") //name:觸發器名稱,group:分組名
                .startNow() //馬上執行一次,默認
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(20,2))//使用Simple觸發器,執行20次,間隔2秒
                .build();
        //4.讓調度器關聯Job和觸發器
        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();
    }

    public static class MyJob implements Job {
        
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            //獲取JobDetail的Map參數
            JobDataMap jobDetailMap = jobExecutionContext.getJobDetail().getJobDataMap();
            Integer count = (Integer) jobDetailMap.get("count");
            ++count;
            System.out.println("當前執行次數:"+count);
            jobDetailMap.put("count",count);
        }

    }
}

2.執行結果:

3.說明:

    1.我們想要統計執行次數,但每次獲取到的JobDetail參數Map都是新的。

    2.如果想要JobDetail和Trigger的Map參數都是持久化,只需要在該Job實例的類上加上注@PersistJobDataAfterExecution即可。

    3.修改如下:

    4.新的測試結果:

    5.JobDetail和Trigger的效果一致,Trigger代碼就不多寫,如果使用jobExecutionContext.getMergedJobDataMap(),只能獲取JobDetail和Trigger的Map數據,並不能設值,上文已經說明原理,可自行測試。

 

六、自動注入

1.測試代碼:

public class QuartzTest {

    public static void main(String[] args) throws SchedulerException{
        //1.調度器(Scheduler)
        SchedulerFactory schedulerfactory = new StdSchedulerFactory();
        //拿到調度器,調度器只需要一個即可,可以調度多個任務
        Scheduler scheduler = schedulerfactory.getScheduler();
        //2.Job實例(JobDetil)
        JobDataMap jobDetailMap = new JobDataMap();
        jobDetailMap.put("name","xuye");
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job", "default") //name:任務的名稱,group:分組名
                .usingJobData(jobDetailMap) //傳遞參數
                .build();
        //3.觸發器(Trigger)
        JobDataMap triggerMap = new JobDataMap();
        triggerMap.put("age",100);
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "default") //name:觸發器名稱,group:分組名
                .usingJobData(triggerMap)
                .startNow() //馬上執行一次,默認
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(1,2))//使用Simple觸發器,執行1次,間隔2秒
                .build();
        //4.讓調度器關聯Job和觸發器
        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();
    }
    
    public static class MyJob implements Job {

        private String name;
        
        private Integer age;

        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.out.println("name:"+name+",age:"+age);
        }

        public void setName(String name) {
            this.name = name;
        }
        
        public void setAge(Integer age) {
            this.age = age;
        }
    }
}

2.執行結果:

  

3.說明:

     1.如需使用自動注入,只需要org.quartz.job實現類中提供和其對應的屬性名的set方法即可。

 

七、常用API

1.StdSchedulerFactory

    

方法名 說明
Scheduler getScheduler()
獲取一個調度器
Scheduler
void initialize(Properties props)
初始化SchedulerFactory
Collection<Scheduler> getAllSchedulers()
獲取所有的Scheduler

2.Scheduler

方法名 說明
Date scheduleJob(JobDetail jobDetail, Trigger trigger)
將JobDetail和Trigger綁定
void triggerJob(JobKey jobKey)
通過JobKey立馬執行一個Job
void triggerJob(JobKey jobKey, JobDataMap data)
通過JobKey立馬執行一個Job,並傳遞參數
void start()
開始調度所有的任務,如果是暫停後調用則爲重啓
void shutdown()
馬上關閉所有任務
void shutdown(boolean waitForJobsToComplete)
是否等待任務執行完關閉,true等待,false不等待
void standby()
暫停所有任務Job,通過start()方法重啓
void pauseJob(JobKey jobKey)
通過JobKey暫停某個Job
void resumeJob(JobKey jobKey)
通過JobKey喚醒某個暫停的Job
void pauseTrigger(TriggerKey triggerKey)
暫停某個Trigger的所有Job
void resumeTrigger(TriggerKey triggerKey)
喚醒某個暫停的Trigger的Job

3.JobBuilder

方法名 說明
JobBuilder newJob(Class <? extends Job> jobClass):靜態方法
加載Job的實例
JobBuilder withIdentity(String name, String group)
設置該
JobDetail的名字和分組
JobBuilder usingJobData(String dataKey, String value)
傳遞參數,通過key和value
JobBuilder usingJobData(JobDataMap newJobDataMap)
傳遞參數,通過JobDataMap
JobDetail build()
按照之前的參數設置,構建一個JobDetail

 

4.JobDetail

方法名 說明
JobDataMap getJobDataMap()
獲取該JobDetail的JobDataMap
JobKey getKey()
獲取該JobDetail的JobKey

 

5.TriggerBuilder

方法名 說明
TriggerBuilder<Trigger> newTrigger:靜態方法
加載一個Trigger
TriggerBuilder<T> withIdentity(String name, String group)
設置該
Trigger的名字和分組
TriggerBuilder<T> usingJobData(String dataKey, String value)
傳遞參數,通過key和value
TriggerBuilder<T> usingJobData(JobDataMap newJobDataMap)
傳遞參數,通過JobDataMap
TriggerBuilder<SBT> withSchedule(ScheduleBuilder<SBT> schedBuilder)
關聯一個ScheduleBuilder,通常是SimpleScheduleBuilder或CronScheduleBuilder
T build()
按照之前的參數設置,構建一個Trigger

6.Trigger

方法名 說明
JobDataMap getJobDataMap()
獲取該JobDetail的JobDataMap
 Date getNextFireTime()
獲取下一次執行時間
TriggerKey getKey()
獲取該Trigger的TriggerKey
Date getEndTime()
獲取結束時間
Date getStartTime()
獲取開始時間

7.SimpleScheduleBuilder

方法名 說明
SimpleScheduleBuilder repeatSecondlyForever(int seconds):靜態方法

 

構建一個重複執行,按秒
SimpleScheduleBuilder repeatSecondlyForTotalCount(int count, int seconds):靜態方法
重複執行,間隔按秒,並且執行一定的次數。
類似上面2個重複執行的靜態方法還有按分鐘,按小時,因爲內容過多便不寫出來,方法名都是類似的。
 
SimpleScheduleBuilder withRepeatCount(int triggerRepeatCount)
重複執行的次數,注意:如果是1,則執行2次,因爲運行立馬執行一次,以此類推。

8.CronScheduleBuilder

方法名 說明
CronScheduleBuilder cronSchedule(String cronExpression):靜態方法

 

根據cron表達式構建一個CronScheduleBuilder

 

9.CronExpression

方法名 說明
boolean isValidExpression(String cronExpression):靜態方法

 

校驗Cron表達式
CronExpression(String cronExpression)
構造函數,檢驗一個Cron表達式,如果不通過則拋出異常,該異常信息包含不通過的原因

 

八、Cron表達式

Cron表達式被用來配置CronTrigger實例,Cron表達式是一個由7個子表達式(第7個可以省略)組成的字符串。一般格式如下:* * * * * ?或* * * * * ?*,每個子表達式的代表一個日期細節,具體如下:

位置 說明 允許值 允許的特殊字符
1 Seconds 秒 0-59 , / * -
2 Minutes 分鐘 0-59 , / * -
3 Hours 小時 0-23 , / * -
4 Day-of-Month 月中的天 1-31 , / * - ? L W C
5  Month 月 1-12或英文JAN-DEC , / * -
6 Day-of-Week 週中的天 1-7或英文SUN-SAT , / * - ? L C #
7 Year (optional field) 年(可選) 1970-2099(一般不寫) , / * -

特殊字符含義說明:

字符 含義
,(逗號) 表示多個值,如秒中使用逗號分隔5,10,20,則表示在5秒、10秒、20秒執行,理解爲或。
? 表示不指定值,用於第四(月中的天)和第六位(週中的天),因爲第四位和第六位是衝突的,如果第四位有值則第六位必須爲?,反過來也是如此。
* 表示所有可能的值,如果秒中使用*則表示60秒的每一秒都執行,小時上使用*則表示24小時的每個小時都執行。
- 表示區間,如小時上用6-8,則表示6,7,8點都會執行。
/ 表示間隔,如在秒中使用0/20,則表示每隔20秒執行一次。
# 表示月中的第幾個周幾,如6#3,表示該月第三週的週五(國外的週日=我們的週一)
W 指定離給定日期最近的工作日(週一到週五)
L 用在第四位(月中的天)表示一個月中的最後一天,用在第六位(週中的天)表示該月最後一個星期X,如用在第六位6L,則表示這個月的最後一個週五

九、Trigger觸發器

Trigger觸發器主要分爲兩大類:Simple觸發器(通過SimpleScheduleBuilder關聯)和Cron觸發器(通過CronScheduleBuilder關聯),上文案例中已經介紹了SimpleScheduleBuilder的使用和API設置,下面看CronScheduleBuilder的使用。

1.測試代碼:

public class QuartzTest {


    public static void main(String[] args) throws SchedulerException{
        //1.調度器(Scheduler)
        SchedulerFactory schedulerfactory = new StdSchedulerFactory();
        //拿到調度器,調度器只需要一個即可,可以調度多個任務
        Scheduler scheduler = schedulerfactory.getScheduler();
        //2.Job實例(JobDetil)
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job", "default") //name:任務的名稱,group:分組名
                .build();
        //3.觸發器(Trigger)
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger", "default") //name:觸發器名稱,group:分組名
                .startNow() //馬上執行一次
                .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?"))//使用Cron觸發器
                .build();
        //4.讓Job和觸發器關聯
        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();
    }


    public static class MyJob implements Job {

        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            //打印當前時間
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date = dateFormat.format(new Date());
            System.out.println(date);
        }
    }
}

2.執行結果:

    cron表達式爲:0/3 * * * * ? 即從0秒開始,每間隔3秒執行一次。

 

十、StdSchedulerFactory的配置

上文中介紹了StdSchedulerFactory的API,其中就有一個initialize(Properties props)方法,對StdSchedulerFactory進行初始化,常用的配置的屬性名和值如下:

屬性名 說明
org.quartz.threadPool.class 使用哪個線程池(要實現org.quartz.spi.ThreadPool接口的線程池),一般用org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount  線程池線程數量,根據自己情況定,最好不要超過100
org.quartz.threadPool.threadPriority  線程優先級,1-10,數字越小優先級越高,一般用5即可。
org.quartz.scheduler.instanceName
調度器的名字
org.quartz.scheduler.instanceId
爲調度器創建一個Key值,這個Key必須在所有調度器中唯一,一般填寫AUTO,讓quartz自動生成。
org.quartz.jobStore.class
任務調度存儲(需要實現org.quartz.spi.JobStore接口的實例),一般用org.quartz.impl.jdbcjobstore.JobStoreTX

 

十一、工具類

上文大致把quartz基本內容概述完畢,下一篇博客將會進行高級內容概述,在此之前,先奉上本人自己寫的一個quartz任務調度工具類,能夠及其方便的根據間隔或corn表達式調度任意一個類的某個方法,代碼如下:

public class SchedulerUtils {

    private static StdSchedulerFactory schedulerfactory = new StdSchedulerFactory();



    public static final int SECONDS = 1;

    public static final int MINUTES = 2;

    public static final int HOURS = 3;


    private static String CLASS_KEY = "CLASS-KEY";
    private static String METHOD_KEY = "METHOD-KEY";
    private static String PARAMS_KEY = "PARAMS-KEY";

    /**
     * 初始化StdSchedulerFactory
     * @param map 初始化參數
     * @throws SchedulerException
     */
    public static void init(Map<String,String> map) throws SchedulerException {
        Properties properties = new Properties();
        for(Map.Entry<String, String> entry : map.entrySet()) {
            properties.setProperty(entry.getKey(),entry.getValue());
        }
        init(properties);
    }

    public static void init(Properties properties) throws SchedulerException {
        schedulerfactory.initialize(properties);
    }

    /**
     *  按Cron表達式定時執行
     * @param clazzName 全類名
     * @param methodName 方法名
     * @param args 方法參數
     * @param cron cron表達式
     * @throws Exception
     */
    public static void executeJobCron(String clazzName, String methodName, List<Object> args,String cron) throws Exception {
        executeJobCron(clazzName,methodName,args,cron,null,null);
    }

    /**
     *  按Cron表達式定時執行
     * @param clazzName 全類名
     * @param methodName 方法名
     * @param args 方法參數
     * @param cron cron表達式
     * @param startDate 開始時間,如果馬上開始填寫null或 new Date()即可
     * @param endDate 結束時間,如果沒有結束時間則填寫null即可
     * @throws Exception
     */
    public static void executeJobCron(String clazzName, String methodName, List<Object> args,String cron,Date startDate,Date endDate) throws Exception {
        JobDetail jobDetail = jobDetailHandle(clazzName, methodName, args);
        Trigger trigger = cronTriggerTimeHandle(cron,startDate,endDate);
        Scheduler scheduler = getScheduler();
        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();
    }


    public static void executeJob(String clazzName, String methodName, List<Object> args, int timeUnit, int interval, Date endDate) throws Exception{
        executeJob(clazzName,methodName,args,timeUnit,interval,-1,null,endDate);
    }


    public static void executeJob(String clazzName, String methodName, List<Object> args, int timeUnit, int interval)  throws Exception{
        executeJob(clazzName,methodName,args,timeUnit,interval,-1,null,null);
    }

    public static void executeJob(String clazzName, String methodName, List<Object> args, int timeUnit, int interval, int count)  throws Exception{
        executeJob(clazzName,methodName,args,timeUnit,interval,count,null,null);
    }


    /**
     *  按照間隔時間定時執行
     * @param clazzName 全類名
     * @param methodName 方法名
     * @param args 方法參數
     * @param timeUnit 時間單位,參考本類屬性定義
     * @param interval 間隔長度
     * @param count 執行總數,如果執行總數和結束時間都有,則按結束時間。
     * @param startDate 開始時間,如果馬上開始填寫null或 new Date()即可
     * @param endDate 結束時間,如果沒有結束時間則填寫null即可
     * @throws Exception
     */
    public static void executeJob(String clazzName, String methodName, List<Object> args, int timeUnit, int interval, int count,Date startDate,Date endDate)  throws Exception {
        JobDetail jobDetail = jobDetailHandle(clazzName, methodName, args);
        Trigger trigger = simpleTriggerTimeHandle(timeUnit,interval, count,startDate,endDate);
        Scheduler scheduler = getScheduler();
        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();
    }

    private static JobDetail jobDetailHandle(String clazzName, String methodName, List<Object> args) throws NoSuchMethodException, ClassNotFoundException {
        JobDataMap jobDataMap = new JobDataMap();
        Class clazz = Class.forName(clazzName);
        Method method = findMethod(clazz,methodName,args);
        jobDataMap.put(CLASS_KEY,clazz);
        jobDataMap.put(METHOD_KEY,method);
        jobDataMap.put(PARAMS_KEY,args);
        JobDetail jobDetail = JobBuilder.newJob(TaskJob.class)
                .withIdentity("job")
                .usingJobData(jobDataMap)
                .build();
        return jobDetail;
    }

    private static Trigger simpleTriggerTimeHandle(int timeUnit, int interval, int count, Date startDate,Date emdDate) {
        TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger()
                .withIdentity("simpleTrigger");
        if(startDate == null) {
            startDate = new Date();
        }
        triggerBuilder.startAt(startDate);
        triggerBuilder.endAt(emdDate);
        if(count > 0) {
            switch (timeUnit) {
                case SECONDS : triggerBuilder.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(count,interval));
                    break;
                case MINUTES : triggerBuilder.withSchedule(SimpleScheduleBuilder.repeatMinutelyForTotalCount(count,interval));
                    break;
                case HOURS : triggerBuilder.withSchedule(SimpleScheduleBuilder.repeatHourlyForTotalCount(count,interval));
                    break;
            }
        }
        return triggerBuilder.build();
    }

    private static Trigger cronTriggerTimeHandle(String cron,Date startDate,Date emdDate) throws ParseException {
        new CronExpression(cron);
        if(startDate == null) {
            startDate = new Date();
        }
        Trigger trigger =  TriggerBuilder.newTrigger()
                .withIdentity("cronTrigger")
                .startAt(startDate)
                .endAt(emdDate)
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .build();
        return trigger;
    }

    private static Scheduler getScheduler() throws SchedulerException {
        return schedulerfactory.getScheduler();
    }

    private static Method findMethod(Class clazz,String methodName,List<Object> args) throws NoSuchMethodException {
        Method method;
        if(args != null && !args.isEmpty()) {
            Class<?>[] paramsTypes = getMethodParamsType(args);
            method = clazz.getDeclaredMethod(methodName,paramsTypes);
        }else {
            method = clazz.getDeclaredMethod(methodName);
        }
        return method;
    }


    private static Class<?>[] getMethodParamsType(List<Object> methodParams) {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object os : methodParams)
        {
            classs[index] = os.getClass();
            index++;
        }
        return classs;
    }

    public static class TaskJob implements Job {

        private Map<Class,Object> objectMap = new ConcurrentHashMap<Class, Object>();

        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            JobDataMap dataMap = jobExecutionContext.getMergedJobDataMap();
            Class clazz = (Class) dataMap.get(CLASS_KEY);
            Object object;
            try {
                object = getObject(clazz);
                Method method = (Method) dataMap.get(METHOD_KEY);
                Parameter[] parameters = method.getParameters();
                if (parameters.length > 0) {
                    List<Object> args = (List<Object>) dataMap.get(PARAMS_KEY);
                    Object[] objects = args.toArray();
                    method.invoke(object, objects);
                }else {
                    method.invoke(object);
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }

        private Object getObject(Class clazz) throws IllegalAccessException, InstantiationException {
            Object object = objectMap.get(clazz);
            if(object == null) {
                object = clazz.newInstance();
                objectMap.put(clazz,object);
            }
            return object;
        }
    }
}

        

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章