【问题标题】:How to have a Scala standalone application that uses the playframework libraries如何拥有一个使用 playframework 库的 Scala 独立应用程序
【发布时间】:2014-11-30 23:00:02
【问题描述】:

我有这个简单的测试 Scala 应用程序,它阻塞了 http 请求:

build.sbt

name := "hello"

version := "1.0"

scalaVersion := "2.11.2"

libraryDependencies += "com.typesafe.play" %% "play-ws" % "2.4.0-M1"

Test.scala

import play.api.libs.json._
import play.api.libs.ws._
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

object Test {
  def main(args: Array[String]) = {
    val wsClient = WS.client
    val body = getBody(wsClient.url("http://example.com/").get())
    println(s"body: $body")
  }

  def getBody(future: Future[WSResponse]) = {
    val response = Await.result(future, Duration.Inf);
    if (response.status != 200)
      throw new Exception(response.statusText);
    response.body
  }
}

此应用程序失败:

Exception in thread "main" java.lang.RuntimeException: There is no started application

如何解决这个问题?

【问题讨论】:

    标签: scala playframework-2.0


    【解决方案1】:

    为 Play 2.5 编辑:

    import akka.actor.ActorSystem
    import akka.stream.ActorMaterializer
    import play.api.libs.ws._
    import play.api.libs.ws.ahc.AhcWSClient
    
    import scala.concurrent.Future
    
    object Main {
      import scala.concurrent.ExecutionContext.Implicits._
    
      def main(args: Array[String]): Unit = {
        implicit val system = ActorSystem()
        implicit val materializer = ActorMaterializer()
        val wsClient = AhcWSClient()
    
        call(wsClient)
          .andThen { case _ => wsClient.close() }
          .andThen { case _ => system.terminate() }
      }
    
      def call(wsClient: WSClient): Future[Unit] = {
        wsClient.url("http://www.google.com").get().map { response =>
          val statusText: String = response.statusText
          println(s"Got a response $statusText")
        }
      }
    }
    

    请看:

    有关独立 WSClient 用法的更详细示例。如果您从早期版本迁移,请参阅https://www.playframework.com/documentation/2.5.x/Migration25#Play-WS-upgrades-to-AsyncHttpClient-2

    对于 Play 2.4:

    不要对 HTTPS 使用原始 AsyncHttpClientConfig.Builder - 它不会配置带有主机名验证的安全 SSLContext。

    您可以使用以下代码创建一个新的 WSClient 实例:

    import play.api.libs.ws.ning._
    import play.api.libs.ws._
    
    val config = new NingAsyncHttpClientConfigBuilder(DefaultWSClientConfig()).build()
    val builder = new AsyncHttpClientConfig.Builder(config)
    val wsClient:WSClient = new NingWSClient(builder.build())
    

    请注意,这将启动线程,在您关闭客户端之前不会关闭:

    wsClient.underlying[NingWSClient].close()
    

    如果你不关闭它,你可能会遇到内存泄漏。

    【讨论】:

    【解决方案2】:

    Play 2.4 使得在独立应用中使用 WS 变得非常容易。

    下面的gist 提供了一个很好的工作示例,下面的blog post 提供了一个很好的解释。

    这里是亮点。

    配置 build.sbt

    libraryDependencies ++= Seq(
      "com.typesafe.play" %% "play-ws" % "2.4.0-M2"
    )
    

    初始化 WS 客户端

    val config = new NingAsyncHttpClientConfigBuilder(DefaultWSClientConfig()).build
    val builder = new AsyncHttpClientConfig.Builder(config)
    val client = new NingWSClient(builder.build)
    

    使用 WS

    client.url("http://www.example.com").get
    

    释放 WS 资源

    client.close()
    

    【讨论】:

      【解决方案3】:

      已启动的 PlayApplication 包含一个客户端实例 which WS.client simply points to it。由于您不会启动 Play 应用程序,因此您必须创建自己的客户端,如下所示:

      val client = {
        val builder = new com.ning.http.client.AsyncHttpClientConfig.Builder()
        new play.api.libs.ws.ning.NingWSClient(builder.build())
      }
      client.url("http://example.com/").get()
      

      查看my project 的类似用例,我使用的是 play-ws 和 play-json,没有 Play 本身。

      【讨论】:

        猜你喜欢
        • 2014-07-15
        • 2019-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-09
        • 2021-01-05
        • 2011-02-12
        相关资源
        最近更新 更多