2015-05-30 12 views
15

Ho un controllore mappata con la seguente annotazione:Spring MVC 4: "application/json" tipo contenuto è non essere impostato correttamente

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 
@ResponseBody 
public String bar() { 
    return "{\"test\": \"jsonResponseExample\"}"; 
} 

I restituire una stringa JSON valido tuttavia, il tipo di contenuto quando visualizzare la risposta su Chrome Dev Tools nel browser non è application/json ma semplicemente text/html. Perché il tipo di contenuto non è impostato?

mio web.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app metadata-complete="true" version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 

    <display-name>Spring MVC Web Application</display-name> 

    <servlet> 
     <servlet-name>dispatcher</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

    <!-- static assets --> 
    <servlet-mapping> 
     <servlet-name>default</servlet-name> 
     <url-pattern>*.js</url-pattern> 
    </servlet-mapping> 
    <servlet-mapping> 
     <servlet-name>default</servlet-name> 
     <url-pattern>*.css</url-pattern> 
    </servlet-mapping> 

    <servlet-mapping> 
     <servlet-name>dispatcher</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> 
    </context-param> 

    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
</web-app> 

mio dispatcher-servlet.xml:

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


    <context:annotation-config /> 

    <context:component-scan base-package="com.mydomain.controllers" /> 

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

Utilizzando wildfly 8.1 del server della app.

+0

Usi @ResponseBody e acctualy avere un mapper Json? – John

+1

Vediamo il resto del tuo metodo, le intestazioni delle tue richieste e la risposta completa. –

+0

@SotiriosDelimanolis Aggiunto tutto. – user1757703

risposta

40

La prima cosa da capire è che l'elemento RequestMapping#produces() in

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 

serve solo a limitare la mappatura per la vostra richiesta gestori. Non fa nient'altro.

Quindi, dato che il metodo ha un tipo di ritorno String e viene annotato con @ResponseBody, il valore restituito sarà gestito da StringHttpMessageConverter che imposta l'intestazione Content-type a text/plain. Se si desidera restituire una stringa JSON autonomamente e impostare l'intestazione su application/json, utilizzare un tipo di reso ResponseEntity (eliminare @ResponseBody) e aggiungere intestazioni appropriate.

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 
public ResponseEntity<String> bar() { 
    final HttpHeaders httpHeaders= new HttpHeaders(); 
    httpHeaders.setContentType(MediaType.APPLICATION_JSON); 
    return new ResponseEntity<String>("{\"test\": \"jsonResponseExample\"}", httpHeaders, HttpStatus.OK); 
} 

Nota che probabilmente si dovrebbe avere

<mvc:annotation-driven /> 

nella configurazione contesto servlet per impostare la configurazione MVC con le impostazioni predefinite più adatte.

+1

La libreria di Jackson funziona perfettamente bene con @ResponseBody – John

+2

@ user3360241 Jackson con '@ ResponseBody' è implementato con un' MappingJackson2HttpMessageConverter'. È registrato dopo un 'StringHttpMessageConverter' e quindi non ha alcun ruolo nella gestione di questa richiesta. –

+0

Hm: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/, anche questo è solo un esempio. Direi che l'op vorrebbe restituire oggetti personalizzati come Json. – John

3

Utilizzare la libreria jackson e l'annotazione @ResponseBody sul tipo di ritorno per il controller.

Questo funziona se si desidera restituire POJO rappresentati come JSon. Se desideri restituire String e non POJO come JSon, fai riferimento a Sotirious answer.

+1

L'ho fatto ma ancora non funziona. Potrebbe essere qualcosa a che fare con i miei file XML di configurazione? Usato Gson invece di Jackson ma la stessa cosa. – user1757703

+0

Aggiungi ulteriori dettagli quindi per favore, mostraci la tua dipendenza e l'intero codice per il controller. – John

+0

Non posso parlare di questo Gson, ti garantisco che il jackson funziona anche se. – John

1

Come altre persone hanno commentato, perché il tipo di ritorno del metodo è String Spring non sentirà la necessità di fare nulla con il risultato.

Se cambiate la vostra firma in modo che il tipo di ritorno è qualcosa che ha bisogno di smistamento, che dovrebbe aiutare:

@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json") 
@ResponseBody 
public Map<String, Object> bar() { 
    HashMap<String, Object> map = new HashMap<String, Object>(); 
    map.put("test", "jsonRestExample"); 
    return map; 
} 
-1

Quando ho aggiornato a molla 4 avevo bisogno di aggiornare le dipendenze Jackson come segue:

<dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-core</artifactId> 
     <version>2.5.1</version> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-databind</artifactId> 
     <version>2.5.1</version> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-annotations</artifactId> 
     <version>2.5.1</version> 
    </dependency>   
-1

Ho avuto le dipendenze come specificato @Greg post.Ho ancora affrontato la questione e potrebbe essere in grado di risolvere con l'aggiunta di ulteriori seguenti dipendenza jackson:

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

Non esattamente per questo PO, ma per coloro che ha incontrato 404 e non può impostare la risposta content-type-"application/json" (qualsiasi content-type). Una possibilità è che un server risponda effettivamente 406 ma explorer (ad esempio, chrome) lo stampa come 404.

Se non si personalizza il convertitore di messaggi, la molla utilizza AbstractMessageConverterMethodProcessor.java. Sarebbe funzionare:

List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request); 
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType); 

e se non hanno alcuna sovrapposizione (lo stesso articolo), si getterebbe HttpMediaTypeNotAcceptableException e questo finalmente provoca 406. Non importa se si tratta di un ajax, o GET/POST, o la forma azione, se la richiesta URI termina con un .html o qualsiasi suffisso, il requestedMediaTypes sarebbe "text/[che il suffisso]", e tale procedura sia conforme producibleMediaTypes, che di solito è:

"application/json" 
"application/xml" 
"text/xml"   
"application/*+xml" 
"application/json" 
"application/*+json" 
"application/json" 
"application/*+json" 
"application/xml" 
"text/xml"   
"application/*+xml" 
"application/xml" 
"text/xml"   
"application/*+xml" 
Problemi correlati