解決jsp中文亂碼問題


1. 先解決響應中的亂碼

何為響應中的亂碼?把頁面中的“username”改成“用戶名”你就知道了。

所謂響應中的亂碼,就是顯示頁面上的亂碼,因為頁面數據是從服務器一端放入響應(response)中,然后發送給瀏覽器,如果響應中的數據無法被正常解析,就會出現亂碼問題。

為什么英文就沒有問題呢?因為在iso-8859-1,gb2312, utf-8以及任意一種編碼格式下,英文編碼格式都是一樣的,每個字符占8位,而中文就麻煩了,在gb2312下一個中文占16位,兩字節,而在utf-8下一個中文要占24位,三字節。瀏覽器在不知道確定編碼方式的情況下,就會把這些字符從中間截斷,再顯示的時候就亂掉了。所以,想要解決亂碼問題,就是要告訴瀏覽器我們到底使用了什么樣的編碼方式。

為了獲得正常顯示的中文,需要注意以下幾步:

  1. 因為服務器要先從本地讀取jsp文件,然后經過處理后寫入響應,所以我們首先要知道的就是jsp文件的編碼格式。從問題的源頭着手解決。

    在咱們用的windowxp下,文件默認的編碼格式是gb2312。

  2. 我們要在http的響應(response)中添加編碼信息,使用如下方式:

    <%@ page contentType="text/html; charset=gb2312"%>

    這段要放在jsp頁面的第一行,用來指定響應的類型和編碼格式,contentType為text/html就是html內容,charset表示編碼為gb2312。這樣瀏覽器就可以從響應中獲得編碼格式了。

    這種<%@ %>的形式叫做jsp指令(directive),現在接觸到的是page指令。

  3. 還需要在html中指定編碼格式
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
        <title>title</title>
    </head>

    meta部分用來指定當前html的編碼格式,注意這一段要放在head標簽中,並且放到head標簽的最前面,如果不是最前面ie下可能會出現問題,尤其是在title中有中文的情況下。

    完成了以上三段檢驗,我們才能保證輸出的jsp頁面會正常顯示中文。

     

    2. POST亂碼

    先把form里加上method="POST",讓form提交的時候使用POST方式。

    發送請求的時候,使用的編碼是iso-8859-1,意味着只有英文是有效字符,這個限制是因為當初指定http標准的成員都來自英語國家,所以如果使用默認的方式從請求獲取數據,中文一定會全部變成亂碼。

    如果不信,你可以在剛才的例子里輸入中文,然后提交:

    提交結果就會變成這樣:

    怎么解決呢?我們要jsp最前面加上一條java語句,設置請求的字符編碼。
    <%
        request.setCharacterEncoding("gb2312");
    %>

     

    於是,那些亂碼都正常了:

     
     
    3. GET亂碼

    警告

    GET情況下,使用URLEncode()的確可以解決亂碼問題,該部分需要補充。

    直接點擊超鏈接,form的默認提交方式都是GET。POST方式下的解決方式還算簡單,因為POST方式下提交的數據都是以二進制的方式附加在http請求的body部分發送,只需要在后台指定編碼格式就足矣解決。GET方式下會將參數直接附加到url后面,這部分參數無法使用request.setCharacterEncoding()處理,結果就是get形式的所有中文都變成了亂碼。

    這時再也沒有簡便方法了,只能對這些中文一個一個進行轉換,使用new String(bytes, "gb2312")進行轉碼。

    這時再也沒有簡便方法了,只能對這些中文一個一個進行轉換,使用new String(bytes, "gb2312")進行轉碼。

    <% String username = request.getParameter("username"); byte[] bytes = username.getBytes("iso-8859-1"); String result = new String(bytes, "gb2312"); out.print(result); %>

    如我們所見,先從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 }
    View Code

    在此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編碼。

     

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM