采用DoGet方式提交中文,乱码产生原因分析及解决办法
前段时间某功能在测试机器上出现乱码,情况如下:
怀疑是两台机器(开发人员测试机器,测试人员测试机器)环境不同:1. 先从tomcat查起,在他们各自的tomcat的配置文件server.xml中的Connector标签,有句指定URL编码的配置:URIEncoding="UTF-8" ,开发测试机器上没有配置(默认是IDO-8859-1),测试人员测试机器上配置为GBK,两个配置不同,改成一致(默认),再验证,还是存在乱码;2. 怀疑是系统字符集的问题,用locale命令和查看/etc/sysconfig/i18n 文件查看两台机器的字符集,查看后发现两台机器系统字符集一致,都为UTF-83. 怀疑是apache上有不同的设置,再到apache的httpd.conf上查看,两天的设置基本一致,没有对编码有特殊的设置.4. 怀疑是JVM运行参数的原因.java有一个运行时参数叫做:file.edcoding.这个编码是保存java文件的编码字符集,在调用javac.exe时,JDK用file.edcoding将.java文件读进来,转化为UNICODE放到内存中,所以,这个参数对乱码不会产生影响.从以上可以看出,常规的排查手段已经不能找到原因,所以,从HTTP通信开始下手,从请求发起开始一步步排查,首先,在本地,用到了3个工具,分别是:1. httpFox , Firefox上的一个插件,用来查看所有发起的http请求,内容非常详细.2. membrane-monitor 也是查看http通信的客户端,不依赖浏览器.3. Wireshark 同样是http的抓包工具,他不仅仅可以自己通过各种表达式抓取特定http包,还可以解析tcpdump(后面会说到)抓取的信息(好像tcpdump抓取的是16进制的数据)这次排查三种工具都用到,最简单的是httpFox 使用简单,该有的功能都有,其次是Wireshark,还有很多功能没用到,感觉很强大,而且关键是和浏览器无关,是个很好的分析工具.排查在两个浏览器中进行,IE9和Firefox17,在Firefox下可以看到用DoGET的方式带中文参数请求:
Wireshark 抓取到的信息如下,是UTF-8编码的信息,这步是浏览器自己做的:
在IE9下可以看到用DoGET的方式带中文参数请求:
Wireshark 抓取到的信息如下,是UTF-8编码的信息,这步是浏览器自己做的:
从这里可以看到两个浏览发送中文参数请求的编码方式是不同的.请注意IE里面的高级设置中有这么一个选项:经过试验这的URF8编码,是对URL中的中文例如:www.baidu.com/中文/index.html 中的中文二字进行编码
发送请求后用Wireshark 可以看到,如下图,编码后的部分URL
为了验证,我在服务器上(开发人员测试机器)上又装上了服务器端的http抓包工具,tcpdump,安装过程如下:1、打开网址:www.tcpdump.org/ 下载 libpcap-1.0.0.tar.gz (595.0KB) 软件包,通过命令 tar zxvf libpcap-1.0.0.tar.gz 解压文件,并将其放入自定义的安装目录。2、打开网址:www.tcpdump.org/ 下载tcpdump-4.3.0.tar.gz (867.0KB) 软件包,通过命令 tar zxvf tcpdump-4.3.0.tar.gz 解压文件,并将其放入自定义的安装目录。3.一次到解压目录下:./configure
make
make install即可安装.接着使用命令,将抓取到的信息放到write.log中,tcpdump -X -s 0 -w write.log host xxx.xxx.xxx.xxx and port 80说明下参数:-x 以16 进制数形式显示每一个报文
-s 重定义截取报文大小,默认为96(或68),如果定义为0,则表示获取完整报文
-w 将抓取到的报文放到文件中
host 指定抓取报文的目的地址
port 指定报文目的端口,因为该机器上是apache转发,填apache的端口就可以.
在服务端执行命令后用IE,Firefox下发送请求,将抓取到的文件放到Wireshark中解析,可以看到:
Firefox发送请求时服务端截取的文件:
IE9发送请求时服务端截取的文件:
可以看到和浏览器提交的编码是一致的,所以,可以推断,在浏览器端是编码传输的,并且没有产生所谓的乱码.然后,我在服务端开启远程debug,可以看到在调用以下方法的时候产生了乱码:
但是仔细查看,发现request对象中有个specialAttribute属性,里面以键值对的方式存放了keyword参数,这里的keyword是上图中浏览器编码后的值,所以,在这里是没有乱码的。为什么在调用request.getParameterMap()方法后会产生乱码呢?其实原因和tomcat有关系,在我们调用getParameterMap方法时,request对象会去找WEB容器中的URL编码去解码URL,在Tomcat中指的是在server.xml的以下配置中配置的编码
而开发人员测试机器上没有改配置,即默认使用ISO-8859-1去解码,测试人员测试机器上配置为GBK,即用GBK去解码URL,如果浏览器的编码和tomcat配置文件中配置的编码不一致,就会产生乱码 ,
为了证明我的猜想,我简单加密解密了一段中文,运行结果如下:
这里与我在debug过程中看到的乱码是一致,从而得出结论,乱码的根音来自于tomcat配置文件中设置的URLEncoding参数。
最后,再次总结下:
1. 采用DoGet方式传值,浏览器会帮我们编码,但是各个浏览器的编码方式不一致。
2. 传输过程中,编码后的值不会再被编码。
3. 通过Request对象取参数值时,Request对象会去Web容器中获取URL的编码方式,并用同样的编码区解码URL,如果浏览器的编码和Web容器中的编码不一致,就会产生乱码。
4. 解决方法,在浏览器提交请求前,将中文参数编码两次,浏览器不会再对其进行编码,传到服务端后解码一次即可。
为什么客户端编码两次,服务端解码一次?请看下图:
先声明一个被两次编码以后的字符串,模拟我在浏览器端手动编码的结果,
然后用三种方法对该字符串解码,为什么用三种? 因为这次解码是在调用request.getParameter时
request对象的解码服务端tomcat容器的URLEcoding可能是三种中的一种,可以看到无论是
什么编码方式的解码结果都是一样的,因为这里的配置可能是不一样的,所以要考虑到各种编码方式的可能,这个时候,我们再用代码手动解码一次,就可还原回中文了!
乱码问题就这么解决了,虽然需要手动的解码一次,不过我觉得这个值得,因为乱码后的情况奇奇怪怪,
若觉得每次接么复杂,只需在拦截器端都统一解码就可以,以后不用再担心这个问题.
采用DoGet方式提交中文,乱码产生原因分析及解决办法的更多相关文章
- Code:Blocks 中文乱码问题原因分析和解决方法
下面说说修改的地方. 1.修改源文件保存编码在:settings->Editor->gernal settings 看到右边的Encoding group Box了吗?如下图所示: Use ...
- JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...
- get方式提交中文乱码解决
get方式提交中文时会乱码,过滤器只过滤post请求,此时可修改tomcat配置文件server.xml,为Connector添加属性URIEncoding="utf-8". ec ...
- c# 关于抓取网页源码后中文显示乱码的原因分析和解决方法
原因分析:首先,目前大多数网站为了提升网页浏览传输速率都会对网站内容在传输前进行压缩,最常用的是GZIP压缩解压解压算法,也是支持最广的一种. 因为网站传输时采用的是GZIP压缩传输,如果我们接受we ...
- IDEA2018.3.5Tomcat output 中文乱码 修改配置文件生效的解决办法
首先,我也是尝试别人介绍的方法: IDEA Windows 环境 console 乱码问题 - intellij idea 15 控制台输出中文乱码问题解决办法 - liuhai的博客 - CSDN博 ...
- 服务器CPU使用率高的原因分析与解决办法
我们的服务器在使用操作系统的时候,用着用着系统就变慢了,打开“ 任务管理器 ”一看,才发现CPU使用率达到80%以上.这是怎么回事情呢?遇到病毒了吗?硬件有问题?还是系统设置有问题呢?在本文中将从硬件 ...
- Nested Loops join时显示no join predicate原因分析以及解决办法
本文出处:http://www.cnblogs.com/wy123/p/6238844.html 最近遇到一个存储过程在某些特殊的情况下,效率极其低效, 至于底下到什么程度我现在都没有一个确切的数据, ...
- Cocos2D v3.4.9粒子效果不能显示的原因分析及解决办法
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在游戏App中为了衬托气氛我们往往使用一些特殊的图形效果,粒子 ...
- ORACLE 查询不走索引的原因分析,解决办法通过强制索引或动态执行SQL语句提高查询速度
(一)索引失效的原因分析: <>或者单独的>,<,(有时会用到,有时不会) 有时间范围查询:oracle 时间条件值范围越大就不走索引 like "%_" ...
随机推荐
- iOS开发:iPhone6、6 plus适配
本文转载至 http://jingyan.baidu.com/article/8cdccae97a5c2b315413cda9.html 1 2 3 4 5 6 7 分步阅读 随着苹果公司持续推出新产 ...
- NATS源代码之logger目录
nats的logger目录文件如下 log.go syslog.go syslog_windows.go 基于golang语言的logger包实现日志功能. Golang的log包短小精悍,可以非常轻 ...
- NATS源代码分析之auth目录
NATS是一个轻量的消息发布-订阅系统.NATS的核心是Event machine. 项目Server端源代码地址: github.com/nats-io/gnatsd 在auth目录中, multi ...
- Android UI开发第三十六篇——使用Volley加载图片列表
Android开发者可能会使用Universal Image Loader或者Square`s newer Picasso这些第三方的库去处理图片的加载,那么Volley是怎么加载图片列表的呢,这一篇 ...
- cxGrid 使用指南 1
1:cxgrid是应该数据关联的控件,类似dbgrid.2:一般用来查阅表信息,如果要修改的话,直接在上面编辑或添加 非常不方便通常要放几个EDit来对选中的记录进行编辑或添加记录. 因为表一般都有主 ...
- Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded.
EF6进行Insert操作的时候提示错误 Store update, insert, or delete statement affected an unexpected number of rows ...
- 【转】 JS实现HTML标签转义及反转义
原文地址:http://blog.600km.xyz/2015/12/15/js-encode-html-tags/ 简单说一下业务场景,前台用户通过input输入内容,在离开焦点时,将内容在div中 ...
- 关于jQuery中nth-child和nth-of-type的详解
首先贴出来HTML的代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- 面向对象 - 封装/property - 总结
面向对象 - 封装: 封装:在类定义阶段,以__开头的属性名发生了变形 eg: __x --> _A__x / __foo --> _A__foo 1.特点: 1.在类外部无法直接访问 _ ...
- django_视图层/2.0路由层/虚拟环境











