spring mvc 之彻底解决乱码问题。

1.界面乱码问题

首先分析一下整个流程,首先浏览器打开网页,获取网页数据,读取meta标签中设置的编码,通过指定的编码解析网页,假如未设置,浏览器则采用默认编码进行解析,每个浏览器的默认编码是不一样的。所以会导致这个浏览器不乱码那个浏览器乱码问题。

针对jsp解决该问题的方法是添加如下代码即可

<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8" %>

 通过设置contentType属性中charset设置指定编码,jsp在解析的时候或自动将该属性值解析到如下标签中

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

所以说加了page命令后,这段meta标签其实根本没必要添加就会自动出现。

针对html页面乱码则添加上面的meta标签即可解决乱码问题。注意,meta标签需要添加到head标签里面。

2.传递参数乱码问题

我们继续分析流程,浏览器通过获取meta标签的编码后,那么她同时会将该编码设置为表单提交编码和ajax提交编码。这时候如果提交表单、(假如说项目是运行在tomcat中的,那么先是会提交到tomcat中,tomcat在通过web.xml的配置将请求交给过滤器、servlet等等),tomcat这里对请求做了一次编码处理。也就是我们的tomcat的context.xml配置文件

<Connector executor="tomcatThreadPool"
        port="8080" protocol="HTTP/1.1"
        connectionTimeout="20000"
        redirectPort="8443"
        URIEncoding="UTF-8" />

这段代码,特别注意:别把注释的代码改了,真正的代码没改(最好用支持代码高亮显示的编辑器编辑)。这里的port则是启动端口、protocol是HTTP协议版本、connectionTimeout连接超时时间(单位毫秒)、URIEncoding这个是uri编码,什么是URI呢?URI其实就是请求url域名后面那段玩意,比如说http://www.baidu.com/test/hello,的uri就是/test/hello。也就是说这个配置会影响到所有的GET请求编码,和部分POST请求编码。因为GET请求的参数全部拼在url后面的,所以会直接影响。至于post请求,form表单方式提交都在请求体(详解请科普http协议)里面,不在url后面。所以这里不会影响到他。但是ajax的post提交,这个是可以自定义的,如果是拼接在url后面的参数自然也会影响到。请求体里面则不会。有的get请求乱码post不乱码的问题就是因为这个原因。

继续分析流程,请求通过了tomcat、下一步是进入web.xml中的拦截器。假如没有拦截器就直接进入过滤器。springmvc是通过以下代码解决乱码问题的。

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

可以看出来,这就是过滤器。这个过滤器原理很简单,有空间的可以看下源码。就是设置了request的编码。至于这个forceEncoding是个什么呢,他其实就是是否同时设置response的编码。默认值为false,也就是不设置。那么问题来了,springmvc也是个过滤器。他们都是过滤器、假如说请求来了。请求先进了springmvc的过滤器,然后再进这个编码过滤器。那么这个编码过滤器岂不是没有任何作用。因为请求都处理完了,再来设置编码还有什么用呢。所以这里有个执行顺序问题了,web.xml中的过滤器执行顺序其实很简单,就是写在前面的先执行,后面的后执行。通常把编码过滤器设置为最前面的过滤器就可以了。

3.代码中正常,数据库缺乱码了

这个问题就是因为数据编码与代码编码不一致照成的,数据库的编码不处决与表。不存在这张表是这个编码那张表是这个编码。所以要乱码就所有的表全乱码。解决方案是更改数据库的编码,有时候更改并不会成功。就需要删除数据库(删库跑路),然后重新创建数据库(创建时选择编码)。一定要记得备份数据,别真的删库跑了。即可解决、每种数据的操作方式都不一样。这里不多做介绍,自行百度百科。

4.springmvc深坑之@ResponseBody乱码

比如说一些ajax异步请求,会直接在控制器方法上加上ResponseBody注解,然后就可以直接返回String、或者实体类型了。springmvc会自动给我解析成字符串或json数据返回给浏览器。神奇的spirngmvc既然在这里乱码了,tomcat也配好了,编码过滤器也配置了,forceEncoding属性也设置为true了。结果还是乱码,需要加如下代码解决

方案一

@RequestMapping(value = "test.html",produces = "application/json;charset=utf-8")

就是在控制器请求方法的RequestMapping注解中配置produces属性,即可设置响应编码。这个解决方法的缺点就是直接解决一个方法,每个方法都加一个这个玩意就太恶心了。

方案二

<mvc:annotation-driven>  
    <mvc:message-converters>  
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>  
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">  
            <property name="supportedMediaTypes">  
                <list>  
                    <value>text/plain;charset=utf-8</value>  
                    <value>text/html;charset=UTF-8</value>  
                </list>  
            </property>  
        </bean>  
    </mvc:message-converters>  
</mvc:annotation-driven>

配置一个这个就全部解决了。下面来说一下,为什么会乱码了。这里就简单说一下,具体要区看spring的源代码。springmvc在处理返回方法上面有ResponseBody注解的方法时,会进入很多个消息转换器。上面的配置都是配置消息转换器的编码,假如说是对象类型会先进入一个将对象转换成json字符串的转换器、然后再将处理结果交个字符串转换器去处理、接着会处理成byte二进制数据、这里就需要通过指定编码转换成二进制数据。我们的配置就是配置这个玩意,中间还有很多复杂步骤。这里就简单概括一下。

到这里springmvc的乱码问题几乎就已经不存在了。

猜你喜欢

转载自my.oschina.net/u/3551926/blog/1600136