Domanda

Se sviluppiamo REST utilizzando Spring MVC, sosterrà i dati XML e JSON. Ho scritto nel mio ContentNegotiationViewResorver primavera app-servlet.xml config fagiolo

<bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
        p:order="1">
        <property name="mediaTypes">
            <map>
                <entry key="xml" value="application/xml" />
                <entry key="json" value="application/json" />
            </map>
        </property>
        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                    <property name="marshaller">
                        <bean class="org.springframework.oxm.xstream.XStreamMarshaller"
                            p:autodetectAnnotations="true" />
                    </property>
                </bean>
                <bean
                    class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
            </list>
        </property>
    </bean>

E RESTO controller mia primavera è:

@Controller
@RequestMapping("/rest/customers")
class CustomerRestController {

protected Log log = LogFactory.getLog(CustomerRestController.class);

@RequestMapping(method = POST)
@ResponseStatus(CREATED)
public void createCustomer(@RequestBody Customer customer,
        HttpServletResponse response) {

    log.info(">>>" + customer.getName());
    response.setHeader("Location", String.format("/rest/customers/%s",
            customer.getNumber()));
}


@RequestMapping(value = "/{id}", method = GET)
@ResponseBody
public Customer showCustomer(@PathVariable String id) {
    Customer c = new Customer("0001", "teddy", "bean");
    return c;
}


@RequestMapping(value = "/{id}", method = PUT)
@ResponseStatus(OK)
public void updateCustomer(@RequestBody Customer customer) {
    log.info("customer: " + customer.getName());
}

I set @XStreamAlias("customer") annotazione nella mia classe di dominio del cliente. Ma quando provo accesso http://localhost:8080/rest/customers/teddy.xml sempre dati di risposta JSON.

I set @XmlRootElement(name="customer") annotazione nella mia classe di dominio del cliente. Ma quando provo accesso http://localhost:8080/rest/customers/teddy.json sempre dati di risposta XML.

C'è qualche cosa che non va?

È stato utile?

Soluzione

Credo che il tipo di contenuto "xml" dovrebbero essere mappati a "text / xml" non "application / xml". Inoltre, per forzare resolver tipo di contenuti in base all'estensione, si può provare a impostare il "favorPathExtension" di proprietà di "ContentNegotiatingViewResolver" true (anche se dovrebbe essere vero per difetto!)

EDIT: ora ho aggiunto un campione di lavoro in questa posizione GIT - git://github.com/bijukunjummen/mvc-samples.git, se si mettono il punto finale, utilizzando mvn Tomcat: corsa, il JSON è servito a http://localhost:8080/mvc-samples/rest/customers/teddy.json e XML a http://localhost:8080/mvc-samples/rest/customers/teddy.xml. Questo utilizza non JAXB2 Xstream, come mi è familiare con JAXB. Una cosa che ho notato è che quando le mie annotazioni JAXB non erano corretti in classe Customer, Primavera stava servendo fuori JSON e non XML il modo in cui l'avete visto (È possibile replicare rimuovendo l'annotazione XMLRootElement dalla classe Cliente), una volta che ho fissato il mio annotazioni, sono tornato XML come previsto. Quindi potrebbe essere che ci sia qualcosa di sbagliato con la configurazione XStream.

EDIT 2: Hai ragione !! Non ho notato, una volta ho avuto xml indietro, ho supposto che JSON sta lavorando ora. Io vedo il problema, nel AnnotationMethodHandlerAdapter, la gestione per @ResponseBody è un po 'strano, ignora completamente le ViewResolvers, e utilizza i MessageConverters registrati invece bypassando completamente il ContentNegotiatingViewResolver, una soluzione per ora è quello di utilizzare @ModelAttribute annotazioni per la risposta, invece di @ResponseBody , in questo modo i resolver vista sono sempre chiamato. Provate ora con il progetto a git@github.com:bijukunjummen/mvc-samples.git e vedere se funziona per voi. Questo potrebbe essere un bug primavera, si può provare e portarla fino nel forum primavera e vedere che cosa suggeriscono.

Altri suggerimenti

intestazioni Cosa Accetta vengono inviati al server? Assicurarsi che il tipo di contenuto che si desidera richiesta non è in questa lista.

Primavera 3.1 risolve il problema si parla utilizzando il nuovo elemento produces sul annotazioni @RequestMapping. Questo consente di controllare la HttpMessageConverter che la primavera si applica al vostro oggetto.

ho scritto un post su di esso:

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

Ho avuto lo stesso problema. Presumo che si sta utilizzando Spring 3 e ho usato <mvc:annotation-driven/>. Io non sono del tutto sicuro, ma penso che questo crea qualche conflitto sulla base dei convertitori messaggio che il MVC namespace configura.

utilizzando lo spazio OXM funzionato per me:

@XmlRootElement(name="person")
class Person {
   private String firstName;
   private String lastName;
}

@Controller 
@RequestMapping("person")
class PersonController {
   @RequestMapping("list")
   public @ResponseBody Person getPerson() {
      Person p = new Person();
      p.setFirstName("hello");
      p.setLastName("world");
      return p;
   }
}

Content Configuration (MVC e vista interna resolver sono in un altro contesto):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:oxm="http://www.springframework.org/schema/oxm"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

        <oxm:jaxb2-marshaller id="jaxbMarshaller">
        <oxm:class-to-be-bound name="package.Person" />
    </oxm:jaxb2-marshaller>

    <bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="defaultContentType" value="text/html" />
        <property name="ignoreAcceptHeader" value="true" />
        <property name="favorPathExtension" value="true" />
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
                <entry key="xml" value="application/xml" />
            </map>
        </property>
        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                    <property name="marshaller" ref="jaxbMarshaller" />
                </bean>
            </list>
        </property>
    </bean>
</beans>

Questo esempio utilizza JAXB, in modo da avreste bisogno di JAXB-api e JAXB-impl nel classpath.

Inoltre, solo un suggerimento, non è necessario l'app-servlet.xml. Nel vostro web.xml, impostare la configurazione per nulla e lasciare che il carico contesto Listener loro per voi:

<listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/mvc-context.xml, /WEB-INF/spring/content-negotiation-context.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value/>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

Beh ho avuto una soluzione, ma non so se è il modo giusto nel vostro metodo show cliente:

@RequestMapping(value = "/{id}", method = GET)
@ResponseBody
public Customer showCustomer(@PathVariable String id) {
    Customer c = new Customer("0001", "teddy", "bean");
    return c;
}

In questa parte, stiamo usando MVC della primavera e nel controller dovremmo essere restituire una vista, quindi ho rimosso il @ResponseBody annotazione e ho restituire un String con il nome della vista perché nel nostro XML abbiamo aggiunto un ContentNegotiatingViewResolver e quando abbiamo ResponseBody il contentnegociationviewresolver viene ignorata perché è in attesa di una vista ma siamo tornati l'oggetto in modo che il metodo dovrebbe essere così:

@RequestMapping(value = "/{id}", method = GET)

public String showCustomer(@PathVariable String id, ModelMap model) {
     Customer c = new Customer("0001", "teddy", "bean");
     model.addAttribute("customer",c);
    return "myView";
}

così che funziona per me, se avete problemi che si possono aggiungere al vostro app-servlet.xml

questo fagiolo, ma non credo che si deve aggiungere questo.

<bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/views/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

ho ottenuto le risposte da mkyong.com

Accesso al controller utilizzando un browswer invierà un browser tipico Accetta intestazione. Essa non corrisponderà alcun resolver vista e di default al primo (application / xml) o partite a causa application / xml è nella lista Accetta.

posso consiglia di utilizzare RestClient http://code.google.com/p/rest- client / di avere il controllo completo su ciò che Accept intestazione (se uno a tutti) che si desidera inviare.

Non consiglio usando text / xml, come il set di caratteri predefinito è US-ASCII e non UTF-8. Questo potrebbe creare problemi di codifica funky lungo la strada. È sempre possibile specificare la codifica ma appliation / XML ha una codifica predefinita UTF-8.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top