客户端和服务器端的乱码问题

1. 服务器端发送数据到客户端(如:浏览器的乱码问题

在整个服务器端数据返回到浏览器的过程中,涉及到三次编码。 
第一次:java文件以什么编码存放在硬盘中,一般工程全部使用UTF-8编码方式,所以程序中的中文字符是以UTF-8形式编码的 
第二次:中文字符串是以什么编码方式转换成字节数组的,如果未指定@RequestMappingproduces属性,同时也未给StringHttpMessageConverter指定编码方式,最终中文字符串是以ISO-8859-1形式转换成字节数组的 
第三次:数据发送给浏览器后,浏览器接收到一堆字节数组,浏览器又是以什么编码方式来解码的。 浏览器的解码方式由responsecontent-type决定。
这样才能保证不会乱码,首先java文件是以UTF-8形式存储的,然后指定StringHttpMessageConverter或者@RequestMappingproduces的编码方式为UTF-8,最后发给浏览器的header中的content-type也为UTF-8,这样才不会乱码。 

 

流程分析:

假设服务器向客户端返回一个中文字符串,首先由RequestMappingHandlerAdapter来调度执行,由于是@ResponseBody,所以从所有的已注册的HandlerMethodReturnValueHandler中找到了@ResponseBody的支持者RequestResponseBodyMethodProcess。然后就是根据客户端Accept字段指定的多个content-type和服务器端指定的content-type进行比较配对,选出最合适的一个content-type。此时,如果@RequestMapping中并没有为produces指定相应的content-type会获取所有的已注册的HttpMessageConverter所支持的content-type作为服务器端指定的content-type因为服务器返回的是字符串,所以最终会选出text/html作为最终的content-type服务器端数据要以text/html形式写入responsebody中。有了返回值的类型为Stringcontent-typetext/html,然后就是从已注册的HttpMessageConverter中找到一个支持这两者的HttpMessageConverter,然后就找到了StringHttpMessageConverter,它有两个构造函数,一个可以指定字符集,当什么都没有指定时,默认使用ISO-8859-1。在将返回值以text/html形式写入responsebody中时,StringHttpMessageConverter先从上述所选出的content-type(即text/html)中尝试获取字符集,若获取不到(因为没在构造函数中指定),则使用自己默认的ISO-8859-1,所以charset就为StringHttpMessageConverter默认的ISO-8859-1,造成了编码方式不对,同时ISO-8859-1是不支持中文的,所以就出现了乱码。

 

解决方式:指定@RequestMappingproduces"text/html;charset=UTF-8"即可解决乱码。 此时StringHttpMessageConverter可以从这个content-type读取到编码方式,便不再采用默认的编码方式ISO-8859-1,并返回的字节数组写responsebody中,同时设置responsecontent-typeproduces的值即text/html;charset=UTF-8,浏览器拿到这个content-type便知道以UTF-8形式来解码这些字节数组

注意:只在配置文件中指定StringHttpMessageConverter的编码方式(如下),是不能完全解决乱码问题的,此方式只会让StringHttpMessageConverter以指定的编码集(如:UTF-8)来转换成字节数组写入resposnebody中。 但是,返回给浏览器的content-type字段并没有指定编码集,浏览器将以它默认的方式来解码(如果 浏览器的 解码方式不是utf -8就会造成乱码 

<mvc:annotation-driven>  

        <mvc:message-converters>  

            <bean class="org.springframework.http.converter.StringHttpMessageConverter">  

                <constructor-arg value="UTF-8"/>  

            </bean>  

        </mvc:message-converters>  

    </mvc:annotation-driven> 

 

2. 客户端到服务器端乱码问题

如:输入http://localhost:8080/test?name=中国,向服务器发送请求,整个过程涉及到2次编码: 
第一次:浏览器将以什么样的编码方式将中文字符串转化成字节数组,这称为URL编码 
第二次:当浏览器发送请求时,服务器是以请求的content-type来解析请求数据的,当浏览器请求没有指定content-type时,服务器又是采用什么样的编码来解析的 服务器一般根据requestcontent-type来解析字符串,如果没有指定content -type 则采用服务器默认的编码方式解码。

乱码的本质:这两次编码方式不一致 

 

1、针对第一个过程,当你仅仅在浏览器上输入http://localhost:8080/test?name=中国来访问时,不同的浏览器会采用不同编码方式来将中国转换成字节数组。比如说chrome浏览器始终以UTF-8的编码形式将中国转换成字节数组。而IE浏览器则是以GBK的编码方式来转换的,正是由于不同浏览器的不同处理情况,导致了可能用chrome发送服务器端正常,IE发送则乱码的现象。 

2针对第二个过程:由于未指定requestcontent-type来让服务器解析这些字节数组,它到底采用什么样的方式来解析呢,不同的服务器应该有不同的策略,并且可以进行设置。如Tomcat服务器,默认采用的是ISO-8859-1,可以修改Tomcatconf/server.xml文件来修改Tomcat的默认编码解析方式。 
这里的tomcat版本是7,在tomcat8中已修订,不存在这个乱码问题 

因此要解决乱码问题就要指定客户端发送的requestcontent-type

猜你喜欢

转载自blog.csdn.net/u013789656/article/details/80937499