SpringBoot 实现定时任务有两种方式,其中包括有 Scheduled 定时器整合 Quartz 定时任务框架,前者简单易上手,但功能较单一,但也能实现大部分需求,后者是一个强大的定时任务框架,但较复杂。接下来分别介绍这两种方式如何使用。

一、通过 Scheduled 定时器实现定时任务

  Scheduled 是 Spring 款架提供的,自 Spring 3.0 开始就提供注解的方式实现定时任务。

1. 在 POM 文件添加 Scheduled

  在 pom.xml 中加入 spring-context-support ,在此之前可以检查一下是否已经有该 JAR ,有就不需要再加了。

<!-- Scheduled 坐标 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
</dependency>
2. 编写定时任务类
package com.task;

import java.util.Date;

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

/**
 * @Description Scheduled 定时任务器
 * @author 欧阳
 * @since 2019年4月14日 下午2:16:42
 * @version V1.0
 */

@Component
public class ScheduledDemo {

	//每两秒执行一次
	@Scheduled(cron = "*/2 * * * * ?")
	public void scheduledMethod() {
		System.out.println("Scheduled 定时器被触发:" + new Date());
	}
}

   使用 @Component 注解是为了让 SpringBoot 能够自动扫包时扫到,@Scheduled 支持 cron 表达式,也支持其他属性,参考 @Scheduled 源码。 cron 表达式 表达式语法参考文章 cron 表达式详解

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {

	/**
	 * A cron-like expression, extending the usual UN*X definition to include
	 * triggers on the second as well as minute, hour, day of month, month
	 * and day of week.  e.g. {@code "0 * * * * MON-FRI"} means once per minute on
	 * weekdays (at the top of the minute - the 0th second).
	 * @return an expression that can be parsed to a cron schedule
	 * @see org.springframework.scheduling.support.CronSequenceGenerator
	 */
	String cron() default "";

	/**
	 * A time zone for which the cron expression will be resolved. By default, this
	 * attribute is the empty String (i.e. the server's local time zone will be used).
	 * @return a zone id accepted by {@link java.util.TimeZone#getTimeZone(String)},
	 * or an empty String to indicate the server's default time zone
	 * @since 4.0
	 * @see org.springframework.scheduling.support.CronTrigger#CronTrigger(String, java.util.TimeZone)
	 * @see java.util.TimeZone
	 */
	String zone() default "";

	/**
	 * Execute the annotated method with a fixed period in milliseconds between the
	 * end of the last invocation and the start of the next.
	 * @return the delay in milliseconds
	 */
	long fixedDelay() default -1;

	/**
	 * Execute the annotated method with a fixed period in milliseconds between the
	 * end of the last invocation and the start of the next.
	 * @return the delay in milliseconds as a String value, e.g. a placeholder
	 * or a {@link java.time.Duration#parse java.time.Duration} compliant value
	 * @since 3.2.2
	 */
	String fixedDelayString() default "";

	/**
	 * Execute the annotated method with a fixed period in milliseconds between
	 * invocations.
	 * @return the period in milliseconds
	 */
	long fixedRate() default -1;

	/**
	 * Execute the annotated method with a fixed period in milliseconds between
	 * invocations.
	 * @return the period in milliseconds as a String value, e.g. a placeholder
	 * or a {@link java.time.Duration#parse java.time.Duration} compliant value
	 * @since 3.2.2
	 */
	String fixedRateString() default "";

	/**
	 * Number of milliseconds to delay before the first execution of a
	 * {@link #fixedRate()} or {@link #fixedDelay()} task.
	 * @return the initial delay in milliseconds
	 * @since 3.2
	 */
	long initialDelay() default -1;

	/**
	 * Number of milliseconds to delay before the first execution of a
	 * {@link #fixedRate()} or {@link #fixedDelay()} task.
	 * @return the initial delay in milliseconds as a String value, e.g. a placeholder
	 * or a {@link java.time.Duration#parse java.time.Duration} compliant value
	 * @since 3.2.2
	 */
	String initialDelayString() default "";

}
3. 启动类中开启定时任务的使用

  在启动类上加上注解 @EnableScheduling 开启定时任务的使用。

package com;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
* @Description 第一个SpringBoot 应用启动类
* @author 欧阳
* @since 2019年4月3日 下午6:14:39
* @version V1.0
*/

@SpringBootApplication
@EnableScheduling
public class App {

	public static void main(String[] args) {
		
		SpringApplication.run(App.class, args);
	}

}

二、通过整合 Quartz 框架实现定时任务

  Quartz 官网:http://www.quartz-scheduler.org/

使用 Quartz 分为三步:
    a. 创建 Job - 任务(要做什么事?)
    b. 创建 Trigger - 触发器 (什么时候去做?)
    c. 创建 Scheduler - 任务调度(什么时候去做什么事?)

1. 在 POM 文件添加 Quartz

  在 pom.xml 文件添加 Quartz

<!-- 添加 quartz -->
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<exclusions>
		<exclusion>
			<artifactId>slf4j-api</artifactId>
			<groupId>org.slf4j</groupId>
		</exclusion>
	</exclusions>
</dependency>
2. 创建 Job 类

  创建一个实现 Job 接口的 Job 类

package com.task;

import java.util.Date;

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

/**
* @Description 定义任务类
* @author 欧阳
* @since 2019年4月14日 下午6:05:13
* @version V1.0
*/

public class QuartzDemo implements Job {

	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		
		System.out.println("Execute:" + new Date());
	}

}
3. 编写 Quartz 的启动类,注入 Spring 容器

   Trigger 有 SimpleTriggerFactoryBeanCronTriggerFactoryBean 等,SimpleTriggerFactoryBean 简单的 Trigger ,可通过其中方法设置什么时候做,而 CronTriggerFactoryBean 通过设置 cron 表达式 来设置什么时候做。cron 表达式 表达式语法参考文章 cron 表达式详解

package com.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.task.QuartzDemo;

/**
 * @Description Quartz 配置类
 * @author 欧阳
 * @since 2019年4月14日 下午6:07:01
 * @version V1.0
 */

@Configuration
public class QuartzConfig {

	/**
	 * 1.创建 Job 对象
	 */
	@Bean
	public JobDetailFactoryBean jobDetailFactoryBean() {
		JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();

		// 关联Job 类
		jobDetailFactoryBean.setJobClass(QuartzDemo.class);

		return jobDetailFactoryBean;
	}

	/**
	 * 2.创建 Trigger 对象
	 */
	@Bean
	public CronTriggerFactoryBean cronTriggerFactoryBeanBean(JobDetailFactoryBean jobDetailFactoryBean) {
		CronTriggerFactoryBean cronTriggerFactoryBeanBean = new CronTriggerFactoryBean();

		// 关联 JobDetail 对象
		cronTriggerFactoryBeanBean.setJobDetail(jobDetailFactoryBean.getObject());
		// 每两秒执行一次
		cronTriggerFactoryBeanBean.setCronExpression("*/2 * * * * ?");

		return cronTriggerFactoryBeanBean;
	}

	/**
	 * 3.创建 Scheduler 对象
	 */
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBeanBean) {
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
		// 关联 trigger
		schedulerFactoryBean.setTriggers(cronTriggerFactoryBeanBean.getObject());
		
		return schedulerFactoryBean;
	}
}
4. 启动类中开启定时任务的使用

  在启动类上加上注解 @EnableScheduling 开启定时任务的使用。

package com;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
* @Description 第一个SpringBoot 应用启动类
* @author 欧阳
* @since 2019年4月3日 下午6:14:39
* @version V1.0
*/

@SpringBootApplication
@EnableScheduling
public class App {

	public static void main(String[] args) {
		
		SpringApplication.run(App.class, args);
	}

}