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

来源:互联网 发布:免费人事考勤软件 编辑:程序博客网 时间:2024/06/03 20:59

问题描述:

在已经在应用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