亂碼原因:
1、瀏覽器頁面數據傳遞到服務器時亂碼,示意為:
頁面(字符)------->自動轉換為字節------->服務器(將字節轉化成字符,否則亂碼)
2、服務器傳遞數據到頁面時亂碼,示意為:
服務器(字符,需要設置返回數據的中文編碼,否則亂碼)------->自動轉換為字節------->頁面(將字節按照頁面指定的編碼格式轉化成字符)
詳解如下:
1、瀏覽器頁面數據傳遞到服務器時亂碼
瀏覽器頁面解讀頁面的編碼格式可以在頁面的頭信息中指定,頁面上的輸入的字符則也是按照指定的編碼格式存儲,傳遞參數的時候會將字符轉化成字節,在后台就收參數的時候需要將接收到的字節轉化成字符才能操作,但是轉化是默認按照ISO-8859-1的編碼方式轉化的,故會出現亂碼問題.
get請求方式解決:
1、 String userName=new String(request.getParameter("username").getBytes("iso-8859-1 "),"utf-8");
說明:此方法表示在接受參數后重新對參數編碼,故對於get方式要手動對參數逐個解碼,此過程可以在過濾器中來對參數編碼
2、修改Tomcat的配置,加上URIEncoding="UTF-8" :<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
注:這種方式缺點顯而易見,換了服務器就要更改,有時候忘記也是很常見的事情,同時這個設置更改了tomcat下所有應用的編碼格式嗎,不夠靈活
post請求方式解決:
1、request.setCharacterEncoding(“utf-8”)
說明:此方法是在接收參數前指定接收數據的編碼格式。
注意:該方法只對post請求中的實體內容有效,對get請求無效,並且轉碼的話前提是頁面指定的編碼格式也要是utf-8,轉碼是按照頁面指定的編碼格式轉換
2、服務器傳遞數據到頁面時亂碼
在服務器向瀏覽器發送數據時會將字符轉化成字節流輸送,但是默認的轉化方式還是ISO-8859-1,故要指定返回數據的編碼格式。
1、設置響應返回數據格式為:reponse.setCharacterEncoding(“utf-8”);reponse.setContentType("text/html"),合並寫為:response.setContentType(“text/html” ;charset=utf-8)
注:
此方法針對字符流返回數據,因為字符流會按照指定的編碼格式查詢碼表編碼,但是此方法對於字節流無效,因為字節流不會去查編碼表,返回的數據中如果有中文的話則中文的編碼格式就是中文字符默認的編碼GBK,可以通過如“hello”.getBytes(“utf-8”)指定字節流的編碼格式;
瀏覽器接收到數據后按照瀏覽器頁面設置的編碼格式來解碼,頁面設置的編碼格式和后台接受轉碼的編碼格式都要一致才行;
在springMVC中可以設置如下:
<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>
CharacterEncodingFilter源碼為:
public class CharacterEncodingFilter extends OncePerRequestFilter { private String encoding; private boolean forceEncoding = false; public void setEncoding(String encoding) { this.encoding = encoding; } public void setForceEncoding(boolean forceEncoding) { this.forceEncoding = forceEncoding; } @Override 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); } }
當Servlet容器啟動的時候,會讀取web.xml中對於過濾器的配置信息, 讀取到<init-param>中的子標簽<param-name>encoding和forceEncoding所對應的<param-value>的值,再通過調用該類setEncoding(String encoding)和setForceEncoding(boolean forceEncoding) 將值分別注入到encoding和forceEncoding 中。
forceEncoding:字面意思是強制字符集,但你大可不必按字面意思理解,因為這個參數的值只不過是指定response的字符集是否也設置成encoding所指定的字符集,所以你可以選擇設置為true或false,默認值為false。
當值為true時,相當於
request.setCharacterEncoding(this.encoding);
response.setCharacterEncoding(this.encoding);
當值為false時,相當於:
request.setCharacterEncoding(this.encoding);
故如果在web.xml中設置了此編碼格式就可以不用再代碼中再寫這兩句設置編碼了
