转载http://ks.netease.com/blog?id=4024 作者:李景
 
 
场景:

         前端Post请求同一个url地址,在chrome浏览器上有正常返回json,而在firefox浏览器上却报500错误。
         下面是controller层的写法:
         
   其他类似的接口都可以正常使用,查看了其他接口的写法,区别在于多了一个header。
 
   与其他接口唯一的区别就是少写了一个Accept=application/json。
 
这是为什么呢?通过查看源码以及对两个浏览器请求头的对比,终于找出问题的原因,下面一一道来。
看到后台有报错:
根据错误,大概可以看出是模板解析错误,怎么用ff请求的时候会使用xml进行解析呢?
应用是使用Freemarker进行页面渲染,配置如下:

 <bean
            >
        <property name="defaultContentType" value="application/json"/>
        <property name="mediaTypes">
            <map>
                <entry key="html" value="text/html;charset=UTF-8"/>
                <entry key="json" value="application/json;charset=UTF-8"/>
                <entry key="xml" value="application/xml;charset=UTF-8"/>
            </map>
        </property>
        <property name="viewResolvers">
            <list>
                <bean
                        >
                    <property name="cache" value="false"/>
                    <property name="prefix" value=""/>
                    <property name="suffix" value=".ftl"/>
                    <property name="exposeSpringMacroHelpers" value="true"/>
                    <property name="exposeRequestAttributes" value="true"/>
                    <property name="exposeSessionAttributes" value="true"/>
                    <property name="allowSessionOverride" value="true"/>
                    <property name="contentType" value="text/html;charset=UTF-8"/>
                </bean>
            </list>
        </property>
        <property name="defaultViews">
            <list>
                <bean
                        >
                    <property name="objectMapper" ref="objectMapper"/>
                    <property name="contentType" value="application/json;charset=UTF-8"/>
                    <property name="modelKeys">
                        <set>
                            <value>msg</value>
                            <value>res</value>
                            <value>errmsg</value>
                        </set>
                    </property>
                </bean>
                <bean id="marshallingView"
                      >
                    <property name="marshaller" ref="xstreamMarshaller"></property>
<property name="modelKey" value="msg"></property>
                   <property name="contentType" value="application/xml"/>
                </bean>
            </list>
        </property>
    </bean>
Freemarker有两种默认的返回结果,分别是json和xml。
最后返回的结果会由org.springframework.web.servlet.view.ContentNegotiatingViewResolver这个类来处理,由这个类来决定使用哪种view方式返回。
具体的转换方法如下:
再来看一下chrome请求头部和firefox请求头部的区别:
chrome的请求头中Accept的值为:*/*
对应上面的步骤:
1、获得请求头部中accept信息:*/*

2、获得转换器中支持Accept的media类型:*/*

3、转换器中支持的media类型是否兼容请求过来的Accept类型:*/*

4、根据请求等参数选择最佳的view

配置文件件配置了defaltView为MappingJackson2JsonView和MarshallingView,顺序匹配,为*时直接匹配上第一种,直播选择MappingJackson2JsonView解析。

firefox中请求头的Accept为text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
对应上面的步骤:
1、获得请求头部中accept信息:text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8

2、获得转换器中支持Accept的media类型:*/*

3、转换器中支持的media类型是否兼容请求过来的Accept类型:text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8

4、根据请求等参数选择最佳的view

配置文件件配置了defaltView为MappingJackson2JsonView和MarshallingView,顺序匹配,当匹配到application/xml时,直播返回使用MarshallingView解析。

以上步骤均是controller中没有加headers = { "Accept=application/json" }的情况,那为什么加了这段代码,firefox就可以运行了呢?

这时对应上面的步骤结果为:

1、获得请求头部中accept信息:text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8

2、获得转换器中支持Accept的media类型:application/json;q=0.8

3、转换器中支持的media类型是否兼容请求过来的Accept类型:application/json;q=0.8

4、根据请求等参数选择最佳的view:candidateViews类型为application/json,自然用MappingJackson2JsonView解析。

看上面的步骤大家已经明白了,加上Accept=application/json后获取的media类型就可以直接为application/json了,所以可以直接使用MappingJackson2JsonView解析,进而返回json数据格式。

再做了个实验,就是调换了一下defaultVeiws的配置顺序,把MarshallingView放在前面,在不加Accept=application/json,用chrome请求时,结果返回xml格式。

也就是说当accept是*/*时,他是顺序匹配的。

在spring mvc中,如果想返回的格式是指定的,也可以配置produces变量:

@RequestMapping(value = "/upload",produces="application/json;charset=UTF-8")

也可以达到同样的效果。

结论:

使用spring mvc时,如果返回的数据格式不正确,需要看一下请求头部的accept、controller层的header配置、以及配置文件中模板的渲染类型和配置顺序,通过这三个方式可以定位出原因。

使用spring mvc返回JSON,chrome可以,firefox不行的问题定位的更多相关文章

  1. spring mvc返回json字符串的方式

    spring mvc返回json字符串的方式 方案一:使用@ResponseBody 注解返回响应体 直接将返回值序列化json            优点:不需要自己再处理 步骤一:在spring- ...

  2. spring mvc返回json字符串数据,只需要返回一个java bean对象就行,只要这个java bean 对象实现了序列化serializeable

    1.spring mvc返回json数据,只需要返回一个java bean对象就行,只要这个java bean 对象实现了序列化serializeable 2. @RequestMapping(val ...

  3. Spring mvc 返回JSON 在IE 下提示下载 解决办法

    http://www.blogjava.net/iamlibo/archive/2013/11/21/406646.html ————————————————————————————————————— ...

  4. Spring MVC返回json数据给Android端

    原先做Android项目时,服务端接口一直是别人写的,自己拿来调用一下,但下个项目,接口也要自己搞定了,我想用Spring MVC框架来提供接口,这两天便抽空浅学了一下该框架以及该框架如何返回json ...

  5. Spring mvc 返回json格式 - 龙企阁 - 博客频道 - CSDN.NET

    第一次使用spring mvc ,在此也算是记录一下以防忘记,希望有经验的朋友指出不足的地方 一.使用maven管理jar. <dependency> <groupId>org ...

  6. spring mvc 返回json的配置

    转载自:http://my.oschina.net/haopeng/blog/324934 springMVC-servlet.xml 配置 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  7. Spring MVC返回json格式

    在使用SpringMVC框架直接返回json数据给client时,不同的版本号有差异. 以下介绍两种类型的版本号怎样配置. 注意:这两种方法均已验证通过. 1.Spring3.1.x版本号 1.1 d ...

  8. 转:spring mvc返回json数据格式

    转:http://www.cnblogs.com/ssslinppp/p/4675495.html <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: ...

  9. Spring MVC 返回json数据 报406错误 问题解决方案

    将jackson jar包改为jackson-databind-2.5.0.jar  jackson-core-2.5.0.jar  jackson-annotations-2.5.0.jar(这个版 ...

随机推荐

  1. Trie树详解

    1. 概述 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树.Trie一词来自retrieve,发音为/tri ...

  2. 使用函数指针调用C++虚函数

    基本概念: 1. 函数指针,一个地址指针变量,其值指向代码区的某个函数首地址. 2. 虚函数,可以被子类覆写的C++成员函数.由虚函数表实现. 3. 虚函数表指针(vpt),指向虚函数表首地址的指针, ...

  3. js实用方法记录-js动态加载css、js脚本文件

    js实用方法记录-动态加载css/js 附送一个加载iframe,h5打开app代码 1. 动态加载js文件到head标签并执行回调 方法调用:dynamicLoadJs('http://www.yi ...

  4. QBC查询

    1.基本语法 session.beginTransaction(); Criteria criteria = session.createCriteria(Person.class); SimpleE ...

  5. iOS最新企业证书的生成

     PS:不知道什么原因  图片显示不出来 请看我简书里面的文章 http://www.jianshu.com/p/baab03ac43e9 1.生成CSR文件 SpotLight搜索>钥匙串访问 ...

  6. java虚拟机学习-慢慢琢磨JVM(2)

    1 JVM简介 JVM是我们Javaer的最基本功底了,刚开始学Java的时候,一般都是从“Hello World”开始的,然后会写个复杂点class,然后再找一些开源框架,比如Spring,Hibe ...

  7. 用border或者div制作三角形等图形

    一般情况下, 我们设置盒子的宽高度, 及上下左右边框, 具体代码如下: 通过上述代码,div的具体样式如下: 现在在上面基础上, 我们把div的宽高度都设为0时, 现在我们再次查看效果,如下图: 这时 ...

  8. WebService入门实例教程

    什么是WebService 通过使用WebService,您的应用程序可以向全世界发布信息,或提供某项功能,它是基于Web的服务,通过Web进行发布.查找和使用. WebService脚本平台需支持X ...

  9. css的定位,relative/absolute/fixed的用法

    其实position的值有四个,static/relative/absolute/fixed,而static是默认值,不算具有有定位属性,这里就不讲了. 定位其实就是跟元素设置定位属性,然后设置其对位 ...

  10. Visual Studio Code 使用心得

    Visual Studio Code 使用心得 最好用的跨平台编辑器,没有之一! 修改编辑器的显示语言 起因:vsCode又升级了(1.13.0),重启之后发现熟悉的中文菜单没有了,而且设置文件 se ...