
环境:tomcat6.0.23 jdk 1.6
相关参考:
http://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html
http://wiki.apache.org/tomcat/FAQ/CharacterEncoding
影响编码的环境:server.xml中Connector节点的URIEncoding与useBodyEncodingForURI参数,http请求头content-type charset=xxx中的charset值,servlet request的setCharacterEncoding参数值以及setCharacterEncoding的调用时机这五个环境参数;
请求参数解析的时间(tomcat环境):第一次请求request参数时,且每次用户请求中有且只有一次参数解析。换而言之,参数的初始化是Lazy的,且会一次性初始化所有请求中包含的参数字段与对应的取值;
get请求测试用例 A:
http://localhost:8080/test?addr=上海
请求头:content-type charset=utf-8;
server.xml配置<Connector URIEncoding="utf-8" useBodyEncodingForURI="true" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
服务端收到请求后的处理方式:servlet中未调用request.setCharacterEncoding("utf-8")
结果:getParameter("addr") 解码正确
get请求测试用例 B:
http://localhost:8080/test?addr=上海
请求头:(无 content-type charset=utf-8;)
server.xml配置<Connector URIEncoding="utf-8" useBodyEncodingForURI="true" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
服务端收到请求后的处理方式:同A
结果:getParameter("addr") 乱码
get请求测试用例 C:
http://localhost:8080/test?addr=上海
请求头:(无 content-type charset=utf-8;)/ content-type charset=iso-8859-1;
server.xml配置<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
服务端收到请求后的处理方式:同A
结果:getParameter("addr") 解码正确
参数解析过程(待整理):
-> server.xml
Connector -> setURIEncoding
CoyoteAdapter -> server(req: org.apache.coyote.Request, res: org.apache.coyote.Response) ->
req.getParameters():org.apache.tomcat.util.http.Parameters.setQueryStringEncoding(connector.getURIEncoding()) ->
connector.getContainer().getPipeline().getFirst().invoke(request, response) -> doFilter ->
#? org.apache.catalina.connector.Request.setCharacterEncoding() -> org.apache.coyote.Request.setCharacterEncoding()
getParameters ->
enc = org.apache.coyote.Request.getCharacterEncoding() -> org.apache.coyote.Request.charEncoding -if null-> get header content-type charset=???
-if enc != null-> org.apache.tomcat.util.http.Parameters.setEncoding(enc)
--if connector.getUseBodyEncodingForURI() -> org.apache.tomcat.util.http.Parameters.setQueryStringEncoding(enc)
-else org.apache.tomcat.util.http.Parameters.setEncoding("iso-8859-1")
--if connector.getUseBodyEncodingForURI() -> org.apache.tomcat.util.http.Parameters.setQueryStringEncoding("iso-8859-1")
GET decode -> org.apache.tomcat.util.http.Parameters.handleQueryParameters() -> queryStringEncoding decode queryString
POST decode -> org.apache.tomcat.util.http.Parameters.processParameters -> encoding decode data