? 我们在开发的过程中,不可避免的会遇到前后端的数据通信问题,又不可避免的会遇到数据为中文的情况,初学者在毫不知情中,就遭遇了自己的第一次中文乱码问题,今天,我们就一起来探讨下中文乱码问题为何会发生、以及如何解决前后端数据传输的中文乱码问题。

  ? 为了更好的展示中文乱码问题,我们来举个栗子,首先,前端页面如下所示:

  ? 后端Servlet中对应的获取代码如下:

  ? 页面上输入对应的值后,比如输入李子树/26,点击提交后,后端打印的结果如下图所示,出现了中文乱码问题,以上为本文背景。

  资源分配图

  ? 其实说到中文乱码,其出现的根本原因就是字符编码和解码使用的字符集不同,因为汉字较为复杂,以至于个人PC诞生后的一段时间,中文的输入问题都没有很好的解决, 可以这么说在中文在不同的字符集中,汉字的编码都几乎没有雷同。

  资源分配图

  ? 就好像早期战争时期发电报一样,发之前将内容按照密码本进行编码,转成密码本中对应的页数、行数、列数,使之可以唯一的对应上一个字,接收方收到电报后,根据约定好的密码本,再将接收到的报文进行转码,这样就可以通过无线电来传输数据。这其中,密码本就可以认为是一个字符集,如果编码和解码使用的不是同一个密码本,那么就无法获得真正的报文内容,也就是乱码问题。

  ? 上面的例子是在战争时期的谍报,主要是为了加密,防止被敌人知道情报。但是到现在的信息时代,字符集的提出,是为了统一标准,让数据可以更好的传输。我们来看些常用的字符集:

  ASCII:编程必学必知必会,使用一个字节来表示包括拉丁字母,数字,常用标点符号及控制符,ASCII码表中共128个字符;ISO-8859-1:利用了ASCII剩下的128字符(1字节8位,表示范围为0~255),添加了对西欧语言的支持;GB2312:中国国家标准局最早发布的简体中文字符集,可以完美的支持中文,一个汉字占两个字节;GBK:在GB2312的基础上,增加了对繁体中文的支持;UTF-8:是Unicode(万国码)编码的一种实现方式,也是目前最常用的字符集,是一种变长字节编码方式,其使用1~4个字节表示一个符号,会根据不同的符号而变化字节长度,一个汉字占三个字节。

  ? 了解了字符集后,我们在回过头看下我们在第一部分遇到的问题,数据在传输前,因为页面上设置了编码方式为UTF-8(Content-Type),因此编码方式为UTF-8,而服务器收到字节流后默认使用ISO-8859-1来解码,因此导致中文乱码问题。

  ? 知道了原因,那么问题解决起来就简单多了,(其实在实际开发中,肉眼可见的错误是最好解决的,再辅以报错信息,令人头疼的是逻辑错误,尤其是多线程、高并发、环境等导致的问题)我们只需保证在浏览器处使用的编码方式和服务器端一致即可。

  ? 对于上述问题,我么将服务器端的代码修改如下:

  ? 之后,我们在浏览器上再次点击提交后,即可看到如下页面,乱码问题被解决啦。

  资源分配图

  ? but、but、but,注意到上面代码块中的注释了么,setCharacterEncoding方法设置的编码方式只对该request中的请求体有效,有我们的上篇博文中,我们说到了Http请求主要有三部分组成:请求行、请求头、请求体,而数据包含在请求行的queryString中或者请求体的FormData中。

  ? 我们在来看下setCharacterEncoding方法的方法说明,也验证了我们刚才的说法。

  ? 那我们就来验证下以get方式,在url中传输数据的中文乱码问题,我们只需将前端页面中form表单中的method属性由post改为get即可,再次输入李子树/26,点击提交后一起看下结果:

  资源分配图

  资源分配图

  ? 啥、啥、啥、啥,为什么会有两张截图,因为你的运行结果会是这两者之间的一种。说到这里,我们就需要知道另一些知识了,首先我们来看张图片:

  资源分配图

  ? 这里相信大家看到的都是相同的结果,不过这里不是我们要说的中文乱码发生的案发现场,在这里我们看到的url是经过URLEncode编码过的,浏览器将此次HTTP请求提交到Http服务器,敲黑板敲黑板,Http服务器在将Http请求封装成HttpServletRequest时,对url进行了一次编码,这也是为啥url里的中文参数也会出现中文乱码问题。

  ? 但是为啥部分同学在上例中没有出现中文乱码问题?这里就要说下统一编码格式的重要性了,因为UTF-8的强大包容性,使得其使用范围最广,也直接影响了Tomcat,Tomcat在8.0以后的版本中,默认编码改为了UTF-8,在8.0之前的版本中,默认的编码为ISO-8859-1。这也是为什么上面的程序会出现两种结果,主要是因为服务器的默认编码方式的不同。

  ? 那当服务器为Tomcat V7.0时,又要如何解决url中的中文参数乱码问题?主要有两种方式:

  在后端先讲参数值使用ISO-8859-1编码方式转为字节数组,再将其使用UTF-8来进行编码,示例代码如下:修改Tomcat服务器的默认编码方式,保持和服务器一致,方法如下:

  ? 修改tomcat安装路径下conf文件夹下的server.xml文件,在Connector节点上新增一属性useBodyEncodingForURI,如下图所示:

  ? 这里需要注意的是,useBodyEncodingForURI属性的默认值为false,当设置为true时,url的编码方式则和body使用的编码方式相同,注意,这里在后端代码中,需要设置body的编码方式。

  ? 同时,Tomcat还提供了一个URIEncoding属性,用于设置所有的URL的编码方式,修改如下图所示:

  ? 当然,对于Url中的中文参数的乱码问题(tomcat7及以前版本),推荐使用在后端先使用ISO-8859-1编码,后使用UTF-8解码,即方式一,这样可以使我们的服务不依赖于服务器的配置。

  ? 对于中文乱码问题,其本质上还是编码和解码方式的不同,对于一些常见的编码方式,我们也需要做到熟悉了解。本文最后也介绍了两种解决问题的方式,也希望能解决你的问题。

  ? 又到了分隔线以下,本文到此就结束了,本文内容全部都是由博主自己进行整理并结合自身的理解进行总结,如果有什么错误,还请批评指正。

  ? Java web这一专栏会是一个系列博客,喜欢的话可以持续关注,如果本文对你有所帮助,还请还请点赞、评论加关注。

  ? 有任何疑问,可以评论区留言。