Spring 和 Quartz 實現定時功能

Spring 和 Quartz 實現定時功能

在 pom.xml 中添加必須的包:

<!-- QuartzJobBean in spring-context-support.jar -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
</dependency>       

<!-- Spring + Quartz need transaction -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
</dependency>

<!-- Quartz framework -->
<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
</dependency>

首先要了解幾個核心的概念:
Job:定時器要執行的任務;
JobDetail:定義任務的描述信息;
Trigger:定義任務如何執行,比如間隔多久,執行次數等;
Scheduler:管理任務的執行。

定義 Job——實現 Job 接口

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SimpleJob implements Job {
    private static Logger logger = LoggerFactory.getLogger(SimpleJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        Trigger trigger = jobExecutionContext.getTrigger();
        logger.info("execute {} with trigger: {}", jobDetail.getKey().getName(), 
                    trigger.getDescription());
    }
}

xml 配置:

<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-3.0.xsd">

    <!-- 定義 JobDetail -->
    <bean name="runJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.example.job.SimpleJob"/>
        <property name="name" value="mySimpleJob"/>
    </bean>

    <!-- 定義 SimpleTrigger 每隔5秒執行一次  -->
    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="runJobDetail"/>
        <property name="repeatInterval" value="5000"/>
        <property name="startDelay" value="1000"/>
        <property name="description" value="mySimpleTrigger"/>
    </bean>

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

</beans>

Java 配置:

@Configuration
public class SpringJobConfig {

    @Bean
    public JobDetailFactoryBean runJobDetail() {
        JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
        jobDetailFactoryBean.setJobClass(SimpleJob.class);
        // 使用類名作爲job名稱
        jobDetailFactoryBean.setName(SimpleJob.class.getSimpleName());
        return jobDetailFactoryBean;
    }

    @Bean
    public SimpleTriggerFactoryBean simpleTrigger(JobDetail runJobDetail) {
        SimpleTriggerFactoryBean simpleTriggerFactoryBean = new SimpleTriggerFactoryBean();
        simpleTriggerFactoryBean.setJobDetail(runJobDetail);
        simpleTriggerFactoryBean.setRepeatInterval(5000);
        simpleTriggerFactoryBean.setStartDelay(1000);
        simpleTriggerFactoryBean.setDescription("mySimpleTrigger");
        return simpleTriggerFactoryBean;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(Trigger simpleTrigger) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setTriggers(simpleTrigger);
        return schedulerFactoryBean;
    }
}

自定義 Job 以及 CronTrigger

定義要執行任務的類,不需要實現 Job 接口:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomJob {
    private static Logger logger = LoggerFactory.getLogger(CustomJob.class);

    public static void execute() {
        logger.info("execute CustomJob with static method");
    }

    public void run() {
        logger.info("execute CustomJob with non-static method");
    }
}

類的任何方法都可以作爲定時任務執行,既可以指定靜態方法,也可以指定非靜態方法,需要用 MethodInvokingJobDetailFactoryBean 定義 JobDetail:

    <bean id="customJob" class="com.example.job.CustomJob"/>

    <bean id="customRunJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 使用 targetClass 的話,需要在 targetMethod 中指定靜態方法 -->
<!--        <property name="targetClass" value="com.example.job.CustomJob"/>-->
<!--        <property name="targetMethod" value="execute"/>-->
        <!-- 使用 targetClass 的話,需要在 targetMethod 中指定靜態方法 -->
        <property name="targetObject" ref="customJob"/>
        <property name="targetMethod" value="run"/>
    </bean>

    <!-- Cron Trigger, run every 5 seconds -->
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="customRunJobDetail"/>
        <property name="cronExpression" value="0/3 * * * * ?"/>
        <property name="description" value="myCronTrigger"/>
    </bean>

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

java 配置:

    @Bean
    public MethodInvokingJobDetailFactoryBean customJobDetail(CustomJob customJob) {
        MethodInvokingJobDetailFactoryBean jobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
        // 定義靜態方法
//        jobDetailFactoryBean.setTargetClass(CustomJob.class);
        jobDetailFactoryBean.setTargetObject(customJob);
        jobDetailFactoryBean.setTargetMethod("run");
        jobDetailFactoryBean.setName(customJob.getClass().getSimpleName());
        return jobDetailFactoryBean;
    }

    @Bean
    public CronTriggerFactoryBean cronTrigger(JobDetail customJobDetail) {
        CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
        cronTriggerFactoryBean.setJobDetail(customJobDetail);
        cronTriggerFactoryBean.setCronExpression("0/3 * * * * ?");
        cronTriggerFactoryBean.setDescription("myCronTrigger");
        return cronTriggerFactoryBean;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(Trigger simpleTrigger, Trigger cronTrigger) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setTriggers(simpleTrigger, cronTrigger);
        return schedulerFactoryBean;
    }

定義是否啓動任務

在 xml 中無法自定義任務是否啓動,只要在 SchedulerFactoryBean 添加了某個 Trigger,服務啓動之後就會運行任務。

在 Java 中,可以通過判斷配置文件中的配置,來決定是否要把某個 Trigger 添加到 SchedulerFactoryBean 中。

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(Trigger simpleTrigger, Trigger cronTrigger) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        List<Trigger> triggerList = new ArrayList<>();

        if (jobSwitch.contains(simpleTrigger.getJobKey().getName() + "+on")) {
            triggerList.add(simpleTrigger);
        }
        if (jobSwitch.contains(cronTrigger.getJobKey().getName() + "+on")) {
            triggerList.add(cronTrigger);
        }
        schedulerFactoryBean.setTriggers(triggerList.toArray(new Trigger[0]));
        return schedulerFactoryBean;
    }

參考:
https://www.baeldung.com/spring-quartz-schedule

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