最近在做个人博客开发,因为打算直接利用中文参数请求后台,所以碰到了一些跟编码有关的问题。
我的请求URL原本为http://localhost:8080/okyoungblog/bloglist?articleType=心得笔记
但是浏览器会自动帮我encode,所以URL被转变成了Http://localhost:8080/okyoungblog/bloglist?articleType=%E5%BF%83%E5%BE%97%E7%AC%94%E8%AE%B0
可以清楚的看到中文参数变成了UTF-8编码的形式(我的网页meta信息里设置了content="text/html;charset=utf-8")
但传到后台就出现了各种编码问题:
分别打出了六条log记录,
1) 第一条输出queryString,发现他跟前台传入的转码后的参数一致;
2)第二条decode queryString后发现乱码;
3)第三条decode queryString with 'utf-8' 发现恢复正常,通过查看 decode源码,发现不指定字符集时,默认使用平台默认编码(windows为gbk);
4)第四条log,说明当前请求参数编码是‘utf-8’;
5)第五条log, 发现通过模型驱动获得到的get参数竟然是乱码,而且还是在请求参数编码是‘utf-8’的情况下(基于第四条)。
前三条log说明了前台传入的url参数是以字符串的形式传入后台,但是不同的decode方式决定能否解码正确。
第五条说明模型驱动获取参数过程中,requestCharaterEncoding并不能决定get参数的编码。
随即做了下面两个实验:
1)
这个实验发现通过添加tomcat connector 配置URIEncoding,可以解决typeParam的解码问题,说明get参数实际上在传到服务器后,经过了tomcat的解码。
通过查询相关资料,得知如果不设置URLEncoding,tomcat默认使用‘iso-8859-1’字符集解析URL,而get参数是URL的一部分,所以将原本UTF-8编码的参数用‘iso-8859-1’来解码,当然会乱码了。
进一步实验:
将tomcat的URIEncoding设置去掉,就用默认‘iso-8859-1’方式解析URL,而通过在代码中添加articleType = new String(articleType.getBytes("ISO-8859-1"),"utf-8");
同样可以解决,参数乱码问题。为什么要添加这句代码呢?
这跟java语言的特性有关,整个参数传递的过程是:
a.当前台传入articleType=%E5%BF%83%E5%BE%97%E7%AC%94%E8%AE%B0这条参数时,tomcat将这条参数存入queryString字段中,
b.但是当使用模型驱动来获取get参数的时候,使用'iso-8859-1'字符集解析get参数,并转化成unicode编码的java 的String对象(java String 内存中的编码方式为Unicode),
c.当调用get("ISO-8859-1")时,又将该参数转换成“ISO-8859-1”字符集解码前的二进制序列,而未经解码的参数实际上是‘utf-8’编码的,所以通过new String (typeParam,"utf-8");就能够使用utf-8字符集解析这段二进制序列,也得到了正确的参数。
(注意:如果直接是中文,用“ISO-8859-1”字符集解码,会导致数据丢失,因为“ISO-8859-1”不支持中文,
对于无法解析的字符,通常会用?代替,所以直接就导致二进制序列发生改变,再转回去也只是将错误的二进制序列转回去,并不能得到未解码前的序列)。