如何在 Scala Play 框架中对服务器启动执行操作? [英] How do I perform an action on server startup in the Scala Play Framework?

查看:27
本文介绍了如何在 Scala Play 框架中对服务器启动执行操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 conf/ 目录中有一个配置文件 servers.conf,每当路由 /servers 被命中时,我的 ServerController 就会读取该文件.这不是高效的,因为当文件不会更改时,它需要在每次连续命中时重新读取配置文件.此外,如果配置文件有问题,我可以尽快告诉用户,而不是在页面点击时抛出异常.

I have a config file servers.conf in my conf/ directory that is read by my ServerController whenever the route /servers is hit. This isn't performant because it requires a re-read of the configuration file on each successive hit when the file won't change. Further if there are problems with the config file, I can tell the user ASAP rather than throw an exception on a page hit.

目前我在我的 ServerController.scala 中有这个:

Currently I have this in my 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.如果有问题,我想立即抛出异常.

My goal is to have the server read the config file at startup and pass the list of servers to the ServerController when the route is hit if there are no problems reading in the config file. If there are problems, I want an exception to be thrown immediately.

不过,我似乎找不到应用程序的入口点,所以我不知道如何在启动时执行操作.

I can't seem to find an entry point for my application, though, so I don't know how to perform actions on startup.

有人知道怎么做吗?我使用的是 Play 2.5.x.

Does anyone know how to do this? I'm using Play 2.5.x.

推荐答案

如果您使用的是最新版本的 Play,它会在启动时查找根包中名为 Module 的任何类(也就是说,文件顶部没有 package 定义).以下是从 Play 2.5.x 的最新 Activator 模板中获取的示例,我对其进行了修改以演示应用程序启动和关闭时的运行代码:

If you're using the latest version of Play, it looks on startup for any class called Module that is in the root package (that is, there is no package definition at the top of the file). Here is an example taken from the latest Activator template for Play 2.5.x, which I have modified for demonstration of running code on application startup and shutdown:

services/Say.scala 中,这将是一个简单的服务,可以说你好!"在启动和再见!"当应用程序关闭时:

In services/Say.scala, this would be a simple service to say "Hello!" on startup and "Goodbye!" when the application shuts down:

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 中,

In 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 是 Play 使用的默认 DI 框架.

Some further resources you may find useful are the Scala dependency injection (DI) documentation and the Guice documentation. Guice is the default DI framework used by Play.

这篇关于如何在 Scala Play 框架中对服务器启动执行操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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