0

我尝试使用 scala 和喷雾路由创建简单的 CRUD 应用程序。我有以下路线:

override def receive = runRoute {
    path("entities" / LongNumber) { id =>
      get {
        produce(instanceOf[MyEntity]) {
          func => ctx => heavyLookupById(id, func)
        }
    }
}

我是根据官方文档http://spray.io/documentation/1.2.2/spray-routing/marshalling-directives/produce/写的

MyEntity 如下(实际上并不重要):

case class MyEntity(text: String, id: Option[Long])

我有以下 json-support 对象

object MyJsonSupport extends DefaultJsonProtocol with SprayJsonSupport {
    implicit val format = jsonFormat2(MyEntity)
}

“heavyLookupById”函数包含一些繁重的阻塞计算(假设数据库查询或 http 请求),因此我必须处理 scala 未来:

def heavyLookupById(id: Long, func: MyEntity => Unit) = {
   // ... heavy computations
   future onSuccess { case x => func(x) }
}

但是,如果我的未来失败了,我该怎么办?我想用诸如错误请求(400)或未找到(404)HTTP错误之类的东西来响应,但是该怎么做呢?如果我不在“heavyLookupById”中调用“func”——请求只是挂起——我相信默认服务器超时(1 分钟左右)它会失败。

4

1 回答 1

1

您拥有 RequestContext (ctx),因此您可以调用 reject、failWith 或RequestContext.

  val route = path("entities" / LongNumber) { id =>
    get {
      produce(instanceOf[MyEntity]) {
        func => ctx => heavyLookupById(id, func, ctx)
      }
    }
  }

  def heavyLookupById(id: Long, func: MyEntity => Unit, ctx: RequestContext) = {
    // ... heavy computations
    val future = Future.successful(MyEntity("Hello", Some(1)))
    future.onComplete {
      case Success(value) => func(value)
      case Failure(ex) => ctx.failWith(ex)
    }

  }

个人更喜欢handleWith而不是produce,我觉得它更容易阅读。

此外,在失败的情况下,spray 只会返回一个 500,您可以使用exceptionHandlers 对其进行自定义。

  def heavyLookupById(id: Long) = {
    // ... heavy computations
    Future.successful(MyEntity("Hello", Some(1)))
  }


  val route = path("entities" / LongNumber) { id =>
    get {
      handleWith(heavyLookupById)
    }
  }
于 2015-07-08T09:52:38.327 回答