Java Spring MVC 4:“application/json”内容类型设置不正确
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30548822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring MVC 4: "application/json" Content Type is not being set correctly
提问by user1757703
I have a controller mapped with the following annotation:
我有一个映射有以下注释的控制器:
@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public String bar() {
return "{\"test\": \"jsonResponseExample\"}";
}
I return a valid JSON string however, the content-type when I view the response on Chrome Dev Tools in browser is not application/json
but just plain text/html
. Why is the content type not being set?
但是,我返回了一个有效的 JSON 字符串,当我在浏览器中的 Chrome Dev Tools 上查看响应时,内容类型不仅application/json
是普通的text/html
. 为什么没有设置内容类型?
My web.xml
:
我的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>
My dispatcher-servlet.xml
:
我的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>
Using WildFly 8.1 as my app server.
使用 WildFly 8.1 作为我的应用服务器。
采纳答案by Sotirios Delimanolis
First thing to understand is that the RequestMapping#produces()
element in
要了解的第一件事是,RequestMapping#produces()
在元素
@RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json")
serves only to restrict the mapping for your request handlers. It does nothing else.
仅用于限制请求处理程序的映射。它什么都不做。
Then, given that your method has a return type of String
and is annotated with @ResponseBody
, the return value will be handled by StringHttpMessageConverter
which sets the Content-type
header to text/plain
. If you want to return a JSON string yourself and set the header to application/json
, use a return type of ResponseEntity
(get rid of @ResponseBody
) and add appropriate headers to it.
然后,假设您的方法的返回类型为String
并用 注释@ResponseBody
,则返回值将由将标头StringHttpMessageConverter
设置为 的处理。如果您想自己返回一个 JSON 字符串并将标头设置为,请使用(摆脱)的返回类型并向其添加适当的标头。Content-type
text/plain
application/json
ResponseEntity
@ResponseBody
@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);
}
Note that you should probably have
请注意,您可能应该有
<mvc:annotation-driven />
in your servlet context configuration to set up your MVC configuration with the most suitable defaults.
在您的 servlet 上下文配置中使用最合适的默认值设置您的 MVC 配置。
回答by John
Use Hymanson library and @ResponseBody
annotation on return type for the Controller.
@ResponseBody
在控制器的返回类型上使用 Hymanson 库和注释。
This works if you wish to return POJOs represented as JSon. If you woud like to return String and not POJOs as JSon please refer to Sotirious answer.
如果您希望返回表示为 JSon 的 POJO,这将起作用。如果您想将字符串而不是 POJO 作为 JSon 返回,请参阅 Sotirious 答案。
回答by ninj
As other people have commented, because the return type of your method is String
Spring won't feel need to do anything with the result.
正如其他人所评论的那样,因为您的方法的返回类型是String
Spring 不会觉得需要对结果做任何事情。
If you change your signature so that the return type is something that needs marshalling, that should help:
如果您更改签名以便返回类型需要编组,那应该会有所帮助:
@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;
}
回答by Greg Lindholm
When I upgraded to Spring 4 I needed to update the Hymanson dependencies as follows:
当我升级到 Spring 4 时,我需要更新 Hymanson 依赖项,如下所示:
<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-core</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-databind</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.Hymanson.core</groupId>
<artifactId>Hymanson-annotations</artifactId>
<version>2.5.1</version>
</dependency>
回答by Vishal
I had the dependencies as specified @Greg post. I still faced the issue and could be able to resolve it by adding following additional Hymanson dependency:
我有@Greg 帖子中指定的依赖项。我仍然面临这个问题,可以通过添加以下额外的 Hymanson 依赖项来解决它:
<dependency>
<groupId>com.fasterxml.Hymanson.dataformat</groupId>
<artifactId>Hymanson-dataformat-xml</artifactId>
<version>2.7.4</version>
</dependency>
回答by Tiina
Not exactly for this OP, but for those who encountered 404 and cannot set response content-type
to "application/json"
(any content-type
). One possibility is a server actually responds 406 but explorer (e.g., chrome) prints it as 404.
不完全是这个OP,但对于那些谁遇到404,并且不能设置响应content-type
于"application/json"
(任意content-type
)。一种可能性是服务器实际上响应 406,但资源管理器(例如,chrome)将其打印为 404。
If you do not customize message converter, spring would use AbstractMessageConverterMethodProcessor.java
. It would run:
如果您不自定义消息转换器,spring 将使用AbstractMessageConverterMethodProcessor.java
. 它会运行:
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request);
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);
and if they do not have any overlapping (the same item), it would throw HttpMediaTypeNotAcceptableException
and this finally causes 406. No matter if it is an ajax, or GET/POST, or form action, if the request uri ends with a .html
or any suffix, the requestedMediaTypes
would be "text/[that suffix]", and this conflicts with producibleMediaTypes
, which is usually:
如果它们没有任何重叠(相同的项目),它会抛出HttpMediaTypeNotAcceptableException
并最终导致 406。无论是 ajax、GET/POST 还是表单操作,如果请求 uri 以 a.html
或任何后缀结尾,这requestedMediaTypes
将是“文本/[那个后缀]”,这与 冲突producibleMediaTypes
,通常是:
"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"