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();
    }
}
⚠️ **GitHub.com Fallback** ⚠️