JBoss.orgCommunity Documentation

第 20 章 JAX-RS 内容协商

20.1. URL-based 协商
20.2. 基于查询字符串参数的协商

HTTP 协议内置了内容协商头,允许客户端和服务器指定他们传输的内容和他们希望得到的内容。服务器通过 @Produces 和 @Consumes 头声明内容类型。

@Consumes 是特定资源或资源方法使用的媒体类型数组。例如:

@Consumes("text/*")
@Path("/library")
public class Library {

    @POST
    public String stringBook(String book) {...}

    @Consumes("text/xml")
    @POST
    public String jaxbBook(Book book) {...}
}

当客户端发出请求时,JAX-RS 首先找到与路径匹配的所有方法,然后根据客户机发送的内容类型标头对方法进行选择。因此,如果一个客户端发送:

POST /library
Content-Type: text/plain

This is a nice book

将调用 stringBook() 方法,因为它匹配默认的"text/*"媒体类型。现在,如果客户端发送 XML:

POST /library
Content-Type: text/xml

<book name="EJB 3.0" author="Bill Burke"/>

将调用 jaxbBook() 方法。

@Produces 用于映射客户端请求并将其与客户端的 Accept 头匹配。接受 HTTP 标头由客户端发送,并定义客户端希望从服务端接收的媒体类型。

@Produces("text/*")
@Path("/library")
public class Library {

@GET
@Produces("application/json")
public String getJSON() {...}

@GET
public String get() {...}

因此,如果客户端发送:

GET /library
Accept: application/json

将调用 getJSON() 方法。

@Consumes 和 @Produces 可以列出它们支持的多种媒体类型。客户端的 Accept 头信息还可以发送它可能希望接收的多个类型。首先选择更具体的媒体类型。客户端 Accept 头信息或@Produces @Consumes 也可以指定用于匹配请求和资源方法的加权首选项。这在 RFC 2616第14.1节中得到了最好的解释。RESTEasy 支持这种复杂的内容协商方式。

JAX-RS 中的一个变体是媒体类型、内容语言、内容编码以及标签、最后修改的头和其他先决条件的组合。这是一种更复杂的内容协商形式,由应用程序开发人员使用 javax.ws.rs.Variant、VarianListBuilder 和 Request 对象以编程方式完成。通过 @Context 注入请求。阅读 javadoc 以获得更多关于这些的信息。

有些客户端(如浏览器)不能使用 Accept 和 Accept-Language 头信息来协商表示的媒体类型或语言。RESTEasy 允许映射文件名后缀,如(.xml, .txt, .en, .fr)到媒体类型和语言。这些文件名后缀取代并覆盖客户端发送的任何 Accept 头信息。您可以使用 resteasy.media.type.mappings 和 resteasy.language.mappings 参数来配置这个属性。如果在 web.xml 中配置,它看起来像:

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <context-param>
        <param-name>resteasy.media.type.mappings</param-name>
        <param-value>html : text/html, json : application/json, xml : application/xml</param-value>
    </context-param>

   <context-param>
        <param-name>resteasy.language.mappings</param-name>
        <param-value>en : en-US, es : es, fr : fr</param-value>
   </context-param>

   ...
</web-app>

有关应用程序配置的更多信息,请参见第 3.4 节 “配置”

映射是"后缀/媒体类型"或"后缀/语言" 映射的逗号分隔列表。每个映射都由一个’:’分隔。因此,如果调用 GET /foo/bar.xml.en ,这相当于调用以下请求:

GET /foo/bar
Accept: application/xml
Accept-Language: en-US

在将请求分派到相应的 JAX-RS resource之前,从目标 URL 路径剥离映射的文件后缀。

RESTEasy 可以基于查询字符串中的参数进行内容协商。要实现这一点,可以配置 resteasy.media.type.param.mapping 参数。在 web.xml 中,它看起来如下所示:

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <context-param>
        <param-name>resteasy.media.type.param.mapping</param-name>
        <param-value>someName</param-value>
    </context-param>

    ...
</web-app>

有关应用程序配置的更多信息,请参见第 3.4 节 “配置”

param-value 是 RESTEasy 将在 Accept 头信息使用的查询字符串参数的名称。

通过内容协商,在调用 http://service.foo.com/resouce?somename=application/xml 时,application/xml 媒体类型将被赋予最高优先级。

在请求同时包含参数和 Accept 头信息的情况下,参数将更具相关性。

可以将 param-value 保留为空,这将导致处理器查找名为'accept'的参数。