今天遇到一个乱码问题,本来项目使用了spring的字符集过滤器org.springframework.web.filter.CharacterEncodingFilter配置,如:
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
forceEncoding
true
CharacterEncodingFilter
/*
可是发现配置的过滤器只对post提交方式有用,get请求不起作用。
总结一下这个问题的原因:
在默认情况下,浏览器发送的HTTP请求采用“ISO-8859-1”字符编码。当HTTP请求以POST方式发出时,请求参数位于请求正文中。
而当HTTP请求以GET方式发出时,请求参数位于请求头的URI中。
而tomcat对post和get采用不同的处理编码机制:
对于get请求,
Tomcat对于GET请求会永远使用iso-8859-1编码。
对于POST请求:
Tomcat使用request.setCharacterEncoding方法所设置的编码来处理,如果未设置,则使用默认的iso-8859-1编码。
看下源码:
org.springframework.web.context.ContextLoaderListener
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding) {
response.setCharacterEncoding(this.encoding);
}
}
filterChain.doFilter(request, response);
}
可以看到这个过滤器调用了request.setCharacterEncoding方法,
看下这个方法的声明:
/**
* Overrides the name of the character encoding used in the body of this
* request. This method must be called prior to reading request parameters
* or reading input using getReader(). Otherwise, it has no effect.
*
* @param env String
containing the name of
* the character encoding.
*
* @throws UnsupportedEncodingException if this ServletRequest is still
* in a state where a character encoding may be set,
* but the specified encoding is invalid
*/
public void setCharacterEncoding(String env) throws UnsupportedEncodingException;
可以看到,request.setCharacterEncoding和org.springframework.web.context.ContextLoaderListener过滤器只对请求体中的内容编码,而请求头不编码,post方式的参数在请求体中,get方式的参数在请求头中。所以org.springframework.web.context.ContextLoaderListener过滤器对get方式无效。
解决的方法有三个:
1. 将GET请求改成POST请求,然后就可以使用request.setCharacterEncoding(“GBK”)方法设置编码,并使用request.getParameter方法直接获得中文请求参数了。
2. 不用改GET请求,在Servlet中使用如下的代码来得到中文请求参数。
String name = new String(request.getParameter(“name”).getBytes(“ISO-8859-1”), “GBK”);
3.为了保证get数据采用UTF8编码,在server.xml中进行了如下设置
<Connector port="8989" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true"
URIEncoding="UTF-8"/