項目經常會用到定時任務,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 觸發執行...
以上即爲本文全部內容。