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