java - responsebody - spring boot rest post json example
Spring MVC 4: el tipo de contenido "application/json" no se está configurando correctamente (6)
Tengo un controlador asignado con la siguiente anotación:
@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public String bar() {
return "{/"test/": /"jsonResponseExample/"}";
}
Sin embargo, devuelvo una cadena JSON válida, el tipo de contenido cuando veo la respuesta en Chrome Dev Tools en el navegador no es application/json
sino text/html
simple text/html
. ¿Por qué no se establece el tipo de contenido?
Mi 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>
Mi 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>
Usando WildFly 8.1 como mi servidor de aplicaciones.
Como otras personas han comentado, porque el tipo de retorno de su método es String
Spring no sentirá la necesidad de hacer nada con el resultado.
Si cambia su firma de modo que el tipo de retorno sea algo que necesita reorganización, eso debería ayudar:
@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;
}
Cuando actualicé a Spring 4 necesitaba actualizar las dependencias de jackson de la siguiente manera:
<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>
Lo primero que hay que entender es que el elemento RequestMapping#produces()
en
@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json")
Solo sirve para restringir el mapeo de sus manejadores de solicitudes. No hace nada más.
Luego, dado que su método tiene un tipo de String
de retorno y se anota con @ResponseBody
, el valor de devolución será manejado por StringHttpMessageConverter
que establece el encabezado de Content-type
en text/plain
. Si desea devolver una cadena JSON usted mismo y establecer el encabezado en application/json
, use un tipo de ResponseEntity
de ResponseEntity
(deshacerse de @ResponseBody
) y agregue los encabezados apropiados.
@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);
}
Tenga en cuenta que probablemente debería tener
<mvc:annotation-driven />
en su configuración de contexto de servlet para configurar su configuración de MVC con los valores predeterminados más adecuados.
No exactamente para este OP, pero para aquellos que encontraron 404 y no pueden establecer el content-type
respuesta en "application/json"
(cualquier content-type
). Una posibilidad es que un servidor responda en realidad 406, pero el explorador (por ejemplo, Chrome) lo imprime como 404.
Si no personaliza el convertidor de mensajes, Spring usaría AbstractMessageConverterMethodProcessor.java
. Se ejecutaría:
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request);
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);
y si no tienen ninguna superposición (el mismo elemento), arrojará HttpMediaTypeNotAcceptableException
y esto finalmente causa 406. No importa si es un ajax, o GET / POST, o acción de formulario, si la solicitud uri termina con un .html
o cualquier sufijo, los requestedMediaTypes
medios requestedMediaTypes
serían "texto / [ese sufijo]", y esto entra en conflicto con los producibleMediaTypes
, que generalmente es:
"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"
Tuve las dependencias según lo especificado @Greg mensaje. Todavía enfrenté el problema y podría resolverlo agregando la siguiente dependencia adicional de jackson:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.7.4</version>
</dependency>
Utilice la biblioteca jackson y la anotación @ResponseBody
en el tipo de devolución para el controlador.
Esto funciona si desea devolver POJOs representados como JSon. Si desea devolver String y no POJO como JSon, consulte la respuesta de Sotirious.