`
jameswxx
  • 浏览: 776420 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

tomcat接收多字节参数为null问题分析

阅读更多

前段时间,在项目中遇到一个很奇怪的问题,服务器端接收中文参数为null,接收单字节字符能正常获取。一开始我以为是项目中某个过滤器做了一些多字节字符过滤,对系统接收参数的环节debug跟踪了好多遍,没发现有过滤多字节参数的地方。

我以前碰到过很多编码问题或者中文等多字节乱码问题,但是服务器得不到参数还是头一次情况,以前是不管编码怎样转换,总还有点东西吧,不至于为null,但是这个所谓的经验误导了我。跟踪服务端没有头绪,于是,我分析客户端提交请求的环节。客户端用ajax提交数据,提交前,UED同事对数据用jsescape函数encode了。

jsescape函数会将多字节数据转换为unicode格式,比如“阿里”会转换成” %u963F%u91CC”。转换就转换了吧,为什么服务端会认为它是null呢?服务器用的jboss,于是我就去查tomcat的源代码,发现tomcat在解析客户端提交的参数时,如果某个参数的值里有%,那么它会跳过两个字符往后寻找匹配的%。如果找不到就会抛出异常,并且该参数被忽略掉,通过request.getParameter得到的就是nullTomcat接收请求后,会解析请求里的参数,具体类是org.apache.tomcat.util.http. Parameters,里面有一个方法public void processParameters( byte bytes[], int start, int len, String enc )。这个方法有这么一部分

           try {

                addParam( urlDecode(tmpName, enc), urlDecode(tmpValue, enc) );

            } catch (IOException e) {

//此处省略异常处理部分

}

urlDecode函数调用了org.apache.tomcat.util.buf. UDecoderpublic void convert( ByteChunk mb, boolean query )函数。遇到参数值有%时,有这么一段代码:

                // read next 2 digits

                if( j+2 >= end ) {

                    throw new CharConversionException("EOF");

                }

                byte b1= buff[j+1];

                byte b2=buff[j+2];

                if( !isHexDigit( b1 ) || ! isHexDigit(b2 ))

                    throw new CharConversionException( "isHexDigit");

                j+=2;

                int res=x2c( b1, b2 );

它认为如果一个参数值含有%,那么从这个%开始,后面应该是两个数字,%aa%bb%%cc%,否则就会抛出异常,忽略此参数。

但是看看jsescape函数encode出来的值,以“阿里”为例,escape值是” %u963F%u91CC”encodeURI的值是%E9%98%BF%E9%87%8C。显然escape的值是不合法的,服务器会丢弃这个参数,escape会将数据编码成unicode码,encodeURI将数据编码成utf-8编码,unicode码和utf-8编码存在着一个对应关系,并且utf-8编码是unicode的子集,是可变的多字节编码,服务器收到%E9%98%BF%E9%87%8C,会将它转成unicode码,然后从unicode码转成对应的编码,如果服务器没有设置编码则默认用ISO-8859-1客户端数据编码的函数有escape,encodeURI,encodeUriComponent。这三个函数是有区别的,最后的解决是如此简单,在ajax提交时,将escape换成encodeURI就好了。

分享到:
评论
3 楼 w0017 2011-08-30  
其实这还是tomcat处理的问题。
2 楼 jameswxx 2011-01-06  
cues 写道
ajax提交我前端一般没做编码处理,直接提交过去,在后台用如下方式处理:

GET--
msg = new String(msg.getBytes("iso-8859-1"));

POST--
msg = new String(msg.getBytes("iso-8859-1"), "utf-8");


嘿嘿,你可能没明白我说的这个场景。
你写的
msg = new String(msg.getBytes("iso-8859-1"));
这种转码的很常见,但是,这个msg是通过request.getParameter得到的对吧?我现在的问题是通过request.getParameter根本连参数都拿不到,拿到的是null,而客户端又传了这个参数。
1 楼 cues 2010-12-27  
ajax提交我前端一般没做编码处理,直接提交过去,在后台用如下方式处理:

GET--
msg = new String(msg.getBytes("iso-8859-1"));

POST--
msg = new String(msg.getBytes("iso-8859-1"), "utf-8");

相关推荐

    详解tomcat 解决 POST请求传参数过长受限制的问题

    这里的`maxPostSize="10240"`表示Tomcat允许的最大POST数据量为10240字节(即10KB)。如果需要解除这个限制,可以将`maxPostSize`的值设置为0,表示不限制POST请求的大小: ```xml ,text/xml" maxPostSize="0"/> ``...

    630.628.JAVA基础教程_IO流与网络编程-URL网络编程实现Tomcat服务端数(630).rar

    Servlet通过`HttpServletRequest`对象接收请求参数,通过`HttpServletResponse`对象返回响应数据。 以下是一个简单的示例,演示如何使用Java的IO流和URL网络编程发送GET请求到Tomcat服务器: ```java import java....

    详解Tomcat7中WebSocket初探

    - `bufferedAmount`:表示尚未发送到网络的字节数。 - `onopen`:连接成功时触发的事件处理函数。 - `onerror`:发生错误时触发的事件处理函数。 - `onclose`:连接关闭时触发的事件处理函数。 - `onmessage`:接收...

    java编程出现中文乱码解决方法一

    在本例中,提供了一个简单的静态方法`Chinese`,该方法接收一个字符串参数`value`,并将其从ISO-8859-1编码转换为UTF-8编码。 ##### 方法实现 ```java public static String Chinese(String value){ try { if ...

    Ajax传参是乱码解决方案

    在Ajax请求中,前端浏览器与服务器之间的数据交换可能会经过多次编码转换,如果这些环节中的任何一处编码设置不正确,都可能导致乱码问题的发生。 1. **前端编码**:前端在发送请求时会将数据进行编码。 2. **传输...

    java 聊天室之 传送图片文字等功能的实现

    Java提供了Serializable接口,可以将对象转换为字节流,然后在另一端反序列化回原来的对象。 4. **IO流**:在Java中,输入输出流(InputStream和OutputStream)用于读写数据。在聊天室中,我们可能需要使用...

    java面试题

    - **GET请求乱码**:可通过修改Tomcat配置文件或手动对参数进行编码转换来解决。 修改Tomcat配置文件: ```xml ``` 或者对GET请求参数进行编码转换: ```java String userName = new String(request...

    java学习笔记整理

    - **HashMap**: 基于哈希表实现的键值对存储容器,允许一个null键和多个null值。 - **遍历方式**: 使用`iterator`遍历keySet或entrySet。 ##### 4.4 Collection三种遍历方式总结 - **for循环**: 通用,适用于所有...

    ClassLoader实例

    Java 类加载机制是Java虚拟机(JVM)的关键特性之一,它负责将类的字节码文件加载到内存中,并转换为对应的类对象。在Java中,类加载器(ClassLoader)扮演着至关重要的角色,它们负责查找和加载类。本文将深入探讨...

    java面试必会200题.docx

    ### Java面试必会知识点解析 #### 一、基本概念 1. **操作系统中heap和stack的... - **九种基本数据类型的大小**:byte(1字节)、short(2字节)、int(4字节)、long(8字节)、float(4字节)、double(8字节)、char(2字节)、...

    java面试知识

    - **方法重载**:同一类中方法名相同但参数列表不同的多个方法。 ##### StringBuffer、StringBuilder与String的区别 - **String**:不可变字符串,适用于频繁读取而很少修改的情况。 - **StringBuilder**:可变...

    自整理Java关于基础和框架的面试题

    - **HashMap**:非线程安全,允许一个null键和多个null值。 ##### Forword(请求转发)与Redirect(重定向) - **请求转发**:服务器内部进行转发,客户端地址栏不变。 - **重定向**:服务器告诉客户端去另一个地址获取...

Global site tag (gtag.js) - Google Analytics