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;
}