播放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文档中窃取建议,我无法提出一个很好的解决方案对于这个问题.我设法得到的最好的方法是在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)
}
}
推荐答案
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.
参考:
- Understanding Play thread pools
- Play Runtime Dependency Injection for Scala
- Integrating with Akka
相关问题:
- How to correctly schedule task in Play Framework 2.4.2 scala?
- Was asynchronous jobs removed from the Play framework? What is a better alternative?
这篇关于播放2.4:使用依赖项注入在应用程序启动时安排重复执行的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!