在 Play 中请求 Content-Type! REST Web 服务框架

Posted

技术标签:

【中文标题】在 Play 中请求 Content-Type! REST Web 服务框架【英文标题】:Request Content-Type in Play! Framework for REST webservices 【发布时间】:2012-03-29 08:37:39 【问题描述】:

我正在尝试使用 Play 实现 REST Web 服务!框架。我知道如何通过指定多个模板以不同格式(JSON、XML、html 等)返回响应。但是,我没有找到任何有关如何处理(例如 POST)请求(表单编码、JSON、XML 等)中不同内容类型的信息。

是否可以注释方法以仅匹配某些内容类型(例如@Consumes)?我是否必须在控制器方法中使用if-clause 区分不同的请求内容类型?

【问题讨论】:

【参考方案1】:

查看 Play 文档以了解组合正文解析器:

http://www.playframework.com/documentation/2.2.0/ScalaBodyParsers

如果您想将帖子正文限制为仅 xml 或 json,您可以按照以下方式编写一些内容:

val xmlOrJson = parse.using 
  request =>
    request.contentType.map(_.toLowerCase(Locale.ENGLISH)) match 
      case Some("application/json") | Some("text/json") => play.api.mvc.BodyParsers.parse.json
      case Some("application/xml") | Some("text/xml") => play.api.mvc.BodyParsers.parse.xml
      case _ => play.api.mvc.BodyParsers.parse.error(Future.successful(UnsupportedMediaType("Invalid content type specified")))
    


def test = Action(xmlOrJson) 
  request =>
    request.body match 
      case json: JsObject => Ok(json) //echo back posted json
      case xml: NodeSeq => Ok(xml) //echo back posted XML
    

xmlOrJson 函数查看内容类型请求标头以确定正文解析器。如果它不是 xml 或 json,则它返回带有 UnsupportedMediaType 响应 (HTTP 415) 的错误正文解析器。

然后,您将此函数作为您想要限制为 xml 或 json 内容的任何操作的主体解析器传递。在操作中,您可以查看正文以确定是否已解析 xml 或 json 并进行相应处理。

【讨论】:

【参考方案2】:

您不是通过注释来执行此操作,而是通过您的路由文件或通过您的操作中的 if 语句来执行此操作。取决于您的用例,哪个最适合。

以下 URL 为您提供了有关用于内容协商的路由文件的一些信息。 http://www.playframework.org/documentation/1.2.4/routes#content-types

例子

GET    /index.xml         Application.index(format:'xml')  
GET    /index.json        Application.indexJson(format:'json')  

上面调用了不同的动作,但如果你愿意,你可以用不同的格式值调用相同的动作。

【讨论】:

据我了解,您引用的文档部分是关于结果(响应)的内容类型。但是,我的问题是关于请求的内容类型(例如,包含表单或 JSON 数据的 POST 请求的正文)。 我猜不同格式的处理是一样的,只是最后的响应不同?如果是这样,如何让 1 个控制器方法消耗每个请求,进行一般处理(保持 DRY),然后根据 request.contentType.equals("application/json OR whatever") 决定如何渲染它? @Geert-Jan 当你调用 render 方法时,它会根据格式渲染视图,所以如果 index.xml 它会渲染 index.xml 文件,但是对于 index.json,它将调用 index.json 文件。两者都将由 Groovy 正常评估,但它允许控制器共享相同的代码,但附加两个或多个不同的视图。【参考方案3】:

您可以在 Play 2 with Scala 中使用默认解析器和模式匹配。像这样的:

  def myAction() = Action  req =>
    req.body match 
      case AnyContentAsFormUrlEncoded(m) =>
        val f1 = m.get("field1").flatMap(_.headOption)
        ...
      case AnyContentAsJson(j) =>        
        val f1 = (j \ "field1").asOpt[String]
        ...
      case _ => //handle content types you don't support
        ...

【讨论】:

以上是关于在 Play 中请求 Content-Type! REST Web 服务框架的主要内容,如果未能解决你的问题,请参考以下文章

Http请求中Content-Type讲解以及在Spring MVC中的应用

http请求头中的content-type属性

Play 框架中的请求队列

Http请求中Content-Type讲解以及在Spring MVC中的应用

Http请求中Accept、Content-Type讲解以及在Spring MVC中的应用

http请求中的content-type