我们正在使用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 traits和 JsonFormat for abstract class with generic parameter
我觉得,我们缺少了一些东西。那么,有人知道这到底是什么问题吗?处理这些鼻窦炎的方便方法是什么?
答案 0 :(得分:0)
间接解决方案
我不知道与问题中提供的错误消息相关的根本问题的原因。但是,我认为您要解决的总体问题有一个更简单的解决方案。
创建“自定义” 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())
}