2012-04-03 10 views
5

JAX-RS ofrece una forma maravillosa de especificar tipos de contenido en @Produces, y el marco determinará automáticamente el mejor tipo de contenido del encabezado HTTP Accept del cliente y, maravilla de maravillas, incluso convierta su objeto a ese tipo (por ejemplo, XML utilizando JAXB o JSON utilizando Jackson) al devolver información a la persona que llama.Asignación de tipos de contenido de extensión en Apache CXF JAX-RS

Mi cliente (de trabajo), como suelen hacer los clientes, dificultó un trabajo simple al solicitar que especifique el tipo de contenido por la extensión en la URL, p. api/widgets.json. Esto me obliga a tener varios métodos getWidgetsXXX(), uno con @Produces("application/json"), otro con @Produces("application/xml"), etc.

Pero estoy usando Apache CXF y yo estaba encantado de encontrar lo que pude configure CXF para mapear varias extensiones para los tipos de contenido utilizando el jaxrs.extensions parámetro init!

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

Pero no puedo encontrar absolutamente ninguna documentación sobre cómo funciona esto en el mundo real. Ingenuamente pensaba que sólo podía anotar un método con un camino con una extensión y sería imitar la cabecera Accepts:

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

Así que llaman usando api/widgets.json y devuelve XML! Lo cual es particularmente extraño, porque JAX-RS especifica que el tipo de contenido predeterminado es el primero en la lista.

¿Dónde puedo encontrar información sobre cómo usar la asignación de tipos de contenido de extensión CXF?

P.S. No estoy usando Spring.

Respuesta

0

En su situación, declaro que el método @Produce el tipo de contenido */* (es decir, un comodín completo) y luego realizo la negociación de contenido yo mismo. Lo que probablemente se busca en una firma método como este:

@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); 

que le da acceso tanto al nombre del archivo deseado - una manera de adivinar el tipo de medio para entregar - y todo el conjunto de cabeceras HTTP (pista: use headers.getAcceptableMediaTypes()), lo que significa lo contrario. Cómo equilibrar los dos es probable que sea "interesante". (El código que tengo que hacer es muy específico para el modelo interno de mi aplicación, por lo que no es útil para ti.) Luego devuelves el resultado construyendo un Response, que te da un control bastante cercano sobre lo que el cliente vuelve.

Sí, esto es más trabajo que dejar que CXF maneje todo esto por ti (normalmente genera un montón de repeticiones para hacer todo esto) pero en un caso complejo estarás contento del control.

+0

Gracias por la sugerencia. Su respuesta puede ser útil --- pero me temo que no responde la pregunta. :( –

4

Añadiendo lo siguiente en sus obras <jaxrs:server>:

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

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

+0

¿Quiere decir en la sección donde dice: "Aquí hay un ejemplo de cómo se puede hacer con Spring"? –

+0

Vaya, no había notado que era solo para Spring. – praseodym

+0

Aunque no era lo que estaba buscando el OP porque, fue muy útil para mí, y tampoco estoy usando Spring. ¡Gracias! –

0

Los imitadores de extensión de la cabecera Accept como usted adivinado.Sin embargo no se debe declarar que la extension en el @Path anotación:

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

A continuación, puede llamar o widgets.xmlwidgets.json

1

no sabe si esa ayuda usted o no, pero yo también estaba enfrentando el mismo problema de introducir algo así en mis servicios JAX-RS. Logré esta funcionalidad usando JAX-RS_Content_Negotiation La siguiente ubicación tiene detalles al respecto.

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

sólo hay que asignar los tipos de medios con los valores que desea

<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) { 


} 

Ahora puedo acceder a mis servicios como esa y la respuesta es según la extensión que puse al final

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

puede poner .xml O .json al final de la URL y servic e generará respuesta en consecuencia.

Cuestiones relacionadas