專案經常會用到定時任務,springboot自然是可以通過整合相關元件來實現的。
目前常用的定時任務的實現有兩種:
- 通過spring 自帶的定時器任務@Schedule來實現
- 通過Quartz來實現
本次借用上一篇《spring boot 整合Mybatis》的既有專案結構進行案例除錯。
一、cron表示式
無論上面說的哪種實現方式,都需要用到cron表示式,因此不得不先介紹下它。
Cron表示式是一個字串,由6或7個域組成,每個域有不同的含義,每個域之間用空格隔開。有2中格式:
Seconds Minutes Hours DayofMonth Month DayofWeek Year (7個域)
Seconds Minutes Hours DayofMonth Month DayofWeek (6個域)
每個域可能出現的值:
Seconds:有效範圍為0-59的整數
Minutes:有效範圍為0-59的整數
Hours:有效範圍為0-23的整數
DayofMonth:有效範圍為0-31的整數
Month:有效範圍為1-12的整數或JAN-DEC
DayofWeek:有效範圍為1-7的整數或SUN-SAT兩個範圍。1表示星期天,2表示星期一, 依次類推
Year:有效範圍為1970-2099年
除了以上內容外,還可能出現一些特殊字元:
(1)*:表示匹配該域的任意值,假如在Minutes域使用*, 即表示每分鐘都會觸發事件。
(2)?:只能用在DayofMonth和DayofWeek兩個域。它也匹配域的任意值,但實際不會。因為DayofMonth和DayofWeek會相互影響。例如想在每月的10日觸發排程,不管10日到底是星期幾,則只能使用如下寫法: 13 13 15 10 * ?, 其中最後一位只能用?,而不能使用*,如果使用*表示不管星期幾都會觸發,實際上並不是這樣。
(3)-:表示範圍,例如在Minutes域使用5-20,表示從5分到20分鐘每分鐘觸發一次
(4)/:表示起始時間開始觸發,然後每隔固定時間觸發一次,例如在Minutes域使用5/20,則意味著5分鐘觸發一次,而25,45等分別觸發一次.
(5),:表示列出列舉值值。例如:在Minutes域使用5,20,則意味著在5和20分每分鐘觸發一次。
(6)L:表示最後,只能出現在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味著在最後的一個星期四觸發。
(7)W:表示有效工作日(週一到週五),只能出現在DayofMonth域,系統將在離指定日期的最近的有效工作日觸發事件。例如:在 DayofMonth使用5W,如果5日是星期六,則將在最近的工作日:星期五,即4日觸發。如果5日是星期天,則在6日(週一)觸發;如果5日在星期一到星期五中的一天,則就在5日觸發。另外一點,W的最近尋找不會跨過月份
(8)LW:這兩個字元可以連用,表示在某個月最後一個工作日,即最後一個星期五。
(9)#:用於確定每個月第幾個星期幾,只能出現在DayofMonth域。例如在4#2,表示某月的第二個星期三。
舉例:
@Scheduled(cron = “0 0 1 1 1 ?”)//每年一月的一號的 1:00:00 執行一次
@Scheduled(cron = “0 0 1 1 1,6 ?”) //一月和六月的一號的 1:00:00 執行一次
@Scheduled(cron = “0 0 1 1 1,4,7,10 ?”) //每個季度的第一個月的一號的 1:00:00 執行一次
@Scheduled(cron = “0 0 1 1 * ?”)//每月一號 1:00:00 執行一次
@Scheduled(cron=“0 0 1 * * *”) //每天凌晨 1 點執行一次
以上看上去有點複雜,不過不用擔心,記住常用的就行了。另外,現在網上還有 線上Cron表示式生成器可以幫助我們設定確定相關表示式內容。
二、@Schedule實現
1.引入依賴
<!--新增schedule依賴-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
2.程式碼實現
-
新建類JdkSchedule
@Component public class JdkSchedule { @Autowired UserService userService; @Scheduled(cron = "0/2 * * * * ?") //每個兩秒觸發一次 public void scheduleGetUserList() { System.out.println("**觸發JDK 定時器***"); List<User> list = userService.getUserList(new User()); for (User user :list ){ System.out.println(user.toString()); } } }
裡面的userService為上一次新增的內容
-
啟動類新增註解,啟動定時任務
@EnableScheduling
3.測試效果
每隔兩秒列印一次:
**觸發JDK 定時器***
User{id=1, name='sam', age=32}
User{id=2, name='hah ', age=10}
三、Quartz實現
1.Quartz介紹
Quartz是一個完全由Java編寫的開源任務排程的框架,通過觸發器設定作業定時執行規則,控制作業的執行時間。它包括排程器、觸發器、作業。
組成 | 描述 |
---|---|
Job--任務 | 做什麼事? |
Trigger--觸發器 | 什麼時候做? |
Scheduler--排程器 | 什麼時候需要去做什麼事情? |
2.基本使用
-
引入依賴
<!--引入quartz依賴--> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> </dependency>
-
建立job類
public class MyJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("...quartz job 觸發執行..."); } }
需要實現Quartz的Job介面
-
編寫測試類:
/** * quartz原生態用法 */ public class JobTestMain { public static void main(String[] args) throws SchedulerException { //1.建立job JobDetail job = JobBuilder.newJob(MyJob.class).build(); //2.建立trigger CronTrigger trigger = TriggerBuilder.newTrigger() .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?")) .build(); //3.建立schedule Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(job, trigger); scheduler.start(); } }
-
執行測試類JobTestMain:
每三秒列印一次:
...quartz job 觸發執行...
3.springboot整合使用
-
引入依賴
<!--新增schedule依賴--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!--引入quartz依賴--> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> </dependency> <!--引入spring tx依賴--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency>
springboot整合的時候,需要新增這三個依賴。
-
編寫配置類
/** * springboot整合quartz使用方法 */ @Configuration public class QuartzConfig { /** * 建立job物件 * @return */ @Bean public JobDetailFactoryBean jobDetailFactoryBean() { JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean(); jobDetailFactoryBean.setJobClass(MyJob.class); return jobDetailFactoryBean; } /** * 建立trigger物件 - cron表示式物件 * @param jobDetailFactoryBean * @return */ @Bean public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){ CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean(); cronTriggerFactoryBean.setCronExpression("0/5 * * * * ?"); // 關聯JobDetail物件 cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject()); return cronTriggerFactoryBean; } /** * 建立trigger物件 - 一般物件 * @param jobDetailFactoryBean * @return */ @Bean public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean) { SimpleTriggerFactoryBean simpleTriggerFactoryBean = new SimpleTriggerFactoryBean(); // 關聯JobDetail物件 simpleTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject()); // 設定重複次數,這裡配置的是重複次數,而不是總次數; 總次數=重複次數+1,也就是說這裡配置的次數是:執行完一次之後,再重複執行的次數 simpleTriggerFactoryBean.setRepeatCount(1); // 設定間隔時間 simpleTriggerFactoryBean.setRepeatInterval(2000); return simpleTriggerFactoryBean; } /** * 建立schedule物件 * @param triggerFactoryBean * @return */ @Bean public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean triggerFactoryBean){ SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setTriggers(triggerFactoryBean.getObject()); return schedulerFactoryBean; } }
這裡需要注意下,schedulerFactoryBean()方法中傳入的引數如果是CronTriggerFactoryBean,則執行的是cronTriggerFactoryBean()對應的設定;引數如果是SimpleTriggerFactoryBean,則執行的是simpleTriggerFactoryBean()對應的設定。
-
啟動類新增註解
@EnableScheduling
-
測試效果
每5秒鐘執行一次:
...quartz job 觸發執行...
如果前面的@Schedule和這裡的Quartz的定時任務放在一起了,則執行效果為兩個Job一起執行:
...quartz job 觸發執行... User{id=1, name='sam', age=32} User{id=2, name='hah ', age=10} **觸發JDK 定時器*** User{id=1, name='sam', age=32} User{id=2, name='hah ', age=10} **觸發JDK 定時器*** User{id=1, name='sam', age=32} User{id=2, name='hah ', age=10} **觸發JDK 定時器*** ...quartz job 觸發執行... User{id=1, name='sam', age=32} User{id=2, name='hah ', age=10} **觸發JDK 定時器*** User{id=1, name='sam', age=32} User{id=2, name='hah ', age=10} **觸發JDK 定時器*** User{id=1, name='sam', age=32} User{id=2, name='hah ', age=10} ...quartz job 觸發執行...
以上即為本文全部內容。