何爲響應中的亂碼?把頁面中的「username」改爲「用戶名」你就知道了。html
所謂響應中的亂碼,就是顯示頁面上的亂碼,由於頁面數據是從服務器一端放入響應(response)中,而後發送給瀏覽器,若是響應中的數據沒法被正常解析,就會出現亂碼問題。java
爲何英文就沒有問題呢?由於在iso-8859-1,gb2312, utf-8以及任意一種編碼格式下,英文編碼格式都是同樣的,每一個字符佔8位,而中文就麻煩了,在gb2312下一個中文佔16位,兩字節,而在utf-8下一個中文要佔24位,三字節。瀏覽器在不知道肯定編碼方式的狀況下,就會把這些字符從中間截斷,再顯示的時候就亂掉了。因此,想要解決亂碼問題,就是要告訴瀏覽器咱們到底使用了什麼樣的編碼方式。web
爲了得到正常顯示的中文,須要注意如下幾步:spring
由於服務器要先從本地讀取jsp文件,而後通過處理後寫入響應,因此咱們首先要知道的就是jsp文件的編碼格式。從問題的源頭着手解決。數組
在我們用的windowxp下,文件默認的編碼格式是gb2312。瀏覽器
咱們要在http的響應(response)中添加編碼信息,使用以下方式:服務器
<%@ page contentType="text/html; charset=gb2312"%>
這段要放在jsp頁面的第一行,用來指定響應的類型和編碼格式,contentType爲text/html就是html內容,charset表示編碼爲gb2312。這樣瀏覽器就能夠從響應中得到編碼格式了。app
這種<%@ %>的形式叫作jsp指令(directive),如今接觸到的是page指令。框架
<head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>title</title> </head>
meta部分用來指定當前html的編碼格式,注意這一段要放在head標籤中,而且放到head標籤的最前面,若是不是最前面ie下可能會出現問題,尤爲是在title中有中文的狀況下。jsp
完成了以上三段檢驗,咱們才能保證輸出的jsp頁面會正常顯示中文。
2. POST亂碼
先把form里加上method="POST",讓form提交的時候使用POST方式。
發送請求的時候,使用的編碼是iso-8859-1,意味着只有英文是有效字符,這個限制是由於當初指定http標準的成員都來自英語國家,因此若是使用默認的方式從請求獲取數據,中文必定會所有變成亂碼。
若是不信,你能夠在剛纔的例子裏輸入中文,而後提交:
提交結果就會變成這樣:
<% request.setCharacterEncoding("gb2312"); %>
因而,那些亂碼都正常了:
GET狀況下,使用URLEncode()的確能夠解決亂碼問題,該部分須要補充。
直接點擊超連接,form的默認提交方式都是GET。POST方式下的解決方式還算簡單,由於POST方式下提交的數據都是以二進制的方式附加在http請求的body部分發送,只須要在後臺指定編碼格式就足矣解決。GET方式下會將參數直接附加到url後面,這部分參數沒法使用request.setCharacterEncoding()處理,結果就是get形式的全部中文都變成了亂碼。
這時再也沒有簡便方法了,只能對這些中文一個一個進行轉換,使用new String(bytes, "gb2312")進行轉碼。
如咱們所見,先從request中得到參數,接着把字符串按照iso-8859-1編碼打散成byte數組,而後用gb2312編碼組合成新字符串,最後打印出來就是正常的中文了。
寫在一塊兒就變成了:
<%=new String(new String(request.getParameter("username").getBytes("iso-8859-1"), "gb2312")%>
這樣作的缺點,是從請求中取得的全部中文都須要轉碼,很是煩瑣。
這樣解決中文亂碼問題實在太繁瑣,作通常的測試例子還能夠,作大型項目時就會很麻煩,因此通常用過濾器解決。在spring框架下。例子1
<!-- spring的字符過濾器 ,不是必須的,能夠其餘方式解決 --> <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>
例子2 咱們能夠自定義一個過濾器來解決中文亂碼問題
1 import java.io.IOException; 2 import javax.servlet.Filter; 3 import javax.servlet.FilterChain; 4 import javax.servlet.FilterConfig; 5 import javax.servlet.ServletException; 6 import javax.servlet.ServletRequest; 7 import javax.servlet.ServletResponse; 8 9 public class EncodingFilter implements Filter { 10 11 public void init(FilterConfig config) throws ServletException {} 12 13 public void destroy() {} 14 15 public void doFilter(ServletRequest request, 16 ServletResponse response, 17 FilterChain chain) 18 throws IOException, ServletException { 19 20 request.setCharacterEncoding("gb2312"); 21 chain.doFilter(request, response); 22 } 23 24 }
在此EncodingFilter實現了Filter接口,Filter接口中定義的三個方法都要在EncodingFilter中實現,其中doFilter()的代碼實現主要的功能:爲請求設置gb2312編碼並執行chain.doFilter()繼續下面的操做。
與servlet類似,爲了讓filter發揮做用還須要在web.xml進行配置。
<filter> <filter-name>EncodingFilter</filter-name> <filter-class>anni.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
filter標籤部分定義使用的過濾器,filter-mapping標籤告訴服務器把哪些請求交給過濾器處理。這裏的/*表示全部請求,/表示根路徑,*(星號)表明全部請求,加在一塊兒就變成了根路徑下的全部請求。
這樣,全部的請求都會先被EncodingFilter攔截,並在請求裏設置上指定的gb2312編碼。