JAVA解決亂碼之道


        最近在實際工作的兩個項目中都遇到了亂碼問題,雖然沒有對亂碼實際性問題有深刻理解,不過對於現象倒是有了一二的端倪觀察,現在把自己的解決思路共享一下。

        我將亂碼問題歸類爲4種情況:

        第一種:兩個頁面之間或者頁面與後臺之間參數傳遞,一個request請求傳遞到另一個頁面或者後臺,在接收到參數進行中文處理時,出現了亂碼。亂碼的問題出現大概也有這樣幾種情況,這種情況多見於前臺用form傳遞參數:

         1)文件編碼不統一造成的,如一個頁面是gb2312,一個頁面是utf-8,甚至於有的人會在一個頁面設置兩個編碼格式;這種情況最好辦,文件編碼統一就好了。

         2)瀏覽器默認的編碼格式與後臺處理編碼存在不一致。常見的瀏覽器默認處理編碼"ISO8859-1",處理起來也很簡單,基本上利用以下編程可以解決:

        

// 自定義字符串selfDefStr 
selfDefStr = new String(selfDefStr .getBytes("ISO8859-1"), "UTF-8");
         3)前兩種組合,這個實際情況發生也很多。

        第二種:傳遞的url中包含參數,參數含有中文,多見於直接地址傳參,或者json格式傳遞參數,這種情況出現中文亂碼,多是由於瀏覽器版本造成的,經測試,firefox和谷歌瀏覽器傳遞中文時,只要利用前面提到的第一種2)的解碼方法即可解決,但對於ie瀏覽器,先要對ie進行編碼操作才行,通過js encode方法 ,進行16進制編碼,旨在將中文編程遺傳英文支持良好的字符,傳遞到後臺時信息不會錯亂。

String temStr= URLEncoder.encode(selfDefStr, "UTF-8");
firefox和谷歌同樣可以編碼後傳遞,這樣保證方式統一,無需判斷(注ie只在ie8以上測試過)

有的文章說在java後臺(側)需要利用java的decode方法進行解碼,經本人測試,後臺解碼反而亂碼,直接使用第一種2)的解碼方法進行處理反而通過,所以在此只告訴大家本人是如此解決的。萬一如此解決是亂碼,大家記得前臺編碼,後臺可以解碼這種方案即可。

       第三種:插件給java後臺(jsp)傳遞參數,比如本人集成金格公司的網頁版電子簽章,該空間只適用於ie下使用,封裝成ocx,需要activex調用。由於參數值控件提供,無法知道正確的參數值是多少。解決方法最終是一樣的,也是如下方法,只不過要知道控件的預編碼格式,如金格是gb2312,而本人工程默認是utf-8,就不能轉成utf-8:

// 自定義字符串selfDefStr 
selfDefStr = new String(selfDefStr .getBytes("ISO8859-1"), "GB2312");
  這裏值得一提的是,由於本人不知道參數傳遞是什麼形式,解決方法是,利用抓包工具來查看參數,本人推薦用fidder,具體使用本人就不贅述了,可以看到request請求信息,不如頭信息,編碼格式等,不過編碼格式的信息本人認爲這種方式意義不大,它代表的是傳遞過來的頁面的編碼格式,跟控件無關,最好是詢問控件出品方編碼格式,如果聯繫不到只能猜了,但是抓包的數據還是有利於我們對於數據一致性進行明確。抓包界面如下:


可以看到左邊是每次請求,右邊是請求傳遞的參數。該值意義重大,可以多分析幾次,看看是否每次傳遞不同,窺探控件端倪。

        第四種:由於統一的編碼過濾器造成的亂碼。統一過濾器的好處是對所有頁面統一中文轉碼,基本上不會出現中文亂碼的情況,但是總有例外,像第三種情況,總有一些特殊頁面參數來源不同,編碼格式不同,利用過濾器反而進行了一次過濾轉碼,造成後臺處理時,如何處理也不對,這種情況,就要排除個別頁面,不讓其轉碼。因爲這種情況往往被忽視,特別提出,共享大家。參數excludedPages(自定義)即爲排除。 web.xml

    <filter>
        <filter-name>SetCharacterEncoding</filter-name>
        <filter-class>com.horizon.filter.encoding.SetCharacterEncodingFilter</filter-class>
        <!-- 用戶請求和響應的編碼設置程序 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>        
            <param-name>ignore</param-name>        
            <param-value>false</param-value>    
        </init-param>
        <init-param>
            <param-name>excludedPages</param-name>  
            <param-value>/isignature/Service.jsp</param-value> 
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>SetCharacterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


對應java方法

package com.horizon.filter.encoding;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class SetCharacterEncodingFilter implements Filter {
	protected String encoding;
	protected boolean ignore;
	// 排除不進行統一編碼的頁面
	protected String excludedPages;

	public SetCharacterEncodingFilter() {
		this.encoding = null;

		this.ignore = true;
		
		this.excludedPages = "";
	}

	public void init(FilterConfig filterConfig) throws ServletException {
		
		this.encoding = filterConfig.getInitParameter("encoding");
		String value = filterConfig.getInitParameter("ignore");
		this.excludedPages = filterConfig.getInitParameter("excludedPages");
		
		if (value == null)
			this.ignore = true;
		else if (value.equalsIgnoreCase("true"))
			this.ignore = true;
		else if (value.equalsIgnoreCase("yes"))
			this.ignore = true;
		else
			this.ignore = false;
	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		if ((this.ignore) || (request.getCharacterEncoding() == null)) {
			if(excludedPages.indexOf(((HttpServletRequest)request).getServletPath()) == -1) {
				String encoding = selectEncoding(request);
				if (encoding != null) {
					request.setCharacterEncoding(encoding);
				}
			}

		}

		chain.doFilter(request, response);
	}

	public void destroy() {
		this.encoding = null;
	}

	protected String selectEncoding(ServletRequest request) {
		return this.encoding;
	}
}


發佈了52 篇原創文章 · 獲贊 15 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章