2009年11月28日星期六

[原创]Java Web开发参数传输的编码心得

今天做了个测试:

表单的Get或Post方式、AJAX的Get或POST参数传值的情况。使用英文时没什么问题,但是当使用中文时就会出现不同情况。

在此做一个完全的测试。

1. 测试环境一

测试字符为“中文”,“中文”被UTF-8编码一次后为“%E4%B8%AD%E6%96%87”,两次为“%25E4%25B8%25AD%25E6%2596%2587”。
客户端Html编码为UTF-8,服务器端setCharaterEncoding("utf-8");并且不设置server.xml中connector元素的URIEncoding属性。
测试浏览器为Firefox 3.5 和IE 8.服务器为Tomcat 6.
客户端提交时使用的jquery的get和post方法提交的参数。

表单Get方式
                                                            服务器端不解码               服务器端UTF-8解码一次             服务器端UTF-8解码两次
客户端不加密                                              乱码                                 乱码                                       乱码

表单Post方式
                                                            服务器端不解码              服务器端UTF-8解码一次             服务器端UTF-8解码两次
客户端不加密                                              中文                                 中文                                       中文

AJAX的Get方式
                                                            服务器端不解码              服务器端UTF-8解码一次             服务器端UTF-8解码两次
客户端不加密                                              乱码                                 乱码                                       乱码
客户端encodeURIComponent加密一次   编码一次后结果                     中文                                       中文
客户端encodeURIComponent加密两次   编码两次后结果                    编码一次后结果                        中文

AJAX的Post方式
                                                            服务器端不解码              服务器端UTF-8解码一次             服务器端UTF-8解码两次
客户端不加密                                             中文                                    中文                                     中文
客户端encodeURIComponent加密一次  编码一次后结果                        中文                                      中文
客户端encodeURIComponent加密两次  编码两次后结果                    编码一次后结果                          中文

2. 测试环境二

测试字符为“中文”,“中文”被UTF-8编码一次后为“%E4%B8%AD%E6%96%87”,两次为“%25E4%25B8%25AD%25E6%2596%2587”。
客户端Html编码为UTF-8,服务器端不设置setCharaterEncoding("utf-8");并且不设置server.xml中connector元素的URIEncoding属性。
测试浏览器为Firefox 3.5 和IE 8.服务器为Tomcat 6.
客户端提交时使用的jquery的get和post方法提交的参数。

表单Get方式
                                                            服务器端不解码               服务器端UTF-8解码一次             服务器端UTF-8解码两次
客 户端不加密                                              乱码                                 乱码                                       乱码

表单Post方式
                                                            服务器端不解码              服务器端UTF-8解码一次             服务器端UTF-8解码两次
客户端不加密                                               乱码                                 乱码                                       乱码

AJAX的Get方式
                                                            服务器端不解码              服务器端UTF-8解码一次             服务器端UTF-8解码两次
客户端不加密                                              乱码                                 乱码                                       乱码
客户端encodeURIComponent加密一次   编码一次后结果                     中文                                       中文
客户端encodeURIComponent加密两次   编码两次后结果                    编码一次后结果                        中文

AJAX的Post方式
                                                            服务器端不解码              服务器端UTF-8解码一次             服务器端UTF-8解码两次
客户端不加密                                              乱码                                  乱码                                       乱码
客户端encodeURIComponent加密一次  编码一次后结果                        中文                                    中文
客户端encodeURIComponent加密两次  编码两次后结果                    编码一次后结果                        中文

3. 总结

  • 对比两次实验,setCharaterEncoding("utf-8");只有在表单的Post方式和AJAX的post方式时会起作用。post方式会对参数进行utf-8编码(取决于html的编码),而服务器端得默认解码是iso-8859-1,不设置编码的类型所以会产生乱码。
  • Get方式时,始终使用默认的编码类型“iso-8895-1”进行解码,除非设置server.xml的配置文件。所以也可以在客户端不编码的情况下,在服务器端用iso-8859-1编码,再用utf-8解码。(如:new String(old.getBytes("iso-8859-1"),"utf-8"));)。之所以要用utf-8编码是为了保持一致性,.java文件都是utf-8编码存储的。
  • 客户端在参数的传输时,都是先根据网页的编码,对参数编码,此处的情况就是utf-8。
  • 中文时,用utf-8编码,再用iso-8859-1解码就会出现乱码,但是英文则不会。因为UTF-8和iso-8859-1对非中文字符的编码是一样的。
  • 为了同时照顾到get和post的两种情况,以及表单提交的情况。
    • 首先编码需一致采用utf-8(自定),使用setCharaterEncoding("utf-8");
    • 表单方式提交数据时不使用get,既不安全又有乱码问题。实在需要就是用new String(old.getBytes("iso-8859-1"),"utf-8"));的方法。
    • AJAX的get方式时,可以在客户端编码一次(或两次),在服务器端对应的解码一次(两次)。
4. 疑问

  • 在客户端进行一次(两次)编码,在服务器端手动配置了一次(两次)解码。但是服务器默认的getParameter也会进行解码!那不就多解码了一次?
  • 原因是这里使用了jquery,它的ajax方法会自动对参数进行编码
  •         function add( key, value ){
                s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
            };
  •  如果您是手动添加参数到url上的,那么客户端必须还要encodeURIComponent(value)一次。

没有评论: