2011-06-24 29 views
13

Tengo el requisito de devolver el resultado de la base de datos como una cadena en xml-structure o como json-structure. Tengo una solución, pero no sé, si esta es la mejor manera de resolver esto. Tengo dos métodos aquí:spring mvc rest response json y xml

@RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET) 
public ResponseEntity<String> getContentByIdsAsJSON(@PathVariable("ids") String ids) 
{ 
    String content = null; 
    StringBuilder builder = new StringBuilder(); 
    HttpHeaders responseHeaders = new HttpHeaders(); 
    responseHeaders.add("Content-Type", "text/html; charset=utf-8"); 
    // responseHeaders.add("Content-Type", "application/json; charset=utf-8"); 

    List<String> list = this.contentService.findContentByListingIdAsJSON(ids); 
    if (list.isEmpty()) 
    { 
    content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><error>no data found</error>"; 
    return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED); 
    } 
    for (String json : list) 
    { 
    builder.append(json + "\n"); 
    } 
    content = builder.toString(); 
    return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED); 
} 

@RequestMapping(value = "/content/{ids}", method = RequestMethod.GET) 
public ResponseEntity<String> getContentByIdsAsXML(@PathVariable("ids") String ids) 
{ 
    HttpHeaders responseHeaders = new HttpHeaders(); 
    responseHeaders.add("Content-Type", "application/xml; charset=utf-8"); 

    String content = this.contentService.findContentByListingIdAsXML(ids); 
    if (content == null) 
    { 
    content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><error>no data found</error>"; 
    return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED); 
    } 
    return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED); 
} 

para el primer método que necesito una solución mejor, que ya le pregunté aquí: spring mvc rest mongo dbobject response

El siguiente paso es, que me inserta en la configuración de un convertidor de JSON :

<bean id="jsonHttpMessageConverter" 
    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
    <property name="supportedMediaTypes" value="application/json"/> 
</bean> 

cuando cambio el tipo de contenido en el primer método de "application/json", funciona, pero entonces la respuesta XML ya no funciona, debido a que el convertidor de JSON quiere convertir la cadena XML a json-structure, creo.

¿qué puedo hacer, ese resorte identifica la diferencia de que un método debe devolver un tipo json y el otro un xml normal como cadena? lo probé con la bandera aceptar:

@RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET, headers = "Accept=application/json") 

pero esto no funciona. Me sale el siguiente error:

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.StackOverflowError 

Espero que alguien me pueda ayudar.

Respuesta

8

Whoa ... cuando trabaje con Spring, suponga que alguien más se ha encontrado con el mismo problema. Se puede volcar toda la generación JSON del lado del servidor, porque todo lo que necesita hacer es:

  1. Incluir los JSON JAR Jackson en su aplicación
  2. establecer el tipo de RequestMapping retorno a @ResponseBody(yourObjectType)

primavera convertirá automáticamente su objeto a JSON. De Verdad. Funciona como magia

Doc para @ResponseBody: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-responsebody

+1

No. Automáticamente devuelve xml ... – Jan

+1

Si tiene el tipo de devolución para el método establecido en '@ResponseBody MyObject' y tiene los Jackson JAR en su classpath, Spring realiza la conversión. ¿Estás usando Spring 3? – atrain

+0

gracias por la información en ResponseBody ... tengo que agregar algo, aunque: @RequestMapping (value = "/ pets/{petId}", method = RequestMethod.GET, produces = "application/json") @ResponseBody public Pet getPet (@PathVariable String petId, modelo modelo) { // implementación omitida } –

13

Si está utilizando Primavera 3.1, se puede aprovechar el nuevo elemento produces en el @RequestMapping anotación para asegurar que usted produce XML o JSON como desee, incluso dentro de la misma aplicación .

escribí un post sobre esto aquí:

http://springinpractice.com/2012/02/22/supporting-xml-and-json-web-service-endpoints-in-spring-3-1-using-responsebody/

+0

Esta es una gran respuesta, que tiene en cuenta el servicio eficaz de xml y json. No es tan simple como la implementación de Jaxson en Jersey, pero lo tomaré. –

4

Usted puede utilizar ContentNegotiatingViewResolver de la siguiente manera:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
    <property name="defaultContentType" value="application/json" /> 
    <property name="ignoreAcceptHeader" value="true" /> 
    <property name="favorPathExtension" value="true" /> 
    <property name="order" value="1" /> 
    <property name="mediaTypes"> 
     <map> 
      <entry key="xml" value="application/xml" /> 
      <entry key="json" value="application/json" /> 
     </map> 
    </property> 
    <property name="defaultViews"> 
     <list> 
      <ref bean="xmlView"/> 
      <ref bean="jsonView"/> 
     </list> 
    </property> 
</bean> 

<bean id="jsonView" 
     class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"> 
    <property name="contentType" value="application/json;charset=UTF-8"/> 
    <property name="disableCaching" value="false"/> 
</bean> 

<bean id="xmlView" 
     class="org.springframework.web.servlet.view.xml.MarshallingView"> 
    <property name="contentType" value="application/xml;charset=UTF-8"/> 
    <constructor-arg> 
     <ref bean="xstreamMarshaller"/> 
    </constructor-arg> 
</bean> 


<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"> 
    <property name="autodetectAnnotations" value="true" /> 
    <property name="annotatedClass" value="demo.domain.xml.XMLResponse"/> 
    <property name="supportedClasses" value="demo.domain.xml.XMLResponse"/> 
</bean> 

En su controlador:

@RequestMapping(value = "/get/response.json", method = RequestMethod.GET) 
public JSONResponse getJsonResponse(){ 
    return responseService.getJsonResponse(); 
} 
@RequestMapping(value = "/get/response.xml", method = RequestMethod.GET) 
public XMLResponse getXmlResponse(){ 
    return responseService.getXmlResponse(); 
} 
0

Aquí escribí método que toma XML como parámetro de solicitud de su solicitud URL mapeo

Aquí estoy publicando XML a mi URL "baseurl/usuario/createuser /"

public class UserController { 
    @RequestMapping(value = "createuser/" , 
    method=RequestMethod.POST, consumes= "application/xml") 
    @ResponseBody 
    ResponseEntity<String> createUser(@RequestBody String requestBody) { 

     String r = "<ID>10</ID>"; // Put whatever response u want to return to requester 

    return new ResponseEntity<String>(
       "Handled application/xml request. Request body was: " 
       + r, 
       new HttpHeaders(), 
       HttpStatus.OK);  


    } 
} 

he comprobado usando cartel cromo donde se puede enviar cualquier xml en el cuerpo del contenido como:

"<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <userEntity><id>3</id><firstName>saurabh</firstName><lastName>shri</lastName><password>pass</password><userName>[email protected]</userName></userEntity>" 

este XML capturará por mi método createUser y se almacena en cadena requestBody la que puedo usar más

0

la manera más fácil de hacer esto para conseguir la respuesta JSON sería: utilizando Spring 3.1, se puede hacer de la siguiente manera

  1. En el archivo pom.xml (con la esperanza de que está utilizando un proyecto Maven), añadir la dependencia Maven para Jackson mapeador (http://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl/1.9.13)

  2. Modificar código de la siguiente manera y probar el punto final en cartero:

    @RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET) 
    public @ResponseBody String getContentByIdsAsJSON(@PathVariable("ids") String ids){ 
        String content = ""; 
        StringBuilder builder = new StringBuilder(); 
    
        List<String> list = this.contentService.findContentByListingIdAsJSON(ids); 
        if (list.isEmpty()){ 
         content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><error>no data found</error>"; 
         return content; 
        } 
        for (String json : list){ 
         builder.append(json + "\n"); 
        } 
    
        content = builder.toString(); 
        return content; 
    } 
    
1

Si alguien usando la primavera de arranque para la respuesta XML a continuación, agregue la siguiente dependencia,

<dependency> 
    <groupId>com.fasterxml.jackson.dataformat</groupId> 
    <artifactId>jackson-dataformat-xml</artifactId> 
</dependency> 

Y en la clase de modelo que está devolviendo agregue el @XmlRootElement.

@Entity 
@Table(name = "customer") 
@XmlRootElement 
public class Customer { 
     //... fields and getters, setters 
} 

y en su controlador agregue produces="application/xml". Esto producirá la respuesta en formato xml.