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

查看:25
本文介绍了播放 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 有更好的记录:https://www.playframework.com/documentation/2.6.x/ScheduledTasks

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. 如何正确安排任务在 Play Framework 2.4.2 Scala 中?
  2. 是异步作业从 Play 框架中删除?什么是更好的选择?

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

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