web-dev-qa-db-ja.com

Scala Play Frameworkでサーバーの起動時にアクションを実行するにはどうすればよいですか?

servers.confディレクトリに設定ファイルconf/があり、ルート/serversがヒットするたびにServerControllerによって読み取られます。ファイルが変更されない場合、連続するヒットごとに構成ファイルを再読み取りする必要があるため、これはパフォーマンスが高くありません。さらに、構成ファイルに問題がある場合は、ページヒット時に例外をスローするのではなく、できるだけ早くユーザーに通知できます。

現在、これはServerController.scalaにあります:

case class Server(ip: String, port: String)

/**
  * This controller creates an `Action` to handle HTTP requests to the
  * application's server page.
  */
@Singleton
class ServerController @Inject() extends Controller {

  /**
    * Create an Action to render an HTML page with a the list of servers.
    * The configuration in the `routes` file means that this method
    * will be called when the application receives a `GET` request with
    * a path of `/servers`.
    */
  def index = Action {

    val serverList = ConfigFactory.load().getConfigList("servers")
    val servers: List[Server] = serverList match {
      case null => Nil
      case _ => serverList map { s =>
        Server(s.getString("ip"), s.getString("port"))
      } filter { s =>
        s.ip != null && s.port != null
      }.toList
    }

    Ok(views.html.servers(servers))
  }
}

私の目標は、サーバーに起動時に構成ファイルを読み取らせ、構成ファイルの読み取りに問題がなければ、ルートに到達したときにサーバーのリストをServerControllerに渡すことです。問題がある場合は、すぐに例外をスローしたいと思います。

ただし、アプリケーションのエントリポイントが見つからないため、起動時にアクションを実行する方法がわかりません。

誰かがこれを行う方法を知っていますか? Play2.5.xを使用しています。

18
erip

Playの最新バージョンを使用している場合は、起動時に、ルートパッケージにあるModuleというクラスが検索されます(つまり、上部にpackage定義がありません。ファイル)。これは、Play 2.5.x用の最新のActivatorテンプレートから抜粋した例です。これは、アプリケーションの起動時とシャットダウン時にコードを実行するデモ用に変更しました。

services/Say.scala、これは「こんにちは!」と言う簡単なサービスです。起動時と「さようなら!」アプリケーションがシャットダウンしたとき:

package services

import javax.inject._
import play.api.inject.ApplicationLifecycle
import scala.concurrent.Future

trait Say {
  def hello(): Unit
  def goodbye(): Unit
}

@Singleton
class SayImpl @Inject() (appLifecycle: ApplicationLifecycle) extends Say {  
    override def hello(): Unit = println("Hello!")
    override def goodbye(): Unit = println("Goodbye!")

    // You can do this, or just explicitly call `hello()` at the end
    def start(): Unit = hello()

    // When the application starts, register a stop hook with the
    // ApplicationLifecycle object. The code inside the stop hook will
    // be run when the application stops.
    appLifecycle.addStopHook { () =>
        goodbye()
        Future.successful(())
    }

    // Called when this singleton is constructed (could be replaced by `hello()`)
    start()
}

Module.scalaでは、

import com.google.inject.AbstractModule
import services._

/**
 * This class is a Guice module that tells Guice how to bind several
 * different types. This Guice module is created when the Play
 * application starts.

 * Play will automatically use any class called `Module` that is in
 * the root package. You can create modules in other locations by
 * adding `play.modules.enabled` settings to the `application.conf`
 * configuration file.
 */
class Module extends AbstractModule {

  override def configure() = {
    // We bind the implementation to the interface (trait) as an eager singleton,
    // which means it is bound immediately when the application starts.
    bind(classOf[Say]).to(classOf[SayImpl]).asEagerSingleton()
  }
}

役立つと思われるその他のリソースは次のとおりです Scala依存性注入(DI)ドキュメント および Guiceドキュメント 。GuiceはデフォルトのDIフレームワークですPlayで使用されます。

20
Eric