Play framework是一個web應用程序,大部分的應用邏輯都是通過在Controllers中以響應HTTP請求的方式來完成的。
有時候你可能需要執行一些和HTTP請求無關的應用邏輯。這在處理一些初始化任務、維護任務、不阻塞HTTP請求連接池的耗時任務時非常有用。
Jobs是完全受Framework管理的。也就是說play框架會為你管理所有數據庫連接事宜、JPA entity manager同步、事物管理。
要創建一個Job,只需要簡單地繼承play.jobs.Job類就可以。
package jobs; import play.jobs.*; public class MyJob extends Job { public void doJob() { // execute some application logic here ... } }
如果Job需要返回值的話,那么覆蓋doJobWithResult()方法即可。
package jobs; import play.jobs.*; public class MyJob extends Job<String> { public String doJobWithResult() { // execute some application logic here ... return result; } }
這里的String只是一個例子,你可以用任何其他類型。
引導Job(Bootstrap job):
Bootstrap jobs是在play應用程序啟動的時候被執行(注意DEV、PROD模式的區別)。通過@OnApplicationStart注解就可以把一個job標記為bootstrap job。
import play.jobs.*; @OnApplicationStart public class Bootstrap extends Job { public void doJob() { if(Page.count() == 0) { new Page("root").save(); Logger.info("The page tree was empty. A root page has been created."); } } }
對於Bootstrap jobs不需要返回值,即使你做了,返回值也會丟失。
默認情況下,所有被@OnApplicationStart注解標記的job按順序執行完成后,應用程序才開始處理進來的HTTP請求。
如果你想要在應用程序啟動時就開始一個job,同時,你想不等這個job執行完就直接開始處理進來的HTTP請求,你可以如下這樣通過給注解增加async=true這個參數來達到要求的效果:@OnApplicationStart(async=true)。
所有@OnApplicationStart(async=true)標記的job在應用程序啟動時會自動啟動,並且所有這些異步job是在同一時刻啟動的。
定時任務:
定時任務就是play框架根據用戶的設置周期性地執行任務。使用@Every注解來標記job每隔多久執行一次。
import play.jobs.*; @Every("1h") public class Bootstrap extends Job { public void doJob() { List<User> newUsers = User.find("newAccount = true").fetch(); for(User user : newUsers) { Notifier.sayWelcome(user); } } }
如果@Every不夠用的話,也可以使用更加靈活的@On注解來設置定時任務的時間間隔。@On的設置采用的是CRON表達式。
import play.jobs.*; /** Fire at 12pm (noon) every day **/ @On("0 0 12 * * ?") public class Bootstrap extends Job { public void doJob() { Logger.info("Maintenance job ..."); ... } }
在定時任務時,也不需要返回值,即使你做了,返回值也會丟失。
觸發task jobs:
在任何時候,你都可以通過調用job實例的now()方法來觸發job來執行一個特殊的任務。然后這個job就會以非阻塞的方式被立即執行。
public static void encodeVideo(Long videoId) { new VideoEncoder(videoId).now(); renderText("Encoding started"); }
在job實例上調用now()方法,將會返回一個Promise約定的值。當job完成后,你可以用Promise來接收job的執行結果。看怎么做的??
應用程序關閉時執行的任務:
可以通過@OnApplicationStop注解來聲明在應用程序關閉時要執行的job。
import play.jobs.*; @OnApplicationStop public class Bootstrap extends Job { public void doJob() { Fixture.deleteAll(); } }