【Java】SpringMVC Post&Get编码问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/o0DarkNessYY0o/article/details/52338368

标题图片

      最近不是弄着JAVAWeb项目嘛,刚好学到SpringMVC,而且通过注释注入的方式真心方便快捷,做起来感觉比Struts速度快多了。在项目制作的过程中难免会碰到编码问题,尤其是从本地项目上传到服务器中,自己做的项目中肯定是碰到这个问题了的,于是记录下来,方便以后项目的跟进。

      编码其实并没有太多的特殊要求,只是。。。对中文或者其它的一些类似中文的文字的编码,不像英文那样简便,于是乎。。。编码之前的转换就不能水到渠成,自然而然的会有很多很多的乱码出现在日常码代码之中。。。下面先百度一下常见的几种编码。

iso8859-1

      iso8859-1 通常叫做Latin-1,属于单字节编码,最多能表示的字符范围是0-255,应用于英文系列。比如,字母a的编码为0x61=97。 很明显,iso8859-1编码表示的字符范围很窄,无法表示中文字符。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用iso8859-1编码来表示。而且在很多协议上,默认使用该编码。比如,虽然”中文”两个字不存在iso8859-1编码,以gb2312编码为例,应该是”d6d0 cec4”两个字符,使用iso8859-1编码的时候则将它拆开为4个字节来表示:”d6 d0 ce c4”(事实上,在进行存储的时候,也是以字节为单位处理的)。

GDK/GB2312

      GB2312是汉字的国标码,是简体中文的字符集编码;专门用来表示汉字,是双字节编码,而英文字母和iso8859-1一致(兼容iso8859-1编码)。
      苹果OS以GB2312为基本汉字编码;
      GBK 是 GB2312的扩展,除了兼容GB2312外,它还能显示繁体中文,还有日文的假名;
      Windows 95/98以GBK为基本汉字编码、但兼容支持GB2312。

ANSI

      不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文操作系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。(BIG5:台湾标准)
      不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。
      ANSI编码表示英文字符时用一个字节,表示中文用两个字节,而unicode不管表示英文字符还是中文都是用两个字节来表示。

unicode

      Unicode(统一码、万国码、单一码、标准万国码)是业界的一种标准,它可以使电脑得以呈现世界上数十种文字的系统。
      大概来说,Unicode 编码系统可分为编码方式和实现方式两个层次。
Unicode 的编码方式与 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相对应,目前实际应用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示 2 即 65536 个字符。基本满足各种语言的使用。实际上      目前版本的 Unicode 尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。
      Unicode 的实现方式不同于编码方式。一个字符的 Unicode 编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为Unicode转换格式(Unicode Translation Format,简称为 UTF)。
      目前通用的实现方式是 UTF-16小尾序(BOM)、UTF-16大尾序(BOM)和 UTF-8。在微软公司Windows XP操作系统附带的记事本中,“另存为”对话框可以选择的四种编码方式除去非 Unicode 编码的 ANSI 外,其余三种“Unicode”、“Unicode big endian”和“UTF-8”即分别对应这三种实现方式。
      注:通常我们看到的编码选项中,和UTF-8放在一块的“Unicode编码”指的是UTF-16 小端编码;

UTF-8

       UTF-8是UNICODE的一种变长字符编码,由Ken Thompson于1992年创建。
      UTF-8, 8bit编码, ASCII不作变换, 其他字符做变长编码, 每个字符1-3 byte(英文字母用一个字节,汉字使用3个字节),有以下两个优点:
      与CPU字节顺序无关, 可以在不同平台之间交流
      容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码)
      UTF-16, 16bit编码, 是变长码, 大致相当于20位编码, 值在0到0x10FFFF之间, 基本上就是unicode编码的实现. 它是变长码, 与CPU字序有关, 但因为最省空间, 常作为网络传输的外码.
      UTF-8与UTF-16的区别
      UTF8 和 UTF16 都是变长表示的,欧美程序员会觉得太浪费,因为欧美字符 0x0000 - 0x00FF 就搞定了,UTF8 最小变长是 1 个字节,而 UTF16 变长是 2 个字节, utf-8 与 uft-16 表示 ‘a’ a的ascii是0X61 ;utf-8为[0X61] ;uft-16 [0x00,0X61]
      注意,虽然说utf-8是为了使用更少的空间而使用的,但那只是相对于utf-16编码来说,如果已经知道是汉字,则使用GB2312/GBK无疑是最节省的。

如何查看文件编码

      很简单,我一般都是用NotePad++这个工具,很方便而且免费的,用起来特别舒服。如果懒得下载个工具的话,直接用Windows自带的记事本就行,保存或者另存为的时候,就会在文件名的下面出现当前选择编码。

SpringMVC下配置编码的统一

      玩过Java-Web开发的朋友肯定都知道,网络传输请求为POST和GET两种请求,简单区分一下它们,就是GET是从服务器上获取数据而POST则是向服务器传送数据。

      知道了就简单许多了,一般涉及到配置这方面的,在Java-Web中肯定少不了要找的就是项目的配置文件——web.xml!而一般的编码问题就是通过在里面添加下面这个来统一的:

<filter>
    <!-- filter名,标识用 -->
    <filter-name>CharacterEncoding</filter-name>

    <!-- 使用编码包 -->
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

    <!-- 设置编码类型为UTF-8 -->
    <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>CharacterEncoding</filter-name>    
    <url-pattern>/*</url-pattern><!-- 对工程下所有文件有效 -->
</filter-mapping>  

      当然哈,这个filter过滤器类可以自己继承来写,具体写法可以参考tomcat6中webapps\examples\WEB-INF\classes\filters下SetCharacterEncodingFilter这个类。

      好了,在我们以为这个完全能够满足我们了的时候,很遗憾,现实是残酷的,我们上面做的这些。。。仅仅是做了POST请求方面的编码,而GET请求上的是不起作用的,因为Tomcat对这两种请求的处理方式是不一样的,因此,我们要修改一下Tomcat服务器的配置文件Server.xml,找到这里:

<!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

      就是这个属性,看好注释,很多长一样的说,就是注释不一样,找错了用不起别找我哈,当然,Linux系统下,也是一样一样的,都在Tomcat服务器文件夹conf目录下,不过如果你是使用Eclipse的话,那就更简单了,工程那边有个Server,点它进去就是了,里面就有这个配置文件!找到后添加个后缀,成下面的样子(前面的注释我就不复制粘贴占用版式了)

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>

      注意哈!配置useBodyEncodingForURI=”true”后,基本可以解决普通GET请求的中文乱码问题,但是对于通过Ajax发起的GET请求中文依然会乱码,把useBodyEncodingForURI=”true”改为URIEncoding=”UTF-8”就能解决此问题。

JSP页面下配置编码统一

      这个就只是预防中的预防了,放置可能存在的潜在编码问题,于是我们还需要在页面文件中进行一些小小的处理才行!

      最好是在JSP文件顶部下上<%@ page language=”java” pageEncoding=”UTF-8”%>的一行,使我们的Eclipse会自动将该网页存为UTF-8的编码格式,这样不管Eclipse的默认/当前是什么,我们的页面也使用能够保持UTF-8的编码,这是个小技巧。

      另外还要注意一下头部写的这些东西!

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=iso8859-1"%>

      显而易见,这里的文件编码格式是UTF-8,而设置的当前浏览器解码方式却是iso8859-1!这样编码和解码方式都不同意,势必会出现中文乱码的现象!因此我们得将其统一一下:

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=UTF-8"%>

JAVA文件中配置编码统一

      在fliter中设置一下request.setCharacterEncoding("UTF-8");是把提交内容的字符集设为UTF-8(GET方法),并且一起设置response.setCharacterEncoding("UTF-8");可以把页面中的<%@ page contentType=”text/html;charset=iso8859-1”%>换为charset=UTF-8,是给告诉浏览器当前处理的文件的编码方式(POST方法)。

      上面是其一,我们在字符串处理的使用同样的也可以进行一下操作,即通过String des = new String(s.getBytes("iso8859-1"),"UTF-8");来转换成你想要的UTF-8编码方式。举个栗子:从地址栏获取中文,用new String(request.getParameter("getChinese").getBytes("ISO-8859-1"),"GBK");

结尾后话

      这下就基本搞掂了这个SpringMVC的中文编码乱码的问题了,这些问题解决起来挺繁琐的,我从数据库到代码全部都改过了一边,这些血淋淋的经验希望能给后来者或者正在困扰者提供一些帮助,我现在尽量写够15篇,后面我学习安卓-Web服务器知识的时候希望会以博客专栏的形式推出,一个模块一个专栏的,我分得清楚点儿方便管理,大家也看得舒服,谢谢大家的支持~喜欢轻点赞关注我哦~


2016.09.08补充

      这两天在调试过程中发现,有时候GET请求还是有点儿编码问题不能得到解决,于是整个项目和Tomcat都给检查了一编,发现在Tomcat的bin目录下Server.xml修改

<service name="Catalina">
    ...大量注释
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    ...大量注释
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
    ...后面不管

      就在第一个Connector标签加上一个URIEncoding=”UTF-8”的属性,我把下面这个一块复制上来就是怕大家容易搞混的,这里希望大家也能注意一下,设置成下面这样就OK了!

<service name="Catalina">
    ...大量注释
    <Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    ...大量注释
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
    ...后面不管

      补充完毕!补充之前的那些方法大多作用于POST请求,所以在我们某些使用Ajax使用到的GET方法的时候将有可能会碰到这些麻烦事儿,不过还好,这里也给大家补充完毕了。最后呢,如果有什么更好的解释或者是设置方法希望大家多多交流,在下方留言即可,谢谢大家!

猜你喜欢

转载自blog.csdn.net/o0DarkNessYY0o/article/details/52338368