1

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

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

我的路线功能如下。

  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 都没有到达。

谁能解释为什么?

4

2 回答 2

2

您可以在此处找到解释:了解提取

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

在您的情况下,您println在非叶和非参数化指令中有 s ,因此它们仅在初始化时执行一次。如果您希望它们按照可接受的请求执行 - 只需将它们移入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>
        }
    }
  }

讨论在这里

于 2015-09-14T08:32:13.110 回答
1

好吧,您使用“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
于 2015-09-14T08:19:31.483 回答