玩轉 SpringBoot 2 之整合定時任務篇

前言

通過本文你將瞭解到如何在 SpringBoot 2 中整合定時任務使用教程,具體詳細內容如下:

  • SpringBoot 自帶定時任務使用教程
  • SpringBoot 集成 JDK 定時任務使用教程
  • SpringBoot 集成 quartz 使用教程

閱讀前需要你必須瞭解如何搭建 SpringBoot 項目。

SpringBoot 自帶定時任務使用教程

使用 SpringBoot 自帶的任務調度攏共需要2步:

第一步:在SpringBoot 啓動類上聲明 @EnableScheduling,具體代碼如下:


@SpringBootApplication
@EnableScheduling
public class SpringbootlearnApplication {
	private static final Logger log = LoggerFactory.getLogger(SpringbootexamplesApplication.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	public static void main(String[] args) {
		SpringApplication.run(SpringbootexamplesApplication.class, args);
		 log.info("reportCurrentTimeInitialDelay fixedRate The time is start {}", dateFormat.format(new Date()));
	}
}

Spring Bean 方法上聲明 @Scheduled 並在註解中指定啓動的規則,具體代碼如下:

@Component
public class SchedulerTask {
	
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	//固定的時間執行 也就是 5秒執行一次
    @Scheduled(fixedRate = 5000)
    public void reportCurrentTimeFixedRate() {
    	try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        log.info("reportCurrentTimeFixedRate The time is now {}", dateFormat.format(new Date()));
    }
}

測試結果:

fixedRate: 任務執行的時間是6秒,設置任務時間間隔5秒,實際按每6秒執行一次。

2019-11-17 18:32:46.484  INFO 128312 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 18:32:46
2019-11-17 18:32:52.428  INFO 128312 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:32:52
2019-11-17 18:32:58.428  INFO 128312 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:32:58
2019-11-17 18:33:04.428  INFO 128312 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:33:04
2019-11-17 18:33:10.429  INFO 128312 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:33:10
2019-11-17 18:33:16.429  INFO 128312 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:33:16

fixedRate: 任務執行的時間是3秒,設置任務時間間隔5秒執行一次,實際按每5秒執行一次。

2019-11-17 18:38:34.210  INFO 127372 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 18:38:34
2019-11-17 18:38:37.148  INFO 127372 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:38:37
2019-11-17 18:38:42.145  INFO 127372 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:38:42
2019-11-17 18:38:47.145  INFO 127372 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:38:47
2019-11-17 18:38:52.147  INFO 127372 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:38:52
2019-11-17 18:38:57.147  INFO 127372 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeFixedRate The time is now 18:38:57

任務執行的時間通過在 SchedulerTask 的 reportCurrentTimeFixedRate 方法中通過Thread.sleep(6*1000)來實現。而任務時間間隔通過 fixedRate 來進行設置 5000 就是 5秒

Scheduled 註解經常使用參數設置項:

  • fixedRate :固定的時間執行 也就是 多少秒執行一次。 這個上面的代碼已介紹。
  • fixedDelay:執行完畢後再過5秒後執行。
  • initialDelay:啓動後延遲多少秒後執行 不能單獨使用。

fixedDelayinitialDelay 設置項的 Demo 案例:


@SpringBootApplication
@EnableScheduling
public class SpringbootlearnApplication {
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); 
	public static void main(String[] args) {
		SpringApplication.run(SpringbootlearnApplication.class, args);
		 log.info("reportCurrentTimeInitialDelay fixedRate The time is start {}", dateFormat.format(new Date()));
	}
}


@Component
public class SchedulerTask {
	
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled(initialDelay=0, fixedDelay=5000)
    public void reportCurrentTimeInitialDelay() {
    	try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        log.info("reportCurrentTimeInitialDelay fixedRate The time is now {}", dateFormat.format(new Date()));
    }
	
}

測試結果:

fixedDelay:任務執行的時間是6秒,設置任務執行完後時5秒後在執行,實際按每11秒執行一次

2019-11-17 18:47:28.977  INFO 130308 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 18:47:28
2019-11-17 18:47:54.916  INFO 130308 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:47:54
2019-11-17 18:48:05.918  INFO 130308 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:48:05
2019-11-17 18:48:16.920  INFO 130308 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:48:16
2019-11-17 18:48:27.923  INFO 130308 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:48:27

fixedDelay:任務執行的時間是3秒,設置任務執行完後時5秒後在執行,實際按每8秒執行一次

2019-11-17 18:57:10.370  INFO 129352 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 18:57:10
2019-11-17 18:57:33.306  INFO 129352 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:57:33
2019-11-17 18:57:41.308  INFO 129352 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:57:41
2019-11-17 18:57:49.310  INFO 129352 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:57:49
2019-11-17 18:57:57.312  INFO 129352 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:57:57
2019-11-17 18:58:05.314  INFO 129352 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:58:05
2019-11-17 18:58:13.317  INFO 129352 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:58:13
2019-11-17 18:58:21.319  INFO 129352 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : reportCurrentTimeInitialDelay fixedRate The time is now 18:58:21

同時 Scheduled 還支持 cron 表達式方式,具體是用方式如下:

@Component
public class SchedulerTaskForCron {
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	/**
	 * 每天的14:00 執行一次
	 */
	@Scheduled(cron="0 0 14 * * ?")
	private void cron() {
		 log.info("cron The time is now {}", dateFormat.format(new Date()));
	}
	
	/**
	 * 每5秒執行一次
	 */
	@Scheduled(cron="0/5 * * * * ?")
	private void cron2() {
		try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("cron2 The time is now {}", dateFormat.format(new Date()));
	}
}

測試結果:

任務執行的時間是6秒 設置任務時間間隔5秒 實際按每10秒執行一次

2019-11-17 19:10:47.072  INFO 132132 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 19:10:47
2019-11-17 19:10:56.001  INFO 132132 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : cron2 The time is now 19:10:56
2019-11-17 19:11:06.000  INFO 132132 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : cron2 The time is now 19:11:06
2019-11-17 19:11:16.002  INFO 132132 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : cron2 The time is now 19:11:16
2019-11-17 19:11:26.003  INFO 132132 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : cron2 The time is now 19:11:26
2019-11-17 19:11:36.001  INFO 132132 --- [   scheduling-1] cn.lijunkui.task.own.SchedulerTask       : cron2 The time is now 19:11:36

關於cron使用規則 網上有很多在線生成工具 例如:http://www.bejson.com/othertools/cron/

SpringBoot 集成 JDK 定時任務使用教程

Timer 方式

第一步:定義定時任務多線程 Demo 程序,繼承TimerTask並實現 run 方法,具體代碼如下:

public class DemoTask extends TimerTask{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Override
	public void run() {
		try {
			Thread.sleep(4*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 log.info("DemoTask The time is now {}", dateFormat.format(new Date()));
	}

}

然後通過Timer 的 schedule 方法完成定時任務的操作,具體代碼如下:


public class TimerManger {
	private DemoTask demoTask;
	public TimerManger(DemoTask demoTask) {
		this.demoTask = demoTask;
	}
	public void run() throws ParseException {
		Timer timer = new Timer();
	
		long intevalPeriod = 3 * 1000;
		long delay = 0;
		//該方法是衝現在時間開始每3秒執行一次
		timer.schedule(demoTask, new Date(), intevalPeriod);
	}
}

最後定義項目啓動就執行的 Runner 程序,具體代碼如下:

package cn.lijunkui.task.jdk;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(value = 1)
public class DemoTaskRunner implements ApplicationRunner{

	@Override
	public void run(ApplicationArguments args) throws Exception {
		TimerTest test = new TimerTest(new DemoTask());
		test.run();
	}
}

測試結果:

schedule: DemoTask 任務執行時間是4秒 設置的時間間隔是3秒 我們的任務是每4秒執行一次

2019-11-17 20:49:14.712  INFO 139860 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 20:49:14
2019-11-17 20:49:18.712  INFO 139860 --- [        Timer-0] cn.lijunkui.task.own.SchedulerTask       : DemoTask The time is now 20:49:18
2019-11-17 20:49:22.712  INFO 139860 --- [        Timer-0] cn.lijunkui.task.own.SchedulerTask       : DemoTask The time is now 20:49:22
2019-11-17 20:49:26.713  INFO 139860 --- [        Timer-0] cn.lijunkui.task.own.SchedulerTask       : DemoTask The time is now 20:49:26

scheduleAtFixedRate: DemoTask 任務執行時間是4秒 設置的時間間隔是3秒 我們的任務是每4秒執行一次

scheduleAtFixedRate 使用方式如下:

long intevalPeriod = 3 * 1000;
long delay = 0;
timer.scheduleAtFixedRate(demoTask, delay, intevalPeriod);
2019-11-17 20:59:48.670  INFO 141724 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 20:59:48
2019-11-17 20:59:52.669  INFO 141724 --- [        Timer-0] cn.lijunkui.task.own.SchedulerTask       : DemoTask The time is now 20:59:52
2019-11-17 20:59:56.670  INFO 141724 --- [        Timer-0] cn.lijunkui.task.own.SchedulerTask       : DemoTask The time is now 20:59:56
2019-11-17 21:00:00.670  INFO 141724 --- [        Timer-0] cn.lijunkui.task.own.SchedulerTask       : DemoTask The time is now 21:00:00
2019-11-17 21:00:04.671  INFO 141724 --- [        Timer-0] cn.lijunkui.task.own.SchedulerTask       : DemoTask The time is now 21:00:04

scheduleAtFixedRate:任務執行時間是2秒 設置的時間間隔是3秒 我們的任務是每3秒執行一次,這裏就不在進行演示了。任務執行時間通過 Thread.sleep(4*1000) 來實現。

ScheduledExecutorService 方式

Java SE5 java.util.concurrent 裏 ScheduledExecutorService 提供了新的任務調度的方式。他是採用線程池的方式來執行的,相對於 Timer 語法更爲簡單。

第一步:定義定時任務多線程 Demo 程序,通過實現Runnable 並重寫run 方法,具體代碼如下:


public class ScheduledExecutorTask implements Runnable{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Override
	public void run() {
		try {
			Thread.sleep(4*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 log.info("scheduledExecutorTask The time is now {}", dateFormat.format(new Date()));
	}
}

第二步:通過Executors.newSingleThreadScheduledExecutor() 創建 ScheduledExecutorService 然後在通過ScheduledExecutorService 的schedule方法調用定時任務。具體代碼如下:

package cn.lijunkui.task.jdk.scheduledExecutorService;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorTest {
	private ScheduledExecutorTask task;
	public ScheduledExecutorTest(ScheduledExecutorTask task) {
		this.task = task;
	}
	public void run() {
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 
	    service.schedule(task, 3, TimeUnit.SECONDS);
	}
}

最後定義項目啓動就執行的 Runner 程序,具體代碼如下:

@Component
@Order(value = 1)
public class TimerMangerRunner implements ApplicationRunner{

	@Override
	public void run(ApplicationArguments args) throws Exception {
		ScheduledExecutorTest test = new ScheduledExecutorTest(new ScheduledExecutorTask());
		test.run();
	}
}

測試結果:

schedule:任務執行時間是2秒 設置的時間間隔是3秒 我們的任務是每5秒執行一次

2019-11-27 04:48:02.818  INFO 17196 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 04:48:02
2019-11-27 04:48:07.825  INFO 17196 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:48:07

schedule:任務執行時間是4秒 設置的時間間隔是3秒 我們的任務是每7秒執行一次,並且是隻執行一次

2019-11-27 04:39:19.202  INFO 15416 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 04:39:19
2019-11-27 04:39:26.208  INFO 15416 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:39:26

scheduleAtFixedRate: 任務執行時間是2秒 設置的時間間隔是3秒 我們的任務是每3秒執行一次

public class ScheduledExecutorTest {

	private ScheduledExecutorTask task;
	public ScheduledExecutorTest(ScheduledExecutorTask task) {
		this.task = task;
	}
	public void run() {
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 
	   service.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);
	}
}
public class ScheduledExecutorTest {

	private ScheduledExecutorTask task;
	public ScheduledExecutorTest(ScheduledExecutorTask task) {
		this.task = task;
	}
	public void run() {
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 
	   service.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);
	}
}
2019-11-27 04:51:01.243  INFO 14972 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:51:01
2019-11-27 04:51:04.246  INFO 14972 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:51:04
2019-11-27 04:51:07.244  INFO 14972 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:51:07
2019-11-27 04:51:10.246  INFO 14972 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:51:10

scheduleAtFixedRate: 任務執行時間是4秒 設置的時間間隔是3秒 我們的任務是每4秒執行一次

public class ScheduledExecutorTest {

	private ScheduledExecutorTask task;
	public ScheduledExecutorTest(ScheduledExecutorTask task) {
		this.task = task;
	}
	public void run() {
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 
	   service.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);
	}
}
public class ScheduledExecutorTask  implements Runnable{
	private static final Logger log = LoggerFactory.getLogger(ScheduledExecutorTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Override
	public void run() {
		try {
			Thread.sleep(4*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		 log.info("scheduledExecutorTask The time is now {}", dateFormat.format(new Date()));
	}
}
2019-11-27 04:53:13.951  INFO 15928 --- [           main] c.l.SpringbootexamplesApplication        : Started SpringbootexamplesApplication in 2.939 seconds (JVM running for 4.356)
2019-11-27 04:53:13.963  INFO 15928 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 04:53:13
2019-11-27 04:53:17.966  INFO 15928 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:53:17
2019-11-27 04:53:21.968  INFO 15928 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:53:21
2019-11-27 04:53:25.970  INFO 15928 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:53:25
2019-11-27 04:53:29.973  INFO 15928 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:53:29

scheduleWithFixedDelay : 任務執行時間是2秒 設置的時間間隔是3秒 我們的任務是每5秒執行一次

public class ScheduledExecutorTest {

	private ScheduledExecutorTask task;
	public ScheduledExecutorTest(ScheduledExecutorTask task) {
		this.task = task;
	}
	public void run() {
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 
	    service.scheduleWithFixedDelay(task,0, 3, TimeUnit.SECONDS);
	}
}
2019-11-27 04:58:38.039  INFO 17332 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 04:58:38
2019-11-27 04:58:40.042  INFO 17332 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:58:40
2019-11-27 04:58:45.048  INFO 17332 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:58:45
2019-11-27 04:58:50.053  INFO 17332 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:58:50

scheduleWithFixedDelay : 任務執行時間是4秒 設置的時間間隔是3秒 我們的任務是每7秒執行一次

2019-11-27 04:56:26.884  INFO 13576 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 04:56:26
2019-11-27 04:56:30.883  INFO 13576 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:56:30
2019-11-27 04:56:37.890  INFO 13576 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:56:37
2019-11-27 04:56:44.895  INFO 13576 --- [pool-1-thread-1] c.l.t.j.s.ScheduledExecutorTask          : scheduledExecutorTask The time is now 04:56:44

通過上面測試scheduleAtFixedRate 和 scheduleWithFixedDelay
我們建議使用scheduleAtFixedRate 因爲他的時間間隔更爲合理。

SpringBoot 集成 quartz 使用教程

SpringBoot 2.0 已經有了 快速集成 quartz 的 starter 依賴。

第一步:我們先引入quartz starter 依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

第二步:定義quartz 的 job,也就是具體執行的任務。具體代碼如下:

package cn.lijunkui.task.quartz.simple;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import cn.lijunkui.task.own.SchedulerTask;
import cn.lijunkui.task.quartz.simple.service.OrderService;

public class SimpleJob  extends QuartzJobBean{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Autowired
	private OrderService  orderService;//訂單service
	private String serviceCode;//業務code
	

	public String getServiceCode() {
		return serviceCode;
	}
	public void setServiceCode(String serviceCode) {
		this.serviceCode = serviceCode;
	}

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		
		System.out.println(serviceCode);
		 log.info("quartz simple The time is now {}", dateFormat.format(new Date()));
		orderService.delete();
	}

}

第三步:創建 quartz 的 Config 同時定義 JobDetail 和 觸發器 Trigger

package cn.lijunkui.task.quartz.simple;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SimpleJobConfig {
	@Bean
	public JobDetail simpleJobDetail() {
		
		return JobBuilder.newJob(SimpleJob.class).withIdentity("myJob").storeDurably()
				 	.usingJobData("serviceCode","delete overdue orders")
	                .build();
	}
	@Bean
	public Trigger simpleJobTrigger() {
		//定義每三秒執行一次
		SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever();
		//定義觸發器
		return TriggerBuilder.newTrigger().forJob(simpleJobDetail()).withIdentity("myJobTrigger").withSchedule(simpleScheduleBuilder).build();
	}
}

第四步:定義注入的Job的Service

package cn.lijunkui.task.quartz.simple.service;

import org.springframework.stereotype.Service;

@Service
public class OrderService {
	public void delete() {
		try {
			Thread.sleep(6*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("delete data sucess....");
	}
}

測試結果:

orderService延時 2秒 任務是按照每3秒執行一次

2019-11-27 05:06:15.245  INFO 4496 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 05:06:15
delete data sucess....
delete overdue orders
2019-11-27 05:06:17.586  INFO 4496 --- [eduler_Worker-2] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:06:17
delete data sucess....
delete overdue orders
2019-11-27 05:06:20.583  INFO 4496 --- [eduler_Worker-3] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:06:20
delete data sucess....
delete overdue orders
2019-11-27 05:06:23.585  INFO 4496 --- [eduler_Worker-4] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:06:23
delete data sucess....
delete overdue orders
2019-11-27 05:06:26.582  INFO 4496 --- [eduler_Worker-5] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:06:26
delete data sucess....
delete overdue orders
2019-11-27 05:06:29.584  INFO 4496 --- [eduler_Worker-6] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:06:29
delete data sucess....
delete overdue orders

orderService延時 6秒 任務是按照每3秒執行一次

2019-11-27 05:03:18.333  INFO 3128 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path '/sbe'
2019-11-27 05:03:18.341  INFO 3128 --- [           main] c.l.SpringbootexamplesApplication        : Started SpringbootexamplesApplication in 2.712 seconds (JVM running for 4.122)
2019-11-27 05:03:18.345  INFO 3128 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 05:03:18
delete overdue orders
2019-11-27 05:03:20.786  INFO 3128 --- [eduler_Worker-2] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:03:20
delete overdue orders
2019-11-27 05:03:23.775  INFO 3128 --- [eduler_Worker-3] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:03:23
delete data sucess....
delete overdue orders
2019-11-27 05:03:26.774  INFO 3128 --- [eduler_Worker-4] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:03:26
delete data sucess....
delete overdue orders
delete data sucess....
2019-11-27 05:03:29.775  INFO 3128 --- [eduler_Worker-5] cn.lijunkui.task.own.SchedulerTask       : quartz simple The time is now 05:03:29
delete overdue orders
delete data sucess....

quartz 使用cron 表達式

cron 表達式操作方式和上面的基本一致,不同的是需要實現 Job 而不是使用繼承的方式,具體代碼如下:


public class CronJob implements Job{
	private static final Logger log = LoggerFactory.getLogger(SchedulerTask.class);
	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	@Autowired
	private LiveReminderService  liveReminderService;//直播課提醒
	private String serviceCode;//業務code Live lesson reminder

	public String getServiceCode() {
		return serviceCode;
	}
	public void setServiceCode(String serviceCode) {
		this.serviceCode = serviceCode;
	}
    @Override  
    public void execute(JobExecutionContext context) throws JobExecutionException {
    	log.info("quartz cron The time is now {}", dateFormat.format(new Date()));
    	System.out.println("CronJob"+serviceCode);
    	liveReminderService.sendmessage();
    } 
}

JobDetail 和 觸發器 Trigger的manger類和上面定義的Config操作基本一致,區別在與CronScheduleBuilder 來創建觸發器。具體代碼如下:

@Component
public class CronSchedulerJobManger {
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;
    
    public void scheduleJobs() throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        scheduleJob(scheduler);  
    }  
    
    private void scheduleJob(Scheduler scheduler) throws SchedulerException{
        JobDetail jobDetail = JobBuilder.newJob(CronJob.class) .withIdentity("job1", "group1")
        		.usingJobData("serviceCode","Live lesson reminder1").build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1") .withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail,cronTrigger);   
    }  
      
}

定義直播課提醒的 Service

package cn.lijunkui.task.quartz.cron.service;

import org.springframework.stereotype.Service;

@Service
public class LiveReminderService {
	public void sendmessage() {
		try {
			Thread.sleep(4*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

定義啓動類 使項目一啓動就執行 CronSchedulerJobManger 的定時任務。

package cn.lijunkui.task.quartz.cron;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class CronSchedulerRunner implements CommandLineRunner {
	@Autowired
	public CronSchedulerJobManger manger;
	@Override
	public void run(String... args) throws Exception {
		manger.scheduleJobs();
	}

}

測試結果:

任務執行時間4秒 定時任務設置時間間隔 5秒 實際執行效果是每5秒執行一次

2019-11-27 06:16:33.104  INFO 4268 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 06:16:33
2019-11-27 06:16:35.029  INFO 4268 --- [eduler_Worker-1] cn.lijunkui.task.own.SchedulerTask       : quartz cron The time is now 06:16:35
2019-11-27 06:16:40.002  INFO 4268 --- [eduler_Worker-2] cn.lijunkui.task.own.SchedulerTask       : quartz cron The time is now 06:16:40
2019-11-27 06:16:45.003  INFO 4268 --- [eduler_Worker-3] cn.lijunkui.task.own.SchedulerTask       : quartz cron The time is now 06:16:45
2019-11-27 06:16:50.011  INFO 4268 --- [eduler_Worker-4] cn.lijunkui.task.own.SchedulerTask       : quartz cron The time is now 06:16:50

任務執行時間10秒 定時任務設置時間間隔 5秒 實際執行效果是每5秒執行一次

2019-11-27 06:17:48.662  INFO 22904 --- [           main] c.l.SpringbootexamplesApplication        : reportCurrentTimeInitialDelay fixedRate The time is start 06:17:48
2019-11-27 06:17:50.044  INFO 22904 --- [eduler_Worker-1] cn.lijunkui.task.own.SchedulerTask       : quartz cron The time is now 06:17:50
2019-11-27 06:17:55.005  INFO 22904 --- [eduler_Worker-2] cn.lijunkui.task.own.SchedulerTask       : quartz cron The time is now 06:17:55
2019-11-27 06:18:00.013  INFO 22904 --- [eduler_Worker-3] cn.lijunkui.task.own.SchedulerTask       : quartz cron The time is now 06:18:00

小結

SpringBoot 自帶定時任務,JDK 、quartz 使用各有千秋,在實際工作中你可以根據自己的喜好自行選擇使用任一種方式進行定時任務的開發。如果上述操作你都還沒有接觸過,還等什麼趕緊操作起來!

代碼示例

我本地環境如下:

  • SpringBoot Version: 2.1.0.RELEASE
  • Apache Maven Version: 3.6.0
  • Java Version: 1.8.0_144
  • IDEA:Spring Tools Suite (STS)

整合過程如出現問題可以在我的GitHub 倉庫 springbootexamples 中模塊名爲 spring-boot-2.x_task 項目中進行對比查看

GitHub:https://github.com/zhuoqianmingyue/springbootexamples

參考文獻

http://spring.io/guides/gs/scheduling-tasks/

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