1. 程式人生 > >字符集編碼問題(get/post請求,tomcat有不同的處理)

字符集編碼問題(get/post請求,tomcat有不同的處理)

今天遇到一個亂碼問題,本來專案使用了spring的字符集過濾器org.springframework.web.filter.CharacterEncodingFilter配置,如:

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>

encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>

<url-pattern>/*</url-pattern>
</filter-mapping>

可是發現配置的過濾器只對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

protectedvoid doFilterInternal(
HttpServletRequest request,HttpServletResponse response,FilterChain filterChain)
throwsServletException,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 <code>String</code> 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
*/
publicvoid setCharacterEncoding(String env)throwsUnsupportedEncodingException;

可以看到,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"/