終結解決Java Web開發過程中的中文亂碼問題
網上很多關於Java Web開發過程中的中文亂碼問題,我們前端後端都設定為UTF-8的編碼,最後還是會發生亂碼問題。
1、不同瀏覽器造成的問題
2、不同版本Tomcat造成的問題
在Tomcat不同版本對編碼的預設處理於是不一樣的,Tomcat7(包括Tomcat7)之前的版本預設是iso-8859-1,tomcat 7之後的版本用的是UTF-8編碼,截圖為證:
Tomcat7:
Tomcat8:
解決辦法:
這兩個問題是相輔相成的。我們在前端使用什麼編碼的,在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了。
如果文中有什麼錯誤或者大家有什麼更好的辦法,請給我留言,共同探討!!!