播放2.4:使用依赖项注入在应用程序启动时安排重复执行的任务 [英] Play 2.4: Schedule a recurring task at app startup with dependency injection

查看:84
本文介绍了播放2.4:使用依赖项注入在应用程序启动时安排重复执行的任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在应用程序启动时安排一个周期性任务,该任务本身非常简单,只需向应用程序发送即发即弃的HTTP调用即可.我不是游戏专家,请购买,我认为简单的解决方案就像在Global.onStart中使用play.api.libs.concurrent.Akka.system.schedule一样.从Play 2.4开始,不推荐使用Global配置,而推荐使用新的Guice DI.从 DI文档中窃取建议,我无法提出一个很好的解决方案对于这个问题.我设法得到的最好的方法是在GuiceApplicationLoader之上编写一个包装程序,以调用BuiltInComponentsFromContext的自定义实现,但是在这种情况下,我不能使用注入来获取WSClient.用Play 2.4重写类似内容的最佳方法是什么:

I need to schedule a recurring task on the application start, the task itself is very simple just send to the application a fire-and-forget HTTP call. I'm not a play expert, buy i would assume that s straightforward solution would be something like using play.api.libs.concurrent.Akka.system.schedule in Global.onStart. Since Play 2.4, Global configuration is somewhat deprecated in favor of new Guice DI. Hacking the advice from the DI documentation i couldn't come up with a nice solution for this issue. The best i managed to get is writing a wrapper on top of GuiceApplicationLoader calling a custom implementation of BuiltInComponentsFromContext, but in this case i can't use injection to get WSClient. What's the best way to rewrite something like this with Play 2.4:

object Global extends GlobalSettings {
  override def onStart(app: Application) = {
    Akka.system.schedule(2.hours, 2.hours, theTask)
  }
}

推荐答案

更新:现在对于Play 2.6有了更好的记录:

Update: this is now better documented for Play 2.6: https://www.playframework.com/documentation/2.6.x/ScheduledTasks

您可以通过创建如下模块(注意代码注释)来解决此问题:

You can solve this by creating a module like this (attention to code comments):

package tasks

import javax.inject.{Singleton, Inject}

import akka.actor.ActorSystem
import com.google.inject.AbstractModule

import play.api.inject.ApplicationLifecycle

// Using the default ExecutionContext, but you can configure
// your own as described here:
// https://www.playframework.com/documentation/2.4.x/ThreadPools
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import scala.concurrent.Future
import scala.concurrent.duration._

class MyRecurrentTaskModule extends AbstractModule {
  override def configure() = {
    // binding the RecurrentTask as a eager singleton will force
    // its initialization even if RecurrentTask is not injected in
    // any other object. In other words, it will starts with when
    // your application starts.
    bind(classOf[RecurrentTask]).asEagerSingleton()
  }
}

@Singleton
class RecurrentTask @Inject() (actorSystem: ActorSystem, lifecycle: ApplicationLifecycle) {

  // Just scheduling your task using the injected ActorSystem
  actorSystem.scheduler.schedule(1.second, 1.second) {
    println("I'm running...")
  }

  // This is necessary to avoid thread leaks, specially if you are
  // using a custom ExecutionContext
  lifecycle.addStopHook{ () =>
    Future.successful(actorSystem.shutdown())
  }

}

此后,必须启用此模块,然后在conf/application.conf文件中添加以下行:

After that, you must enable this module adding the following line in your conf/application.conf file:

play.modules.enabled += "tasks.MyRecurrentTaskModule"

然后,只需启动您的应用程序,向它发出一个请求,然后看到计划的任务将每秒运行一次.

Then, just start you application, fire a request to it and see the scheduled task will run every each second.

参考:

  1. 了解Play线程池
  2. Scala的运行时依赖注入
  3. 与Akka集成
  1. Understanding Play thread pools
  2. Play Runtime Dependency Injection for Scala
  3. Integrating with Akka

相关问题:

  1. 如何正确安排任务在Play Framework 2.4.2 scala中?
  2. 是异步作业从Play框架中删除?有什么更好的选择?
  1. How to correctly schedule task in Play Framework 2.4.2 scala?
  2. Was asynchronous jobs removed from the Play framework? What is a better alternative?

这篇关于播放2.4:使用依赖项注入在应用程序启动时安排重复执行的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆