1. 程式人生 > >終結解決Java Web開發過程中的中文亂碼問題

終結解決Java Web開發過程中的中文亂碼問題

網上很多關於Java Web開發過程中的中文亂碼問題,我們前端後端都設定為UTF-8的編碼,最後還是會發生亂碼問題。

1、不同瀏覽器造成的問題

2、不同版本Tomcat造成的問題

在Tomcat不同版本對編碼的預設處理於是不一樣的,Tomcat7(包括Tomcat7)之前的版本預設是iso-8859-1,tomcat 7之後的版本用的是UTF-8編碼,截圖為證:
Tomcat7:
Tomcat7預設編碼為iso-8859-1
Tomcat8:
Tomcat8預設編碼為UTF-8
解決辦法:
這兩個問題是相輔相成的。我們在前端使用什麼編碼的,在Tomcat中使用相同的編碼方式進行解碼,我們就能得到正確的值。
說起來是廢話,我們看下例子:
在Tomcat的server.xml檔案中,我們修改

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

這個時候,我們使用Chrome瀏覽器,後臺就能得到正確的值,但是我們用IE瀏覽器就得到了亂碼,再也變不回來了,估計是位元組被破壞了,同樣的我們將URIEncoding改為GBK,就能直接直接獲取IE訪問的URL中文引數了,但是Chrome的中文引數就是亂碼了,而且再也變不回來了。
但是我們可以取一個折中的辦法,比如,我們在Tomcat將編碼改為ISO-8859-1,然後在後端判斷,作相應的處理:

        String name = request.getParameter("name");
        if(!StringUtils.isEmpty(name)) {
            if(!isMessyCode(new String(name.getBytes("ISO-8859-1"), "UTF-8"))) {
                logger.info("傳過來的引數為:"+ new String(name.getBytes("ISO-8859-1"), "UTF-8"));
            }else {
                logger.info("傳過來的引數為:"
+ new String(name.getBytes("ISO-8859-1"), "GBK")); } }

isMessyCode判斷亂碼的函式為:

    /** 
     * 判斷字元是否是中文 
     * 
     * @param c 字元 
     * @return 是否是中文 
     */  
    public static boolean isChinese(char c) {  
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);  
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS  
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS  
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A  
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION  
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION  
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {  
            return true;  
        }  
        return false;  
    }  

    /** 
     * 判斷字串是否是亂碼 
     * 
     * @param strName 字串 
     * @return 是否是亂碼 
     */  
    public static boolean isMessyCode(String strName) {  
        Pattern p = Pattern.compile("\\s*|\t*|\r*|\n*");  
        Matcher m = p.matcher(strName);  
        String after = m.replaceAll("");  
        String temp = after.replaceAll("\\p{P}", "");  
        char[] ch = temp.trim().toCharArray();  
        float chLength = ch.length;  
        float count = 0;  
        for (int i = 0; i < ch.length; i++) {  
            char c = ch[i];  
            if (!Character.isLetterOrDigit(c)) {  
                if (!isChinese(c)) {  
                    count = count + 1;  
                }  
            }  
        }  
        float result = count / chLength;  
        if (result > 0.4) {  
            return true;  
        } else {  
            return false;  
        }  

    } 

判斷亂碼的函式是我在網上找的,這樣就能同時識別GBK和UTF-8的引數了,以ISO-8859-1作為中間編碼。
但是有種情況,Tomcat的環境是固定的,你改了配置,讓其他的專案都不能玩了,這肯定不行。如果Tomcat編碼環境是ISO-8859-1的,我們就按以上的方法處理,如果Tomcat編碼環境是UTF-8的,對於IE這樣的瀏覽器,我們就要避免使用者直接在位址列輸入地址,實在不行,我們就設計成restful風格的URL,中文path Info是作為UTF-8處理的,不受作業系統的影響,IE瀏覽器設定始終以UTF-8傳送,預設是選中的。直接能得到path引數值,我還沒看到Tomcat編碼環境是GBK的,要是實在是GBK的,我們就只能設計避免使用者在位址列中包含中文的URL了。
如果文中有什麼錯誤或者大家有什麼更好的辦法,請給我留言,共同探討!!!