简体   繁体   English

Spring MVC 4:“application/json”内容类型设置不正确

[英]Spring MVC 4: “application/json” Content Type is not being set correctly

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 .但是,我返回了一个有效的 JSON 字符串,当我在浏览器中的 Chrome Dev Tools 上查看响应时,内容类型不是application/json而是纯text/html Why is the content type not being set?为什么没有设置内容类型?

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 作为我的应用服务器。

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 .然后,假设您的方法具有String的返回类型并使用@ResponseBody注释,则返回值将由StringHttpMessageConverter处理,后者将Content-type标头设置为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.如果您想自己返回 JSON 字符串并将标头设置为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 配置。

Use jackson library and @ResponseBody annotation on return type for the Controller.在控制器的返回类型上使用 jackson 库和@ResponseBody注释。

This works if you wish to return POJOs represented as JSon.如果您希望返回表示为 JSon 的 POJO,这将起作用。 If you woud like to return String and not POJOs as JSon please refer to Sotirious answer.如果您想将字符串而不是 POJO 作为 JSon 返回,请参阅 Sotirious 答案。

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;
}

When I upgraded to Spring 4 I needed to update the jackson dependencies as follows:当我升级到 Spring 4 时,我需要更新 jackson 依赖项,如下所示:

    <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>        

I had the dependencies as specified @Greg post.我有@Greg 帖子中指定的依赖项。 I still faced the issue and could be able to resolve it by adding following additional jackson dependency:我仍然面临这个问题,可以通过添加以下额外的 jackson 依赖项来解决它:

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

Not exactly for this OP, but for those who encountered 404 and cannot set response content-type to "application/json" (any content-type ).不完全是针对这个 OP,而是针对那些遇到 404 并且无法将响应content-type设置为"application/json" (任何content-type )的人。 One possibility is a server actually responds 406 but explorer (eg, chrome) prints it as 404.一种可能性是服务器实际上响应 406,但资源管理器(例如,chrome)将其打印为 404。

If you do not customize message converter, spring would use AbstractMessageConverterMethodProcessor.java .如果不自定义消息转换器,spring 将使用AbstractMessageConverterMethodProcessor.java It would run:它会运行:

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 以.html结尾或任何后缀, requestedMediaTypes将是“text/[that suffix]”,这与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"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring MVC - 不支持内容类型“应用程序/json” - Spring MVC - Content type 'application/json' not supported POST上的Spring MVC不支持内容类型&#39;application / json&#39; - Content type 'application/json' not supported in Spring MVC on POST Spring MVC 和 jackson 不支持内容类型“application/json” - Content type 'application/json' not supported in Spring MVC and jackson 在 Spring 中读取 Content-Type 应用程序/json - Reading Content-Type application/json in Spring 如何将 Spring Webclient 的内容类型设置为“application/json-patch+json” - How do I set Content type for Spring Webclient to "application/json-patch+json" spring boot mvc - 不支持内容类型'application / json; charset = UTF-8' - spring boot mvc - Content type 'application/json;charset=UTF-8' not supported 无法使用Spring MVC / jackson序列化JSON以正确设置 - unable to serialize JSON to Set correctly with Spring MVC/jackson MVC-当自定义内容类型时接受JSON(不是application / json) - MVC - Accept JSON when content-type is custom (not application/json) 服务无法识别RestAssured内容类型application / json - RestAssured content-type application/json not being recognised by service Spring MVC REST-根据请求内容类型返回xml或json - Spring MVC REST - Returning xml or json according to request content type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM