1. 程式人生 > >Spring整合Quartz的3種方式

Spring整合Quartz的3種方式

1.使用xml配置方式

Maven依賴

    <properties>
        <!-- spring版本號 -->
        <spring.version>4.2.2.RELEASE</spring.version>                      <!-- Quartz的版本 -->
    </properties>
    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.2</version>
        </dependency>

application.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 配置Job類 -->
    <bean id="myJob" class="cn.enjoyedu.quartz.xml.CronJob"></bean>

    <!-- 配置JobDetail -->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 執行目標job -->
        <property name="targetObject" ref="myJob"></property>

        <!-- 要執行的方法 -->
        <property name="targetMethod" value="execute"></property>
    </bean>

    <!-- 配置tirgger觸發器 -->
    <bean id="cronTriggerFactoryBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <!-- jobDetail -->
        <property name="jobDetail" ref="jobDetail"></property>

        <!-- cron表示式,執行時間  每5秒執行一次 -->
        <property name="cronExpression" value="0/5 * * * * ?"></property>
    </bean>

    <!-- 配置排程工廠 -->
    <bean id="springJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTriggerFactoryBean"></ref>
            </list>
        </property>

    </bean>

    <!--<bean id="simpleTrigger"  class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">-->
        <!--&lt;!&ndash;配置具體要執行的jobDetail&ndash;&gt;-->
        <!--<property name="jobDetail" ref="simpleJobDetail" />-->
        <!--&lt;!&ndash;初始延遲時間 1s&ndash;&gt;-->
        <!--<property name="startDelay" value="1000" />-->
        <!--&lt;!&ndash;間隔執行時間每2s執行一次&ndash;&gt;-->
        <!--<property name="repeatInterval" value="2000" />-->
    <!--</bean>-->
</beans>

Job類

package cn.enjoyedu.quartz.xml;

public class CronJob {
    public void execute(){
        System.out.println("定時任務執行...每5秒執行一次");
    }
}

測試類

package cn.enjoyedu.quartz.xml;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringQuartzXmlTest {
    public static void main(String[] args) {
        //啟動spring容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        System.out.println("initContext successfully");
    }
}

執行結果

initContext successfully
定時任務執行...每5秒執行一次
定時任務執行...每5秒執行一次

2.註解方式

application.xml

    <!-- 開啟元件掃描 -->
    <context:component-scan base-package="cn.enjoyedu.quartz.annotation"></context:component-scan>
    <!-- 開啟定時任務,spring的定時任務。不是原生quartz -->
    <task:annotation-driven/>

Job class

package cn.enjoyedu.quartz.annotation;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class AnnotationJob {
    @Scheduled(cron = "0/5 * * * * ?")
    public void excute(){
        System.out.println("AnnotationJob 執行 5秒1次");
    }
}

執行結果

initContext successfully
AnnotationJob 執行 5秒1次
AnnotationJob 執行 5秒1次

3.支援資料庫配置cron表示式

3.1TimetaskController

@RequestMapping(value = "/initJob", method = RequestMethod.POST)
    @ResponseBody
    public String initJob() {
        try {
            ObjectResult result = timetaskBiz.initJob();
            return JSONHelper.toJsonDataAPI(result, result.getApiStatus(), result.getErrorMsg());
        } catch (Exception e) {
            return JSONHelper.toJsonErrorDataAPI(e);
        }
    }

3.2 初始化job和啟動job

    /**
     * 初始化job
     * @param timetask
     */
    @Override
    public ObjectResult initJob() {
        ObjectResult result = new ObjectResult();
        try {
            Scheduler scheduler = factoryBean.getScheduler();
            //這裡從資料庫中獲取任務資訊資料
            Timetask timetask = new Timetask();
            //0 表示定時任務停止中  1 表示定時任務執行中
            timetask.setJobStatus("0");
            //從資料庫中查詢定時印務記錄。
            List<Timetask> timetaskList =  this.getTimetaskListCus(timetask).getListTimetask();
            for (Timetask task : timetaskList) {
                addJob(task);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            result.setErrorMsg(e.getMessage());
            result.setApiStatus(ApiData.STATUS_EXCEPTION);
        }
        return result;
    }
    
    

     /**
     * 新增job
     * @param timetask
     */
    private void addJob(Timetask timetask) {
        if(timetask == null || (timetask.getJobStatus() == ScheduleJob.STATUS_RUNNING)) {
            return;
        }

        try {
            Scheduler scheduler = factoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(timetask.getName(),timetask.getGroupName());
            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //如果不存在cronTrigger則重新建立一個
            if(null == cronTrigger){
                Class clazz = null;
                try {
                    clazz = Class.forName(timetask.getBeanClass());
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                JobDetail  jobDetail = JobBuilder.newJob(clazz)
                        .withIdentity(timetask.getName(),timetask.getGroupName())
                        .usingJobData("data","")
                        .build();
                jobDetail.getJobDataMap().put("scheduleJob",timetask);
                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(timetask.getCron());
                cronTrigger = TriggerBuilder.newTrigger().withDescription(timetask.getIdStr())
                        .withIdentity(timetask.getName(),timetask.getGroupName())
                        .withSchedule(cronScheduleBuilder)
                        .build();

                scheduler.scheduleJob(jobDetail,cronTrigger);
            } else {

                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(timetask.getCron());
                //TODO usingJobData的引數
                cronTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey).usingJobData("data","")
                        .withSchedule(cronScheduleBuilder).build();
                scheduler.rescheduleJob(triggerKey,cronTrigger);
            }
            //執行
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

3.3 job類

package com.zt.uni.api.task.jobs;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("MyJob ... execute ...");
    }
}

package com.zt.uni.api.task.jobs;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob2 implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("MyJob2 ... execute ...");
    }
}

3.4 資料庫配置

image

3.5 執行結果

MyJob ... execute ...
MyJob2 ... execute ...
MyJob ... execute ...
MyJob ... execute ...
MyJob2 ... execute ...
MyJob ... execute ...
MyJob ... execute ...

3.6 存在的問題(最近工作忙,後面再補回來)

  • 如果要支援定時任務可以拔插式使用
  • 要支援圖形介面配置
  • 要支援定時任務在某個時間段期間執行[start_time ,end_time]執行
  • 要支援記錄定時任務的異常資訊