jobs - niubods/playframework-notes GitHub Wiki
因为Play是一个Web应用框架,所以大部分应用逻辑是控制器对HTTP请求的响应。
但是有时候你需要在HTTP请求之外执行一些应用逻辑。这在对初始化任务、维护任务或完成长时间的任务而不阻塞HTTP请求执行池时很有用。
作业完全由框架进行管理。也就是说Play将会为你管理所有数据库连接材料、JPA实体管理器的同步和事务管理。要创建一项作业只需继承 play.jobs.Job
超类。
package jobs;
import play.jobs.*;
public class MyJob extends Job {
public void doJob() { // execute some application logic here ... }
}
有时候你需要创建能返回结果的作业。那么你可以覆盖 doJobWithResult()
方法。
package jobs;
import play.jobs.*;
public class MyJob extends Job<String> {
public String doJobWithResult() { // execute some application logic here ... return result; }
}
这里只是为了举个例子使用了 string
,当然一项作业可以返回任何对象类型。
引导作业是在应用启动时由Play执行的。要创建一个引导作业只需要添加一个@OnApplicationStart
注解。
import play.jobs.*;
@OnApplicationStart public class Bootstrap extends Job {
public void doJob() { if(Page.count() == 0) { new Page("root").save(); Logger.info("A root page has been created."); } }
}
你不需要返回返回一个结果。就算你这么干了,结果也会被丢掉。
默认情况下,所有以@OnApplicationStart
注解的作业会被依次执行。当所有作业结束后,你的应用就准备就绪可以处理接收的请求了。
如果你想让你的作业随应用启动,但又想立即开始处理接收的请求,可以这样注解你的作业:@OnApplicationStart(async=true)
。这样你的作业会在应用启动时在后台启动。所有异步作业都会同时启动。
警告
当你在DEV模式下运行应用的时候,应用会等到第一个HTTP请求后才启动。另外当你在DEV模式下,应用有时会在必要时重新启动。
当你在PROD模式下运行时,应用会在服务器启动时同步启动。
Scheduled jobs are run periodically by the framework. You can ask Play to run a job at a specific interval using the @Every
annotation.
调度作业会由框架周期性执行。你可以要求Play在特定时间间隔执行一项作业,通过使用@Every
注解。
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
注解里用一个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 ..."); ... }
}
小贴士
我们使用来自 Quartz library 的CRON解析器。
你不需要返回一个结果,就算你这么做了,结果也会被丢掉。
你还可以在任何时候通过执行一个特定任务触发一项作业,只需简单地在一个作业的实例上调用 now()
。之后这项作业就会以非阻塞的方式立即运行。
public static void encodeVideo(Long videoId) {
new VideoEncoder(videoId).now();
renderText("Encoding started");
}
调用一个作业的 now()
返回一个 Promise
值,调用完成后你可以从中取回任务结果。
因为有时你需要在应用关闭前执行一些动作,所以Play也提供了一个 OnApplicationStop
注解。
import play.jobs.*;
@OnApplicationStop public class Bootstrap extends Job {
public void doJob() { Fixture.deleteAll(); } }