前言
在spring boot中實現定時任務功能,可以通過spring自帶的定時任務調度,也可以通過集成經典開源組件quartz實現任務調度。
本文將詳細介紹關于spring boot實現定時任務應用的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。
一、spring定時器
1、cron表達式方式
使用自帶的定時任務,非常簡單,只需要像下面這樣,加上注解就好,不需要像普通定時任務框架那樣繼承任何定時處理接口 ,簡單示例代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.power.demo.scheduledtask.simple; import com.power.demo.util.datetimeutil; import org.springframework.scheduling.annotation.enablescheduling; import org.springframework.scheduling.annotation.scheduled; import org.springframework.stereotype.component; import java.util.date; @component @enablescheduling public class springtaska { /** * cron表達式參考:http://cron.qqe2.com/ **/ @scheduled (cron = "*/5 * * * * ?" , zone = "gmt+8:00" ) private void timercron() { try { thread.sleep( 100 ); } catch (exception e) { e.printstacktrace(); } system.out.println(string.format( "(timercron)%s 每隔5秒執行一次,記錄日志" , datetimeutil.fmtdate( new date()))); } } springtaska |
上述代碼中,在一個類上添加@enablescheduling注解,在方法上加上@scheduled,配置下 cron 表達式,一個最最簡單的cron定時任務就完成了。cron表達式的各個組成部分,可以參考下面:
1
|
@scheduled (cron = "[seconds] [minutes] [hours] [day of month] [month] [day of week] [year]" ) |
2、fixedrate和fixeddelay
@scheduled注解除了cron表達式,還有其他配置方式,比如fixedrate和fixeddelay,下面這個示例通過配置方式的不同,實現不同形式的定時任務調度,示例代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
package com.power.demo.scheduledtask.simple; import com.power.demo.util.datetimeutil; import org.springframework.scheduling.annotation.enablescheduling; import org.springframework.scheduling.annotation.scheduled; import org.springframework.stereotype.component; import java.util.date; @component @enablescheduling public class springtaskb { /*fixedrate:上一次開始執行時間點之后5秒再執行*/ @scheduled(fixedrate = 5000) public void timerfixedrate() { try { thread.sleep(100); } catch (exception e) { e.printstacktrace(); } system.out.println(string.format("(fixedrate)現在時間:%s", datetimeutil.fmtdate(new date()))); } /*fixeddelay:上一次執行完畢時間點之后5秒再執行*/ @scheduled(fixeddelay = 5000) public void timerfixeddelay() { try { thread.sleep(100); } catch (exception e) { e.printstacktrace(); } system.out.println(string.format("(fixeddelay)現在時間:%s", datetimeutil.fmtdate(new date()))); } /*第一次延遲2秒后執行,之后按fixeddelay的規則每5秒執行一次*/ @scheduled (initialdelay = 2000 , fixeddelay = 5000 ) public void timerinitdelay() { try { thread.sleep( 100 ); } catch (exception e) { e.printstacktrace(); } system.out.println(string.format( "(initdelay)現在時間:%s" , datetimeutil.fmtdate( new date()))); } } springtaskb |
注意一下主要區別:
@scheduled(fixedrate = 5000)
:上一次開始執行時間點之后5秒再執行
@scheduled(fixeddelay = 5000)
:上一次執行完畢時間點之后5秒再執行
@scheduled(initialdelay=2000, fixeddelay=5000)
:第一次延遲2秒后執行,之后按fixeddelay的規則每5秒執行一次
有時候,很多項目我們都需要配置好定時任務后立即執行一次,initialdelay就可以不用配置了。
3、zone
@scheduled注解還有一個熟悉的屬性zone,表示時區,通常,如果不寫,定時任務將使用服務器的默認時區;如果你的任務想在特定時區特定時間點跑起來,比如常見的多語言系統可能會定時跑腳本更新數據,就可以設置一個時區,如東八區,就可以設置為:
zone = "gmt+8:00"
二、quartz
quartz是應用最為廣泛的開源任務調度框架之一,有很多公司都根據它實現自己的定時任務管理系統。quartz提供了最常用的兩種定時任務觸發器,即simpletrigger和crontrigger,本文以最廣泛使用的crontrigger為例。
1、添加依賴
1
2
3
4
5
|
<dependency> <groupid>org.quartz-scheduler</groupid> <artifactid>quartz</artifactid> <version> 2.3 . 0 </version> </dependency> |
2、配置cron表達式
示例代碼需要,在application.properties文件中新增如下配置:
1
2
3
4
|
## quartz定時job配置 job.taska.cron=*/ 3 * * * * ? job.taskb.cron=*/ 7 * * * * ? job.taskmail.cron=*/ 5 * * * * ? |
其實,我們完全可以不用配置,直接在代碼里面寫或者持久化在db中然后讀取也可以。
3、添加定時任務實現
任務1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.power.demo.scheduledtask.quartz; import com.power.demo.util.datetimeutil; import org.quartz.disallowconcurrentexecution; import org.quartz.job; import org.quartz.jobexecutioncontext; import org.quartz.jobexecutionexception; import java.util.date; @disallowconcurrentexecution public class quartztaska implements job { @override public void execute(jobexecutioncontext var1) throws jobexecutionexception { try { thread.sleep( 1 ); } catch (exception e) { e.printstacktrace(); } system.out.println(string.format( "(quartztaska)%s 每隔3秒執行一次,記錄日志" , datetimeutil.fmtdate( new date()))); } } quartztaska |
任務2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package com.power.demo.scheduledtask.quartz; import com.power.demo.util.datetimeutil; import org.quartz.disallowconcurrentexecution; import org.quartz.job; import org.quartz.jobexecutioncontext; import org.quartz.jobexecutionexception; import java.util.date; @disallowconcurrentexecution public class quartztaskb implements job { @override public void execute(jobexecutioncontext var1) throws jobexecutionexception { try { thread.sleep( 100 ); } catch (exception e) { e.printstacktrace(); } system.out.println(string.format( "(quartztaskb)%s 每隔7秒執行一次,記錄日志" , datetimeutil.fmtdate( new date()))); } } quartztaskb |
定時發送郵件任務:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package com.power.demo.scheduledtask.quartz; import com.power.demo.service.contract.mailservice; import com.power.demo.util.datetimeutil; import com.power.demo.util.powerlogger; import org.joda.time.datetime; import org.quartz.disallowconcurrentexecution; import org.quartz.job; import org.quartz.jobexecutioncontext; import org.quartz.jobexecutionexception; import org.springframework.beans.factory.annotation.autowired; import java.util.date; @disallowconcurrentexecution public class mailsendtask implements job { @autowired private mailservice mailservice; @override public void execute(jobexecutioncontext var1) throws jobexecutionexception { system.out.println(string.format( "(mailsendtask)%s 每隔5秒發送郵件" , datetimeutil.fmtdate( new date()))); try { //thread.sleep(1); datetime dtnow = new datetime( new date()); date starttime = dtnow.minusmonths( 1 ).todate(); //一個月前 date endtime = dtnow.plusdays( 1 ).todate(); mailservice.autosend(starttime, endtime); powerlogger.info(string.format( "發送郵件,開始時間:%s,結束時間:%s" , datetimeutil.fmtdate(starttime), datetimeutil.fmtdate(endtime))); } catch (exception e) { e.printstacktrace(); powerlogger.info(string.format( "發送郵件,出現異常:%s,結束時間:%s" , e)); } } } mailsendtask |
實現任務看上去非常簡單,繼承quartz的job接口,重寫execute方法即可。
4、集成quartz定時任務
怎么讓spring自動識別初始化quartz定時任務實例呢?這就需要引用spring管理的bean,向spring容器暴露所必須的bean,通過定義job factory實現自動注入。
首先,添加spring注入的job factory類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package com.power.demo.scheduledtask.quartz.config; import org.quartz.spi.triggerfiredbundle; import org.springframework.beans.factory.config.autowirecapablebeanfactory; import org.springframework.context.applicationcontext; import org.springframework.context.applicationcontextaware; import org.springframework.scheduling.quartz.springbeanjobfactory; public final class autowirebeanjobfactory extends springbeanjobfactory implements applicationcontextaware { private transient autowirecapablebeanfactory beanfactory; /** * spring提供了一種機制讓你可以獲取applicationcontext,即applicationcontextaware接口 * 對于一個實現了applicationcontextaware接口的類,spring會實例化它的同時調用它的 * public voidsetapplicationcontext(applicationcontext applicationcontext) throws beansexception;接口, * 將該bean所屬上下文傳遞給它。 **/ @override public void setapplicationcontext( final applicationcontext context) { beanfactory = context.getautowirecapablebeanfactory(); } @override protected object createjobinstance( final triggerfiredbundle bundle) throws exception { final object job = super .createjobinstance(bundle); beanfactory.autowirebean(job); return job; } } autowirebeanjobfactory |
定義quartzconfig:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
package com.power.demo.scheduledtask.quartz.config; import org.springframework.beans.factory.annotation.autowired; import org.springframework.beans.factory.annotation.qualifier; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.scheduling.quartz.crontriggerfactorybean; import org.springframework.scheduling.quartz.schedulerfactorybean; @configuration public class quartzconfig { @autowired @qualifier ( "quartztaskatrigger" ) private crontriggerfactorybean quartztaskatrigger; @autowired @qualifier ( "quartztaskbtrigger" ) private crontriggerfactorybean quartztaskbtrigger; @autowired @qualifier ( "mailsendtrigger" ) private crontriggerfactorybean mailsendtrigger; //quartz中的job自動注入spring容器托管的對象 @bean public autowirebeanjobfactory autowiringspringbeanjobfactory() { return new autowirebeanjobfactory(); } @bean public schedulerfactorybean schedulerfactorybean() { schedulerfactorybean scheduler = new schedulerfactorybean(); scheduler.setjobfactory(autowiringspringbeanjobfactory()); //配置spring注入的job類 //設置crontriggerfactorybean,設定任務trigger scheduler.settriggers( quartztaskatrigger.getobject(), quartztaskbtrigger.getobject(), mailsendtrigger.getobject() ); return scheduler; } } quartzconfig |
接著配置job明細:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
package com.power.demo.scheduledtask.quartz.config; import com.power.demo.common.appfield; import com.power.demo.scheduledtask.quartz.mailsendtask; import com.power.demo.scheduledtask.quartz.quartztaska; import com.power.demo.scheduledtask.quartz.quartztaskb; import com.power.demo.util.configutil; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.configuration; import org.springframework.scheduling.quartz.crontriggerfactorybean; import org.springframework.scheduling.quartz.jobdetailfactorybean; @configuration public class tasksetting { @bean (name = "quartztaska" ) public jobdetailfactorybean jobdetailafactorybean() { //生成jobdetail jobdetailfactorybean factory = new jobdetailfactorybean(); factory.setjobclass(quartztaska. class ); //設置對應的job factory.setgroup( "quartztaskgroup" ); factory.setname( "quartztaskajob" ); factory.setdurability( false ); factory.setdescription( "測試任務a" ); return factory; } @bean (name = "quartztaskatrigger" ) public crontriggerfactorybean crontriggerafactorybean() { string cron = configutil.getconfigval(appfield.job_taska_cron); crontriggerfactorybean stfactory = new crontriggerfactorybean(); //設置jobdetail stfactory.setjobdetail(jobdetailafactorybean().getobject()); stfactory.setstartdelay( 1000 ); stfactory.setname( "quartztaskatrigger" ); stfactory.setgroup( "quartztaskgroup" ); stfactory.setcronexpression(cron); return stfactory; } @bean (name = "quartztaskb" ) public jobdetailfactorybean jobdetailbfactorybean() { //生成jobdetail jobdetailfactorybean factory = new jobdetailfactorybean(); factory.setjobclass(quartztaskb. class ); //設置對應的job factory.setgroup( "quartztaskgroup" ); factory.setname( "quartztaskbjob" ); factory.setdurability( false ); factory.setdescription( "測試任務b" ); return factory; } @bean (name = "quartztaskbtrigger" ) public crontriggerfactorybean crontriggerbfactorybean() { string cron = configutil.getconfigval(appfield.job_taskb_cron); crontriggerfactorybean stfactory = new crontriggerfactorybean(); //設置jobdetail stfactory.setjobdetail(jobdetailbfactorybean().getobject()); stfactory.setstartdelay( 1000 ); stfactory.setname( "quartztaskbtrigger" ); stfactory.setgroup( "quartztaskgroup" ); stfactory.setcronexpression(cron); return stfactory; } @bean (name = "mailsendtask" ) public jobdetailfactorybean jobdetailmailfactorybean() { //生成jobdetail jobdetailfactorybean factory = new jobdetailfactorybean(); factory.setjobclass(mailsendtask. class ); //設置對應的job factory.setgroup( "quartztaskgroup" ); factory.setname( "mailsendtaskjob" ); factory.setdurability( false ); factory.setdescription( "郵件發送任務" ); return factory; } @bean (name = "mailsendtrigger" ) public crontriggerfactorybean crontriggermailfactorybean() { string cron = configutil.getconfigval(appfield.job_taskmail_cron); crontriggerfactorybean stfactory = new crontriggerfactorybean(); //設置jobdetail stfactory.setjobdetail(jobdetailmailfactorybean().getobject()); stfactory.setstartdelay( 1000 ); stfactory.setname( "mailsendtrigger" ); stfactory.setgroup( "quartztaskgroup" ); stfactory.setcronexpression(cron); return stfactory; } } tasksetting |
最后啟動你的spring boot定時任務應用,一個完整的基于quartz調度的定時任務就實現好了。
本文定時任務示例中,有一個定時發送郵件任務mailsendtask,下一篇將分享spring boot應用中以mongodb作為存儲介質的簡易郵件系統。
擴展閱讀:
很多公司都會有自己的定時任務調度框架和系統,在spring boot中如何整合quartz集群,實現動態定時任務配置?
參考:
http://www.ythuaji.com.cn/article/159301.html
http://www.ythuaji.com.cn/article/159303.html
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。
原文鏈接:http://www.cnblogs.com/jeffwongishandsome/p/spring-boot-integrate-task-schedule-practise.html