【问题标题】:Akka HTTP: Create HTTPResponse from Abstract TypeAkka HTTP:从抽象类型创建 HTTPResponse
【发布时间】:2018-08-08 11:54:11
【问题描述】:

我们使用的是akka-http,需要根据逻辑返回多个响应。这就是为什么,在我们的应用程序中,我们有这样的响应层次结构:

object CustomHttpResponse extends DefaultJsonProtocol {
    implicit val formatter = new RootJsonWriter[CustomHttpResponse] {
        override def write(obj : CustomHttpResponse) : JsValue = obj match
        {
            case success : Success =>
                JsObject("type" -> "success".toJson, "value" -> success.toJson)
            case failure : Failure =>
                JsObject("type" -> "failure".toJson, "value" -> failure.toJson)
        }
    }
}

sealed trait CustomHttpResponse {
    def status : Boolean
}

object Success extends SprayJsonSupport with DefaultJsonProtocol {
    implicit val Formatter : RootJsonFormat[Success] = jsonFormat1(Success.apply)
}
case class Success(override val status : Boolean) extends CustomHttpResponse

object Failure extends SprayJsonSupport with DefaultJsonProtocol {
    implicit val Formatter : RootJsonFormat[Failure] = jsonFormat3(Failure.apply)
}
case class Failure(override val status : Boolean, cause : String) extends CustomHttpResponse

这些响应是根据我的条件生成的,并由我的控制器辅助方法生成,如下所示:

def generateResponse(param1: String, param2: String): HttpResponse[CustomHttpResponse] = { .... }

HttpResponse 类的主体是自定义的:

case class HttpResponse[T <: CustomHttpResponse](statusCode : Int, body : T)

HttpResponse 类只是一种 DTO,它实际上是从控制器助手中获取值并返回给控制器。在控制器中,我们尝试从控制器辅助方法中获取值并将其设置为 akka http complele(.. ) 方法,如下所示:

val response = generateResponse("data", "data2")
complete(response.statusCode, response.body)

在将主体传递给完成方法时,我们得到这样的结果:

[ERROR] too many arguments for method complete: (m: => akka.http.scaladsl.marshalling.ToResponseMarshallable)akka.http.scaladsl.server.StandardRoute
[ERROR]  complete(responseMessage.statusCode,  responseMessage.body )

经过搜索,这个错误的原因是,我们的HttpResponse类包含了一个抽象类型,当我们把抽象类型的值赋给complete方法时,它无法弄清楚格式化程序是什么CustomHttpResponse。即使我们在 CustomHttpResponse 伴随对象中创建所有格式化程序。这方面的参考资料来自:

akka http (un)marshall traitsJsonFormat for abstract class with generic parameter

我觉得,我们错过了一些东西。那么,任何人都知道这是什么问题?处理这些sinerios的便捷方式是什么?

【问题讨论】:

    标签: json scala akka akka-http


    【解决方案1】:

    间接解决方案

    我不知道与问题中提供的错误消息相关的潜在问题的原因。但是,我认为对于您要解决的整体问题,有一个更简单的解决方案。

    您创建“自定义”HttpResponse 值的方式本质上是非常面向对象的。我认为可以消除所有自定义层次结构,并用来自 akka 的标准 HttpResponse 类以及函数方法替换。

    您可以编写响应操纵器函数来根据条件更新响应:

    val setStatus : HttpResponse => HttpResponse = 
      if(someCondition)
        (httpResponse) => httpResponse withStatus 200
      else
        (httpResponse) => httpResponse withStatus 500
    
    val setHeaders : (Boolean) => HttpResponse => HttpResponse =
      (conditionProvided) => 
        if(conditionProvided)
          (httpResponse) => httpResponse withHeaders Seq(...)
        else
          (httpResponse) => httpResponse withHeaders Seq.empty[HttpHeader]
    
    def defaultResponse : () => HttpResponse = HttpResponse()
    

    然后可以在 Route 中使用这些来创建自定义响应:

    val route : Route = {
      val internalCondition : Boolean = ???
    
      val responsePipeline : () => HttpResponse = 
        defaultResponse andThen setStatus andThen setHeaders(internalCondition)
    
      complete(responsePipeline())
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2021-08-13
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多