SpringBoot提供了非常方便使用的定时任务功能。同时也支持Quartz
。
@Configuration
@EnableScheduling
public class SchedulerConfig {
}
// 每5秒执行一次
@Scheduled(fixedDelay = 5000)
public void doSomething() {
// something that should run periodically
}
// cron表达式
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should run on weekdays only
}
pom.xml中加入以下代码:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
自动装配器SchedulerFactoryBean
会提供Scheduler
对象以供使用。
相关配置:
# 集群环境需要使用jdbc。默认:memory
#spring.quartz.job-store-type: jdbc
# quartz是否集群
#spring.quartz.properties.org.quartz.jobStore.isClustered: true
# jdbc模式需要指定驱动委托类。官方文档:https://www.quartz-scheduler.org/documentation/quartz-2.3.0/configuration/ConfigJobStoreTX.html
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.MSSQLDelegate
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.SybaseDelegate
#spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.HSQLDBDelegate
# 通过Spring配置生成的Job,是否覆盖持久化到数据库的Job。需要设置成true。默认:false
spring.quartz.overwrite-existing-jobs: true
# 使用liquibase初始化数据库,要使用 never。默认:embedded
spring.quartz.jdbc.initialize-schema: never
通常使用Quartz都是因为需要支持集群,集群则需要创建数据库表。
可以手动创建创建表结构,SQL脚本在quartz
的jar包中org/quartz/impl/jdbcjobstore/
目录下,可以根据数据库类型选择相应的脚本。
如果系统中使用了liquibase
,则简单很多,直接包含org/quartz/impl/jdbcjobstore/liquibase.quartz.init.xml
文件即可。
databaseChangeLog:
- include:
file: org/quartz/impl/jdbcjobstore/liquibase.quartz.init.xml
example.ExampleJob
需要继承QuartzJobBean
:
package example;
@Component
public class ExampleJob extends QuartzJobBean {
// fields ...
private MyService myService;
// 支持注入Spring托管对象
// Inject "MyService" bean
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
private int timeout;
/**
* Setter called after the ExampleJob is instantiated
* with the value from the JobDetailFactoryBean (5)
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
}
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
// do the actual work
}
}
xml配置文件:
<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="example.ExampleJob"/>
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="5"/>
</map>
</property>
<!-- 没有绑定触发器时,必须设置持久性为 true -->
<property name="durability" value="true"/>
</bean>
java配置类(可代替xml配置文件):
@Bean
public JobDetailFactoryBean createExampleJob() {
final JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(ExampleJob.class);
JobDataMap dataMap = new JobDataMap();
dataMap.put("timeout", 5);
jobDetailFactory.setJobDataMap(dataMap);
// 没有绑定触发器时,必须设置持久性为 true
jobDetailFactory.setDurability(true);
return jobDetailFactory;
}
如果只是想简单的执行某一个方法,不想继承QuartzJobBean
,可以使用这种方式。但这种方式不支持Quartz jdbc模式(集群需要开启jdbc模式):
@Component("exampleBusinessObject")
public class ExampleBusinessObject {
public void doIt() {
// do the actual work
}
}
xml配置文件:
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="exampleBusinessObject"/>
<property name="targetMethod" value="doIt"/>
</bean>
java配置类(可代替xml配置文件):
@Bean
public MethodInvokingJobDetailFactoryBean createBusinessJob(ExampleBusinessObject exampleBusinessObject) {
final MethodInvokingJobDetailFactoryBean jobDetailFactory = new MethodInvokingJobDetailFactoryBean();
jobDetailFactory.setTargetObject(exampleBusinessObject);
jobDetailFactory.setTargetMethod("doIt");
return jobDetailFactory;
}
xml 配置:
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<!-- see the example of method invoking job above -->
<property name="jobDetail" ref="jobDetail"/>
<!-- 10 seconds -->
<property name="startDelay" value="10000"/>
<!-- repeat every 50 seconds -->
<property name="repeatInterval" value="50000"/>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="exampleJob"/>
<!-- run every morning at 6 AM -->
<property name="cronExpression" value="0 0 6 * * ?"/>
</bean>
java配置类(可代替xml配置文件):
和之前类似,代码略...
SpringBoot环境下不需要这一步。SpringBoot会自动创建SchedulerFactoryBean
,并把Trigger
加入其中。
如果没有使用SpringBoot,直接使用Spring,则需要手动配置。为了更好理解SchedulerFactoryBean
的工作原理,这里列出了Spring环境下相应的代码:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
<ref bean="simpleTrigger"/>
</list>
</property>
</bean>
Spring Scheduler是非常轻量级的任务调度器,如果你只需要做一些简单的定时任务,直接使用它就好了。
Quartz Scheduler提供了很多高级功能,最主要的就是支持集群。如果需要做集群,就选择它。