【问题标题】:Mapping extension content types in Apache CXF JAX-RS在 Apache CXF JAX-RS 中映射扩展内容类型
【发布时间】:2012-04-03 20:15:40
【问题描述】:

JAX-RS 提供了一种在 @Produces 中指定内容类型的绝妙方法,并且框架会自动从客户端的 HTTP Accept 标头中确定最佳内容类型,并且,奇迹般的,甚至将您的对象转换为该类型(例如,使用 JAXB 的 XML 或使用 Jackson 的 JSON)向调用者返回信息时。

我的(工作)客户,正如客户经常做的那样,通过请求我通过 URL 中的扩展名指定内容类型,例如,使一项简单的工作变得更加困难。 api/widgets.json。这将迫使我使用各种getWidgetsXXX() 方法,一种是@Produces("application/json"),另一种是@Produces("application/xml"),等等。

但我使用的是 Apache CXF,我很高兴地发现我可以 configure CXF 使用 jaxrs.extensions 初始化参数将各种扩展映射到内容类型!

<!-- registers extension mappings -->
<init-param>
  <param-name>jaxrs.extensions</param-name>
  <param-value>
    xml=application/xml
    json=application/json
  </param-value>
</init-param>

但我绝对找不到关于它在现实世界中如何工作的文档。我天真地以为我可以用带有扩展名的路径注释一个方法,它会模仿 Accepts 标头:

@Path("/widgets.{extension}")
@GET
@Produces({ "application/json", "application/xml" })
public List<Widget> getWidgets();

所以我使用api/widgets.json 调用它,它返回XML!这特别奇怪,因为 JAX-RS 指定默认内容类型是列出的第一个。

在哪里可以找到如何使用 CXF 扩展内容类型映射?

附:我没有使用 Spring。

【问题讨论】:

    标签: mapping cxf content-type jax-rs


    【解决方案1】:

    在您的&lt;jaxrs:server&gt; 作品中添加以下内容:

    <jaxrs:extensionMappings>
        <entry key="json" value="application/json" />
        <entry key="xml" value="application/xml" />
    </jaxrs:extensionMappings>
    

    来源:http://cxf.apache.org/docs/jax-rs.html#JAX-RS-Debugging

    【讨论】:

    • 你的意思是在它说的部分,“这是一个如何使用 Spring 完成的示例”?
    • 糟糕,没有注意到它只适用于 Spring。
    • 虽然这不是 OP 想要的,但它对我很有帮助,而且我也没有使用 Spring。谢谢!
    【解决方案2】:

    不知道这是否对您有帮助,但我也面临同样的问题,在我的 JAX-RS 服务中引入类似的东西。我使用 JAX-RS_Content_Negotiation 实现了这个功能,下面的位置有它的详细信息。

    https://docs.jboss.org/resteasy/docs/3.0.6.Final/userguide/html/JAX-RS_Content_Negotiation.html

    您只需将您的媒体类型映射到您想要的值

     <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>
    
    
     @GET
            @Path("/second/{param}")
            @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
            public Response printStudent(@PathParam("param") String msg) {
    
    
    }
    

    现在我可以像这样访问我的服务,响应是根据我放在最后的扩展名

    http://localhost:8080/RESTfulExample/rest/message/second/bill.json

    您可以将 .xml 或 .json 放在 url 的末尾,服务将相应地生成响应。

    【讨论】:

      【解决方案3】:

      在您的情况下,我会声明方法@Produces 的内容类型为*/*(即完整的通配符),然后自己进行内容协商。您可能会看到这样的方法签名:

      @javax.ws.rs.GET
      @javax.ws.rs.Path("{filename}")
      @javax.ws.rs.Produces("*/*")
      javax.ws.rs.core.Response getDirectoryOrFileContents(
              @javax.ws.rs.PathParam("filename") String filename,
              @javax.ws.rs.core.Context javax.ws.rs.core.HttpHeaders headers);
      

      这使您可以访问所需的文件名 - 一种猜测要传递的媒体类型的方法 - 以及完整的 HTTP 标头集(提示:使用headers.getAcceptableMediaTypes()),这是另一种方式。如何平衡这两者可能是“有趣的”。 (我必须执行的代码非常特定于我的应用程序的内部模型,因此可能对您没有用处。)然后您通过构造 Response 返回结果,这使您可以非常密切地控制客户得到什么。

      是的,这比让 CXF 为您处理所有这些工作要多(它通常会生成大量样板来完成所有这些工作),但在复杂的情况下,您会很高兴控制。

      【讨论】:

      • 感谢您的提示。您的回答可能很有用——但恐怕它不能回答这个问题。 :(
      【解决方案4】:

      如您所料,该扩展程序模仿了 Accept 标头。但是,您不能在 @Path 注释中声明扩展:

      @Path("/widgets")
      @GET
      @Produces({ "application/json", "application/xml" })
      public List<Widget> getWidgets();
      

      然后您可以致电widgets.xmlwidgets.json

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-18
        相关资源
        最近更新 更多