【问题标题】:Scala - How spray call path goes (Debugging spray code)Scala - 喷雾调用路径如何(调试喷雾代码)
【发布时间】:2015-09-14 08:02:32
【问题描述】:

我是 Scala、Spray 和函数式编程的新手。我很伤心,我仍然无法理解 Spray RestAPI 的基本示例。

我已经根据这篇博文中给出的说明编写了程序。 http://www.smartjava.org/content/first-steps-rest-spray-and-scala

而我的Route功能如下。

  val aSimpleRoute =
    path("path1") {
      println("in path path1..")
      put {
        println("in path path1/put..")
        respondWithMediaType(MediaTypes.`text/html`) {
          complete {
            <h1>in path path1/put..</h1>
          }
        }
      } ~ get {
        println("in path path1/get..")
        respondWithMediaType(MediaTypes.`application/json`) {
          complete {
            <h1>in path path1/get..</h1>
          }
        }
      }
    } ~
  path("path2") {
    println("in path path2..")
    get {
      println("in path path2/get..")
      respondWithMediaType(MediaTypes.`application/json`) {
        complete {
          <h1>in path path2/get..</h1>
        }
      }
    } ~ post {
      println("in path path2/post..")
      respondWithMediaType(MediaTypes.`application/json`) {
        complete {
          <h1>in path path2/post..</h1>
        }
      }
    }
  }

一切都按预期进行。但我的问题是,当我的程序启动时,它将通过接收功能运行。查看我的 println 输出,当程序启动时(在它处理任何 http 请求之前)

in path path1..
in path path1/put..
in path path1/get..
in path path2..
in path path2/get..
in path path2/post..
[INFO] [09/14/2015 12:56:01.364] [on-spray-can-akka.actor.default-dispatcher-4] [akka://on-spray-can/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:8080

所以我不明白为什么程序在启动时会进入所有可能的调用路径。 而且,当收到 HTTP 请求时,这些 println 都不会到达。

谁能解释一下为什么?

【问题讨论】:

    标签: scala spray spray-test


    【解决方案1】:

    你可以在这里找到解释:Understanding extractions

    简而言之,非叶和非参数化(无提取)指令仅在构建路由时执行一次。 Leaf 指令(如complete)仅在请求到达指令的路由时才会执行。参数化指令(以及其中的所有内容)根据请求执行(因为每次提取的参数都不同)——即使指令本身在已经接受此请求的指令之后。

    在您的情况下,您在非叶和非参数化指令中有printlns,因此它们仅在初始化时执行一次。如果您希望它们按照可接受的请求执行 - 只需将它们移入 complete:

    val aSimpleRoute =
      path("path1") {
        put {     
          respondWithMediaType(MediaTypes.`text/html`) {
            complete {
              println("in path path1/put..")
              <h1>in path path1/put..</h1>
            }
          }
        } ~ get {
          respondWithMediaType(MediaTypes.`application/json`) {
            complete {
              println("in path path1/get..")
              <h1>in path path1/get..</h1>
            }
          }
        }
      } ~
      path("path2") {
        get {    
          respondWithMediaType(MediaTypes.`application/json`) {
            complete {
              println("in path path2/get..")
              <h1>in path path2/get..</h1>
            }
          }
        } ~ post {
          respondWithMediaType(MediaTypes.`application/json`) {
            complete {
              println("in path path2/post..")
              <h1>in path path2/post..</h1>
            }
        }
      }
    

    讨论是here

    【讨论】:

    • 感谢您为我的问题提供准确答案。这种行为是喷雾特定的还是一般使用 Scala 的??
    • 它是喷雾专用的;但是它使用了 scala 语言的特性,比如惰性计算。例如,complete 函数的主体是按名称调用的参数,这意味着它(主体)实际上是一个零参数的函数,因此它的执行可能会延迟。这就是为什么 printlncomplete 中的行为不同的原因。
    【解决方案2】:

    好吧,您使用“val”来声明喷射路线,这是正常行为,因为当您运行程序时,Scala 会初始化 vals,如果您使用“lazy val”而不是“val”,您会看到您会得到打印何时显式使用此 val。

    例如:

        val a = {
            println("val a initialization")
            "val a initialization"
          }
     
       lazy val b = {
            println("using of val b")
            "using of val b"
          }
        
          println("use of Val a " + a)
        
          println("use of val b  " + b)
    

    结果:

    val a initialization
    use of Val a val a initialization
    using of val b
    use of val b  using of val b
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多