在 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讲解以及在Spring MVC中的应用