Tomcat 8.0.0响应get请求时中文乱码问题

问题描述:

在已经在应用filter中指定了页面编码为UTF-8的情况下,通过GET方式发送的请求中的中文依然被识别为乱码,而通过POST方式发送的中文识别正常.

原因:

Tomcat在解析两种不同的请求方式传递的参数时处理出现了问题,应该视为一个BUG,Tomcat 8.0.0以后的版本一定程度上修复了此问题.

代码分析:

Tomcat解析前台传递过来的参数时使用的类为org.apache.tomcat.util.http.Parameters,解析Get传参时调用的方法为

/** Process the query string into parameters
       */
 public void handleQueryParameters() {
        if( didQueryParameters ) {
            return;
        }

        didQueryParameters=true;

        if( queryMB==null || queryMB.isNull() ) {
            return;
        }

        if(log.isDebugEnabled()) {
            log.debug("Decoding query " + decodedQuery + " " +
                    queryStringEncoding);
        }

        try {
            decodedQuery.duplicate( queryMB );
        } catch (IOException e) {
            // Can't happen, as decodedQuery can't overflow
            e.printStackTrace();
        }
        processParameters( decodedQuery, queryStringEncoding );
    }

注意标红的一行,此时字符编码方式由Parameters对象的queryStringEncoding属性指定,若此属性为空,则使用默认编码方式iso8859-1.然而此字段无法在编码时手工指定,是在分配request对象时由Tomcat赋值的.

 Request request = (Request) req.getNote(ADAPTER_NOTES);
        Response response = (Response) res.getNote(ADAPTER_NOTES);

        if (request == null) {

            // Create objects
            request = connector.createRequest();
            request.setCoyoteRequest(req);
            response = connector.createResponse();
            response.setCoyoteResponse(res);

            // Link objects
            request.setResponse(response);
            response.setRequest(request);

            // Set as notes
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);

            // Set query string encoding
            req.getParameters().setQueryStringEncoding
                (connector.getURIEncoding());

        }

上面的代码为org.apache.catalina.connector.CoyoteAdapter的一部分,标红的部分指出queryStringEncoding应该由Connector给出,但是在Connector的构造中指明了URIEncoding的值为null(特指在Tomcat 8.0.0-RC1版本中),也就造成了所有的以get方式传递的参数均会以iso8859-1格式解码,导致中文乱码.

POST方式不会出现此问题,因为Post的参数解析函数为

 public void processParameters( byte bytes[], int start, int len ) {
        processParameters(bytes, start, len, getCharset(encoding));
    }

此时编码方式由Parameters对象的encoding属性指定,此属性值获取优先级为 (Request的Content-Type中获取) > (用户代码中指定) > (Tomcat指定) ,只要在解码前手工指定过编码方式,就不会出现乱码问题.

解决方法:

1 升级更新版Tomcat,新版本中通过在Connector构造时设定字符编码的方式绕过了此问题.

        if (!Globals.STRICT_SERVLET_COMPLIANCE) {
            URIEncoding = "UTF-8";
            URIEncodingLower = URIEncoding.toLowerCase(Locale.ENGLISH);
        }

2 在filter中通过反射方式修改request.request.coyoteRequest.parameters.queryStringEncoding的值为需要的值(request.request不是拼写错误,就是request里的request对象).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值