Play 2.4:使用依赖注入在应用程序启动时安排一个循环任务

Play 2.4: Schedule a recurring task at app startup with dependency injection

我需要在应用程序启动时安排一个循环任务,任务本身非常简单,只需向应用程序发送一个即发即弃的 HTTP 调用即可。我不是游戏专家,我认为最简单的解决方案是在 Global.onStart 中使用 play.api.libs.concurrent.Akka.system.schedule。自 Play 2.4 以来,Global 配置在某种程度上已被弃用,以支持新的 Guice DI。根据 DI documentation 的建议,我无法为这个问题想出一个好的解决方案。我设法得到的最好的结果是在 GuiceApplicationLoader 之上编写一个包装器调用 BuiltInComponentsFromContext 的自定义实现,但在这种情况下我不能使用注入来获取 WSClient。用 Play 2.4 重写这样的东西的最佳方法是什么:

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

更新:Play 2.6 现在有更好的记录:https://www.playframework.com/documentation/2.6.x/ScheduledTasks


你可以通过创建一个这样的模块来解决这个问题(注意代码注释):

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 文件中添加以下行:

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

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

参考文献:

  1. Understanding Play thread pools
  2. Play Runtime Dependency Injection for Scala
  3. Integrating with Akka

相关问题: