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
init参数将各种扩展映射到内容类型!
<!-- 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扩展内容类型映射?
P.S。我没有使用Spring。
答案 0 :(得分:4)
在<jaxrs:server>
作品中添加以下内容:
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</jaxrs:extensionMappings>
答案 1 :(得分:1)
不知道这对你有没有帮助,但我也面临同样的问题,在我的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,服务会相应地生成响应。
答案 2 :(得分:0)
在您的情况下,我会声明方法@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为你处理所有这些工作要多得多(它通常会生成很多样板来完成所有这些工作)但在复杂的情况下你会对控制感到高兴。
答案 3 :(得分:0)
您猜测时,扩展程序会模仿Accept
标题。但是,您不能在@Path
注释中声明扩展名:
@Path("/widgets")
@GET
@Produces({ "application/json", "application/xml" })
public List<Widget> getWidgets();
然后,您可以致电widgets.xml
或widgets.json