背景
從Tomcat5.x開始,GET,POST方法提交信息,Tomcat采用不同的方式來處理編碼。
對於GET請求,Tomcat不會考慮使用request.setCharacterEncoding("UTF-8")設置的編碼,而會永遠使用ISO-8859-1編碼。
對於POST請求,Tomcat會使用request.setCharacterEncoding("UTF-8")設置的編碼,如果沒有設置,則使用"ISO-8859-1"。
1 get方式,即請求參數的亂碼問題
原因:
Tomcat官方文檔中The HTTP Connector的配置,其中對URIEncoding屬性的描述:
This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
翻譯:如果沒有指定,將使用ISO-8859-1解碼URI。
解決方法,有兩種:
1 根本方法:修改server.xml文件
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8" />
2 局部方法:得到一次參數,解碼,再編碼
String name=request.getParameter(parameter); byte[] arr=name.getBytes("ISO8859-1"); String nameAfterTransfer=new String(arr,"UTF-8");
2 post方式,即請求體的亂碼問題
原因:如果沒有設置Request,則使用"ISO-8859-1"解碼,和你提交頁面的編碼方式無關。
解決方法:
Tomcat官方文檔中Container Provided Filters的配置,系統提供了一些Filter。其中一個是,org.apache.catalina.filters.SetCharacterEncodingFilter,顧名思義,是設置編碼的過濾器。其中有兩個屬性,encoding,要設置編碼的名字,另一個是,ignore,確定是否忽略了由用戶代理指定的任何字符編碼。如果此屬性是true的,則忽略了用戶代
理,即浏覽器提供的任何值。如果false,只有當用戶代理沒有指定一個編碼時,編碼才被設置。默認值是false的。
<filter> <filter-name>SetCharacterEncodingFilter</filter-name> <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>自己設置的編碼</param-value> </init-param> <init-param> <param-name>ignore</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SetCharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
SetCharacterEncodingFilter類的中的實現,就是設置request.setCharacterEncoding(上面配置中的參數);
結論:
我們平時request.setCharacterEncoding("UTF-8")的設置,只是改變請求體的編碼方式。
3 get和post編碼問題一起解決的方式:使用useBodyEncodingForURI屬性。
useBodyEncodingForURI,如果該值是true,將使用請求體的編碼方式編碼URI。
Tomcat官方文檔對useBodyEncodingForURI屬性是這麼解釋的,
如果請求的字符編碼是不知道的(不是由浏覽器提供,不由setcharacterencodingfilter或使用request.setcharacterencoding方法類似的過濾器),默認的編碼是“ISO-8859-1”。而URIEncoding設置對此無影響。
4 您猜測以下結果會亂碼嗎?
在如下html頁面中進行操作,該頁面已經進行了UTF-8編碼,POST提交到後台:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>測試</title> </head> <body> <div> <form action="http://localhost/Web/B" method="post">//B是我使用的Servlet類。 <input type="text" name="name" value="大"/> <input type="submit" value="提交表單"/> </form> </div> </body> </html>
答案是:亂碼,您答對了嗎?
結論:
1 Tomcat不會理會我們所提交頁面的編碼方式,或者說請求中根本不含有編碼方式。
2 如果沒有進行request.setCharacterEncoding("UTF-8")設置或者添加過濾器,Tomcat還是會使用"ISO-8859-1"解碼。
3 所以不論提交前頁面的編碼格式是什麼,我們都要設置自己的編碼方式。
終極解決方案
假設我們要全部使用UTF-8進行解碼,終極解決方案就是,
1 設置server.xml中,useBodyEncodingForURI="true"
2 設置request.setCharacterEncoding("UTF-8");//本質添加過濾器也就是這麼處理的,故沒有說添加過濾器。
就這樣,我們就達到了get與post請求全部UTF-8解碼的效果。
最後,如果裡面有不對的地方,歡迎大家對我的總結進行指正。
欲戴王冠,必承其重。