HttpServletRequest获取中文参数乱码问题

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

1.问题复现

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

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<body><form action="RequestTestServlet" method="post">姓名: <input type="text" name="name" style="width: 150px" />年龄: <input type="text" name="age" style="width: 150px" /><input type="submit" value="提交" /></form>
</body>
</html>

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

protected void doPost(...) throws ...{String name = request.getParameter("name");String age = request.getParameter("age");System.out.println("姓  名: " + name);System.out.println("年  龄: " + age);
}

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

2.中文乱码问题时如何出现的?

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

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

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

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

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

3.问题解决

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

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

protected void doPost(...) throws ...{//设置该request对象中请求体的使用的编码方式request.setCharacterEncoding("utf-8");String name = request.getParameter("name");String age = request.getParameter("age");System.out.println("姓  名: " + name);System.out.println("年  龄: " + age);
}

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

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

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

 //ServletRequest.class/*** Overrides the name of the character encoding used in the body of this* request. This method must be called prior to reading request parameters* or reading input using getReader(). Otherwise, it has no effect.* * @param env      <code>String</code> containing the name of*                 the character encoding.* @throws         UnsupportedEncodingException if this*                 ServletRequest is still in a state where a*                 character encoding may be set, but the specified*                 encoding is invalid*/public void setCharacterEncoding(String env) throws UnsupportedEncodingException;

​ 那我们就来验证下以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中的中文参数乱码问题?主要有两种方式:

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

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

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

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

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

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

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

4.结论

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


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

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

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

HttpServletRequest获取中文参数乱码问题相关推荐

  1. Js的Url中传递中文参数乱码的解决

    一:Js的Url中传递中文参数乱码问题,重点:encodeURI编码,decodeURI解码: 1.传参页面 Javascript代码: 2. 接收参数页面:test02.html 二:如何获取Url ...

  2. JSP中文及传中文参数乱码解决方法小结

    在使用JSP的过程中,最使人头疼的一个问题就是中文乱码问题,以下是我在软件开发中遇到的乱码问题以及解决方法. 1.JSP页面乱码 这种乱码的原因是应为没有在页面里指定使用的字符集编码,解决方法:只要在 ...

  3. php考过来运行后报乱码,PHP接收GET中文参数乱码怎么办

    [摘要] PHP即"超文本预处理器",是一种通用开源脚本语言.PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言.PHP独特的语法混合了C.Java.Perl以及 ...

  4. jquery 乱码 传参_jquery ajax传递中文参数乱码问题及解决方法说明

    jQuery传递中文参数乱码,原因是默认的传递方式没有采用UTF-8,所有我们可以在传递参数的时候对参数进行编码,然后再操作,代码如下,红色的代码为传递的参数,已标注 smsubmitclick = ...

  5. ThinkPHP3.2.3分页中文参数乱码问题及解决

    ThinkPHP3.2.3分页中文参数乱码问题及解决 参考文章: (1)ThinkPHP3.2.3分页中文参数乱码问题及解决 (2)https://www.cnblogs.com/shenxinpet ...

  6. html页面url中文传值乱码,URL传参时,中文参数乱码的解决方法

    URL传参时,中文参数乱码的解决: 今天在工作中遇到了这样的一个问题,在页面之间跳转时,我将中文的参数放入到url中,使用location进行跳转传参,但是发现接收到的参数值是乱码.我的代码是这样写的 ...

  7. java中文 x_java环境url中文参数乱码处理

    在做搜索开发过程中,由于翻页功能需要,要把当前查询的中文条件放在URL中带到服务器进行下一页查询,结果出现乱码情况. 此时情况有如下两种: 1.在输入框输入搜索内容,直接通过from提交,参数值正常读 ...

  8. URL传参时 从URL中获取中文参数的方法

    利用url传参时如果url中的参数是中文时因为编码类型不同在页面中获取会出现乱码 使用此方法能获取url中的参数值 并解决乱码问题 调用时直接 GetUrlByParamName("参数名& ...

  9. hibernate之HQL传中文参数乱码 解决办法

    在spring+hibernate中:Hql中有中文参数(如from test as c where c.name='张三')的话被翻译成sql的时候会出现乱码,解决办法是在application.x ...

  10. 框架页,URL中文参数乱码

    在web.config这样声明编码   <globalization requestEncoding="utf-8"  responseEncoding="utf- ...

最新文章

  1. 微软发布的python教程_微软发布Python 教程《Develop with Python on Windows》
  2. cloud foundry_介绍“又一个” Cloud Foundry Gradle插件
  3. 信息安全工程师笔记-数据库安全
  4. 垂直电商独立站,到底有何优势?
  5. 数据库、SQL脚本、存储过程执行准则(*****)
  6. dell服务器装不了无线网卡,DELL E6420无线网卡装不上去
  7. Failed installing ‘Tomcat8‘ service?
  8. 利用python转载朋友微信表情包
  9. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true
  10. PostgreSQL 磁盘空间的保护伞 PG_repack VS 表膨胀
  11. 生存模型的calibration需要注意的一个问题
  12. Google确认Chrome存在严重漏洞,向20亿用户发出警告:你们需立即更新浏览器
  13. 苹果平板电脑成长历程
  14. 【现代简约风格装修案例】诠释不一样的简单 !
  15. (学习笔记) SPI通信协议
  16. 蓝牙的Baseband说明
  17. 【Microsoft Azure 的1024种玩法】四十二. 通过Windows Admin Center快速创建Azure Virtual Machines
  18. linux进程异常退出分析,ECS Linux程序异常退出提示“out of memory”的临时解决办法...
  19. 十个好用的iOS开发辅助工具与资源
  20. 初级程序员软考重点7 软件工程

热门文章

  1. react-hooks/exhaustive-deps警告
  2. 一个非常好用的批量图片压缩工具
  3. WPS Word为PDF签名
  4. 两台android相互ADB实现一台安卓手机给另一台安卓手机ADB
  5. php+mysql+jquery瀑布流
  6. 腾讯云实验室linux基本操作
  7. Python for S60(pys60)介绍
  8. 解决9341系列LCD,使用杜邦线等连接线,造成白屏问题
  9. 快速配置无线模块连入家庭Wifi
  10. 实时工业以太网EtherCAT高速发展背后