GET请求传参乱码问题补充 | useBodyEncodingForURI 的影响

之前写过一篇关于乱码产生原因及使用Tomcat如何配置解决乱码的文章(后台回复关键字007即可查看),其中对于URIEncoding影响GET请求参数处理相关代码做了说明和解读。

本文,作为上一篇乱码文章关于GET请求参数解析乱码问题的补充

在Tomcat的通道(Connector)配置中,除了URIEncoding之外,还有一个影响编码的参数useBodyEncodingForURI,关于这个参数,官方文档说明如下:

This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This

setting is present for compatibility with Tomcat 4.1.x, where the encoding

specified in the contentType, or explicitly set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.

Notes: 1) This setting is applied only to the query string of a request. Unlike URIEncoding it does not affect the path portion of a request URI. 2) If request character encoding is not known (is not provided by a browser and is not set bySetCharacterEncodingFilter or a similar filter using Request.setCharacterEncoding method), the default encoding is always "ISO-8859-1". The URIEncoding setting has no effect on this default.

其作用大致概括下就是,contentType中指定的编码是否要替换URIEncoding已经设置的值。或者说将Body的编码用于URI的参数解析,这个Body的编码有两方面的来源:

  • request.setCharacterEncoding()

  • request header中设置的contentType中包含的编码

如果从上述两个地方能够获取到charset信息,同时useBodyEncodingForURI参数也设置为true,此时GET请求的参数解析也使用同一个charset。

如果两个地方都拿不到charset,那Body的编码会使用默认值ISO-8859-1,这个一般都能注意到。但这个参数设置为true时,相当于有个隐含的条件,即GET请求的编码也会使用默认编码ISO-8859-1,而无论你之前的URIEncoding设置的是什么编码。

那这种情况下,虽然URIEncoding设置的编码可以正常处理中文,但再配置上了这个开并,却并没有按照其规定设置,就会导致乱码再次产生。而Tomcat8默认已经将URIEncoding设置为UTF-8,如果配置中指定useBodyEncodingForURI这一项,乱码就出现了。

这一配置,默认项为false,

/**
 * URI encoding as body.
 */
protected boolean useBodyEncodingForURI = false;

使用这一配置是否生效的地方,在这里

// getCharacterEncoding() may have been overridden to search for
// hidden form field containing request encoding
String enc = getCharacterEncoding();

boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI();
if (enc != null) {
    parameters.setEncoding(enc);
    if (useBodyEncodingForURI) {
        parameters.setQueryStringEncoding(enc);
    }
} else {
    parameters.setEncoding
        (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
    if (useBodyEncodingForURI) { //这里的配置是比较容易忽略的地方
        parameters.setQueryStringEncoding
            (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); }
}

再看对于enc变量的获取

coyote包中的Request类:
/**
 * Get the character encoding used for this request.
 */
public String getCharacterEncoding() {

    if (charEncoding != null) { //这里的值即是通过request.setCharacterEncoding设置的
        return charEncoding;
    }
    charEncoding = getCharsetFromContentType(getContentType());
    return charEncoding;
}

关于从ContentType中获取charSet的代码的代码此处就不再罗列了。

简要总结如下:

影响URI参数解析编码(GET请求)的地方共有:
1. Connector 的URIEncoding 配置
2.  Connector的useBodyEncodingForURI 配置,此配置为true时则直接使用ContentType的charset或者request.setCharacterEncoding指定的encoding。
注意,request设置的会先被使用。
3. 特别注意,当设置useBodyEncodingForURI为true时,如果getCharacterEncoding为空,即request未设置编码,并且ContentType也未配置charset,则queryString会被设置为ISO-8859-1

由于微信编辑器的设置,当前文章中并不能直接加入已发送文章的超链接,只能每次将相关的文章设置一些关键字。对关联的内容有兴趣目前只能通过关键字查看了。如果哪篇文章对你有一点帮助,帮忙转发,请让更多人看到。和我一起期待早日开通链接功能。

扫描或长按下方二维码,关注我,一起交流!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值