我想了解Spray中的指令是如何工作的.根据文件:
指令的一般解剖如下:
Run Code Online (Sandbox Code Playgroud)name(arguments) { extractions => ... // inner Route }
我的基本理解是在下面的代码片段中,32作为参数传递给方法test.
test {
32
}
Run Code Online (Sandbox Code Playgroud)
但是,在上面的指令name示例中,所谓的参数被传递到内部路由,这是一个匿名函数.
有人可以帮我理解语法和流程,从如何提取参数并传递到内部路径?
第一次喷涂用户无法在任何地方找到任何适当的示例.我想要解组包含一个的XML API响应List[Person].
说case class Person(name: String, age: Int).unmarshaller应该产生适当的List[Person].
Spray有一个默认值,NodeSeqUnmarshaller但我无法弄清楚如何正确地连接东西,会感激任何指针.
鉴于以下代码:
import spray.http._
import spray.client.pipelining._
import scala.concurrent.Future
implicit val system = ActorSystem()
import system.dispatcher // execution context for futures
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive
val response: Future[HttpResponse] = pipeline(Get("http://spray.io/"))
Run Code Online (Sandbox Code Playgroud)
下面的伪代码函数等待 10 秒,如果HttpResponse返回则返回“GOOD” ,或者在Await#result异常时返回“BAD” (参见docs .
import scala.concurrent.Await
import scala.concurrent.duration._
def f(fut: Future[HttpResponse]): String = {
try {
val result = Await.result(fut, 10.seconds)
"GOOD"
}
catch e @ (_: InterruptedException | _: IllegalArgumentException
| _: TimeoutException ) => "BAD"
}
Run Code Online (Sandbox Code Playgroud)
在我的catch,是否只需要捕获抛出的异常Await#result …
在这里回答我自己的问题,因为这花了我一天多的时间来弄清楚,这是一个非常简单的问题,我认为其他人可能会遇到.
在使用REST创建RESTful-esk服务时,我希望将具有字母数字id的路由作为路径的一部分进行匹配.这是我最初开始的:
case class APIPagination(val page: Option[Int], val perPage: Option[Int])
get {
pathPrefix("v0" / "things") {
pathEndOrSingleSlash {
parameters('page ? 0, 'perPage ? 10).as(APIPagination) { pagination =>
respondWithMediaType(`application/json`) {
complete("things")
}
}
} ~
path(Segment) { thingStringId =>
pathEnd {
complete(thingStringId)
} ~
pathSuffix("subthings") {
pathEndOrSingleSlash {
complete("subthings")
}
} ~
pathSuffix("othersubthings") {
pathEndOrSingleSlash {
complete("othersubthings")
}
}
}
}
} ~ //more routes...
Run Code Online (Sandbox Code Playgroud)
这没有问题编译,但是当使用scalatest来验证路由结构是否正确时,我很惊讶地发现这种类型的输出:
"ThingServiceTests:"
"Thing Service Routes should not reject:"
- should /v0/things
- should /v0/things/thingId
- should …Run Code Online (Sandbox Code Playgroud) 从spray.io文档页面:
color提取参数“ color”的值作为字符串
color.?提取参数“ color”的可选值作为Option [String]
amount.as[Int]将参数“ amount”的值提取为Int,就需要一个匹配的反序列化器才能使其正常工作(另请参阅解组)
那么如何解析可选Int值?喜欢的东西amount.?.as[Int]似乎并没有工作时。
我有以下采用路径参数的代码;
def candlesRange: Route = (path("candles" / Segment / Segment / IntNumber / LongNumber / LongNumber) & get) {
(a1, a2, tf, t1, t2) => complete(apiController.apiGetCandlesRange(a1, a2, tf, t1, t2))
}
Run Code Online (Sandbox Code Playgroud)
但我想将一些参数更改为查询参数。所以 URL 将遵循这样的格式;
/candles/Asset1/Asset2/timeStart=1507198441000&timeEnd=1512382501000&interval=60m
Run Code Online (Sandbox Code Playgroud)
并将它们传递给相同的方法(甚至可能从分钟中删除“m”,因为方法上的参数是一个整数)
如何在 Scala Akka Http 中更改此路由以执行此操作。我能找到的唯一示例使用 Path params
我正在尝试执行以下操作(我使用spray-json_2.9.2 v1.2.3因为我使用scala 2.9.2)
import spray.json._
import spray.json.DefaultJsonProtocol
import DefaultJsonProtocol._
case class TestMe(key: String, value: String)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val prot = jsonFormat4(TestMe)
}
Run Code Online (Sandbox Code Playgroud)
但我得到编译错误:
TestMe.type(底层类型对象com ... TestMe)[INFO]必需:(?,?,?,?)=>?[INFO]注意:隐含值prot在这里不适用,因为它位于应用程序点之后,并且缺少显式结果类型[INFO]隐式val prot = jsonFormat4(TestMe)
我做错了什么我只是按照以下文档:https://github.com/spray/spray-json#providing-jsonformats-for-case-classes
谢谢
到目前为止,我的尝试遇到了java.lang.ClassCastException: scala.runtime.BoxedUnit cannot be cast to scala.Option.事实上,我甚至无法想出适当的反应如何.可能吗?
我有一个akka actor,它会生成一堆文件,然后将它们拉上来,并返回该zip文件.我想然后将此文件传递回完整的喷涂路由方法,以允许下载zip文件.
我真的希望能够使用getFileFrom,但我似乎无法找到一种方法来利用它来回归未来.我也试过将文件传回完整的函数,但是得到了一个非常神秘的错误.
如何链接期货以获得我想要在浏览器中下载的结果?
这是我正在使用的一些代码
get {
path("test") {
respondWithMediaType(`application/zip`) {
complete {
val pi = new PackageInfo("Test")
doCreate(pi)
}
}
}
}
def doCreate(pi: PackageInfo) = {
val response = (worker ? Create(pi))
.mapTo[Ok]
.map(result => result.zipFile: File)
.recover { case _ => "error" }
response
}
Run Code Online (Sandbox Code Playgroud)
在尝试不同的事情时收到的许多错误之一
could not find implicit value for parameter marshaller: spray.httpx.marshalling.ToResponseMarshaller[scala.concurrent.Future[Comparable[_ >: java.io.File with String <: Comparable[_ >: java.io.File with String <: java.io.Serializable] with java.io.Serializable] with java.io.Serializable]]
Run Code Online (Sandbox Code Playgroud) 到处都可以看到,在执行长时间运行的操作或阻塞操作时,最好使用特殊的Execution上下文。阻止操作,例如访问数据库。我明白为什么。这是为了避免线程饥饿。我们不想让“ 8”个可用线程忙于一些可能最终返回或保持阻塞的阻塞代码。它会严重降低应用程序速度或无限期阻止它。
同时,我想知道如何实现Spray或Play之类的东西。确实,让我们来看看客户端。发送请求后,我们将获得以后的答复。换句话说,请求是异步执行的。顺便说一句,这可能会导致长时间运行。但是,没有什么可以说启动许多请求会导致线程匮乏。因此,我想知道为什么在这种情况下这不是问题。他们有特殊的线程池吗?
我在《学习Scala中的并发编程》一书中提到,在Future中使用“ Blocking {}”语句块可以帮助其调度程序自动产生更多线程。难道是他们处理的方式?
接收请求可以说是一样的,在游戏中我们可以执行一个异步动作。如果要通过此操作访问数据库,则应使用“ Blocking {}”语句块。如何执行该操作是一个特殊的threadPool / ExecutionContext。
我在这里的假设是,它们依赖于hidden.global ExecutionContext。也许我错了。底线是。默认情况下,发出请求是一个漫长的操作,例如在代码中使用spray会如何处理它,从而不会在代码中创建线程饥饿?
我们使用不同的ExecutionContext吗?
编辑:刚刚发现了这个简短的演示文稿,请不要阻塞-如何弄清Akka和Spray的情况,以更好地说明我在这里遇到的问题。
无论如何,我希望能有其他意见
编辑:这是我了解到的使用未来时会发生的事情:
def apply[T](body: =>T): Future[T] = impl.Future(body) //here I have omitted the implicit ExecutorContext
impl.Future is an implementation of Future trait:
def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] =
{
val runnable = new PromiseCompletingRunnable(body)
executor.prepare.execute(runnable)
runnable.promise.future
}
Run Code Online (Sandbox Code Playgroud)
PromiseCompletingRunnable如下所示:
class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()
override def run() = {
promise complete {
try Success(body) catch { …Run Code Online (Sandbox Code Playgroud)