1、盡量使用統一的編碼,如果你是重頭開發一個系統,特別是Java開發的,推薦從頁面到數據庫再到配置文件都使用UTF-8進行編碼,安全第一。

2、采用三種方式
1)入門方法,在所有的servlet和jsp中堆設定用的代碼。
2)中級方法,對web伺服器進行配置。
3)高級方法,編寫filter過濾器,對“POST”和“GET”獨立過濾處理。
上面的注意對post和get的分別處理

3、數據庫的亂碼
a.設置數據庫的編碼
b.創建connection時候,在url中傳遞編碼
jdbc:mysql://localhost:3306/hibernateTest?useUnicode=true&characterEncoding=GBK
c.當傳遞的數據和數據庫不一致,只能重新new string














【參考】http://www.javaeye.com/topic/31742
亂碼對于使用非英語文字程序員基本上是一直纏繞在身邊的麻煩事,這個誰也避免不了。下面是我解決亂碼時候的一點小經驗。歡迎指正
 
一、避免亂碼的一些注意點:
1.盡量使用統一的編碼,如果你是重頭開發一個系統,特別是Java開發的,推薦從頁面到數據庫再到配置文件都使用UTF-8進行編碼,安全第一。
2.SetCharacterEncodingFilter的使用,這個東西不是萬能的,但是沒有它就會很麻煩,如果是基于Servlet開發的東西,能用的就給它用上,省心。不過有一個注意的地方,這個Filter只是對POST請求有效,GET一律忽略,不信你可以debug一下,看看它怎么做的,至于為什么不過濾get請求,好象是它對GET請求是無能為力的。
3.就如上面所說,GET請求有問題,盡量使用POST請求,這個也是Web開發的一個基本要領:
Web Health Warning:Put All Destructive Actions Behind a POST method(from Agile Web Development with Rails)
有點扯遠了,不過少用GET,是會有回報滴。
4.JavaScript和Ajax亂碼的避免,注意JavaScript默認是ISO8859的編碼,避免JS/AJAX亂碼和GET一樣,不要在URL里面使用中文,實在避免不了,就只能在生成鏈接的時候轉碼,絕對不能想當然的認為SetCharacterEncodingFilter會幫你做什么事情。
5.盡早統一開發環境,早點模擬真實環境測試,這個好像也有跑題的嫌疑,但凡軟件開發都是這么干的,但仍然值得注意。我這出現過一次狀況,程序是在Win下編譯的,拿去Linux上測試沒問題,等實際部署的時候代碼是在Linux下編譯,結果亂碼,秋后算帳總覺得有點晚。

二、亂碼發生的情況和應對措施
1.開發環境亂碼
      由于Java默認使用UTF-8編碼,而且網上很多人都建議Struts開發的時候應盡量選用UTF-8做為默認編碼,而非GBK。IDE使 用Eclipse,在第一次使用Eclipse的時候應將default text editor改為UTF-8編碼,免得日后后悔再改就慘了,我本次開發的時候就忽視了這一點,剛開始沒注意,結果到快交工時亂碼問題無法解決,導致將所有 的文件全部修改一遍,嗚……
      自打使用Ubuntu,我就開心的笑阿,再也不用為搞這些亂碼問題而煩惱^^(Ubuntu公益廣告)
2.POST請求的過濾
      這個是最基本的了,每個Servlet系統基本都會用到這個東西。不過只對POST請求有效,這個挺關鍵的。
      使用SetCharacterEncodingFilter,這個很基礎的一套過濾器,將所有來自頁面的POST請求全部過濾為UTF-8編碼。
3. JSP ,HTML頁面亂碼
     將JSP頁面全部改為charset=UTF-8,這樣可以保證與后臺交互的時候都是UTF-8編碼,一般應用做了以上工作就基本可以應付了。
4.資源文件中漢字轉化UTF-8字符問題
      國際化問題,在使用資源文件的時候,由于中文在properties文件中無法被程序所識別,需要將其進行轉碼,我在資源文件下面制作了一個很簡單的 bat文件,每次修改資源文件的時候都是在一個臨時文件中修改,然后執行這個bat文件,將其轉化并保存為所需要的資源文件,這個動作挺煩的,也有項目組 成員使用一些插件,但是那些東西都是直接寫UTF-8碼的,有時候反倒不方便,不過以后任務量巨大的時候可能會考慮使用。Bat文件內容:   set path=%path%;%JAVA_HOME%/bin/,native2ascii -encoding UTF-8 ApplicationResources_bk.txt > ApplicationResources_zh.properties

     PS:上面的方法好老了,實際操作起來相當麻煩,現在基本都是使用Eclipse插件,Eclipse3.1時使用PropertyEditor,但是這 個項目看上去好像停擺了,到Eclipse3.2時改用了ResourseBundle,相當的強勁的一個插件,推薦使用。
5. GET請求亂碼
      如果在本項目中采用了get方式提交請求并附加參數,結果導致編碼亂碼,原因是Tomcat默認請求編碼是ISO8859,需要在Tomcat的配置文件 server.xml添加一個參數,URIEncoding=”UTF-8”,這樣請求中附件的參數就會以UTF-8來進行編碼。
6.Ajax請求亂碼
    使用Ajax,JS也是默認使用ISO8859編碼,所以在進行請求時遇到中文參數需要進行編碼,如:var url = "GetSelectListAction.do?queryData=subTrade" + "&queryId=" + encodeURI(obj.value) + "&r=" + Math.random();  
    這里有兩個地方需要注意:第一個地方是encodeURI(),方法,可以將參數進行轉碼,默認是轉化為UTF-8,如果需要轉為其他碼制,需要在方法中添加第二個參數。
     第二個地方是Math.random(),由于Ajax有緩存機制,在接受請求的時候第一時間先判斷該請求的地址是否被訪問過,如果被訪問過則 直接使用緩存中的內容返回,這個東西很討厭,客戶在訪問過一次出錯后以后每次出現的都是這個錯誤,所以在請求中給其增加一個時間戳,只要可以隨機生成一個 不同的字串就可以,保證Ajax每次都去訪問服務器。
7. GET方法的另一個亂碼問題
      在項目即將交工的時候突然又出現亂碼問題,發現對于超長的漢字做為參數傳遞仍然會出現亂碼問題,解決方法是采用java.net.URLEncoder的 Encode方法強制轉碼,缺點是會使JSP頁面代碼相當的長,但是目前還沒有其他好的解決辦法,我想最好的辦法就是不用中文做為參數傳遞 :P,寫法如:<a href="TestAction.do?name=<%= java.net.URLEncoder.encode("你好","UTF-8")%>

8.亂碼仍然是偶們的心病,一直牽動著大家的心,最近一位朋友說連接MSSQL數據庫有亂碼,使用了很多辦法,都沒解決,后來重新下了個新的驅動搞定……
數據庫亂碼其實也很討厭的,一般來說驅動問題比較常見,所以一旦碰到比較難纏的亂碼可以先考慮下換換驅動。也有如MySQL這種,直接連接的時候就需要顯示進行編碼轉化的,這個就要不同情況區別對待了。

//2007年11月30日添加
9.WebService亂碼,由于對WebService不怎么熟悉,使用的是Weblogic提供的WebService支持,亂碼再次出現搞得手忙腳亂,而且無從下手,在自己系統上跑都沒有問題,結果跑到服務器上就全亂套,又無法調試,愁人。
    反復嘗試的過程就不說了,絕對比普通的Web開發麻煩的多。最終解決方法:
    A.為WebService服務也加上一個filter,WebService也是走HTTP協議的,這個東西同樣有用,先得加上。
    B.修改服務器上的環境變量,LANG=zh_CN.UTF-8,改成這個是為什么我仍然說的不是很清楚,不過當時開發人員就是在Win下開發的,我在自己的Ubuntu上測試沒問題,拿到Redhat服務器上就不行,因為服務器上默認的是LANG=en_US.UTF-8,這個明顯是不支持漢字的。
    經過這兩個步驟WebService亂碼總算得到抑制,它主要的麻煩在于所有與協議有關的東西都被Weblogic包辦,里面做什么事情我們不好控制,所以只能采取這種比較笨的辦法,雖然解燃煤之急但無法尋根溯源的搞定它,說不定哪天又會出來搞鬼。果然又一次出現亂碼問題,經過比較環境變量發現服務器上的LC_CTYPE被修改了,所以強制改成LC_CTYPE=zh_CN。修改環境變量的方法不到萬不得已不推薦使用。



【參考】Java開發,表單提交中發生中文亂碼的問題。

Web開發的中文問題一直困惑大家,尤其是對于初上手者。這次有機會徹底解決研究了一下中文亂碼的原因和解決方案,做個總結。
為什么會有中文亂碼?
因為在默認情況下,HTTP的包都是以“8859_1”來編碼的(沒辦法,誰叫這些標準都是老美定的)。“8859_1”是西文編碼方式,對于英文字母沒有任何問題,但是對于中文就不行了。所以,如果不做任何設定,直接將中文用“8859_1”來編碼傳遞,那結果必然是亂碼。
解決思路是什么?
好在老美還是有國際化眼光的,HTTP包的編碼方式可以由用戶指定。因此,只要事先指定好用相對應的編碼方式來對傳遞內容(比如表單提交的中文等)進行編碼,就可以順利解決亂碼的問題。
兩個基本概念
在進入具體的解決方法之前,首先要對兩個基本概念作一下解釋。對于由表單提交的內容,HTTP有兩種傳遞方式,分別是“GET”方式和“POST”方式。
“GET”方式就是將各參數直接通過HTTP的包頭(head)來傳遞,簡而言之就是直接通過我們所熟悉的網址(URL)來傳遞,所以我們經常能看到的在一個網址后面跟著許多復雜的由“?”和“&”構成的字符串,其實這就是需要傳遞的參數了。
“POST”方式則是將所需傳遞的參數包在HTTP的正文(body)中來傳遞。因此通過“POST”方式來進行傳遞,在瀏覽器的網址上面什么都看不見。
因此,相比較而言,“POST”隱蔽性較好;而“GET”方式使用起來比較容易,直接寫URL就可以了。
綜上所述,不難發現,解決中文亂碼問題實際上就變為對這兩種HTTP傳遞的編碼方式進行適當的設定。當然,從解決問題的難易以及對系統架構的完美性角度著手,又分為以下三個層次:
1)入門方法,在所有的servlet和jsp中堆設定用的代碼。
2)中級方法,對web伺服器進行配置。
3)高級方法,編寫filter過濾器,對“POST”和“GET”獨立過濾處理。
下面就具體描述各解決方法:
1)入門方法,在所有的servlet和jsp中“堆”寫設定用的代碼。
所謂入門方法,那就是現實十分簡單,當然效果也是很好的。只是必須在每個相應的文件中寫相同的設定代碼,代碼的重復性就比較大。
由前面所述,由于“POST”和“GET”方式的不同,因此對應著兩種的設定方式也不同。
“POST”的情況下,如果服務器端腳本是一個servlet,那只要在doPost()方法里面插入一句

request.setCharacterEncode("GB2312");

需要注意的是,這句設定必須在所有從request對象做提取操作之前執行,如果類似于request.getParameter()的操作在前,那么系統將使用默認的“8859_1”編碼方式,而忽略后面的設定代碼。
如果服務器端是一個jsp腳本,那只要在該腳本的jsp申明部分做好設定即可:

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

如果是“GET”方式,也就是想通過URL來傳遞中文的話,稍微要麻煩些,首先因為瀏覽器地址欄是不支持中文的,也就是如果直接將中文放置在超級連接里面是無效的。因此需要在發送端對中文內容進行編碼,比如:

URLEncoder.encoder("http://localhost/submit?name=張三","UTF-8");

“UTF-8”表示用這種編碼方式對原字符串進行編碼,編碼好之后看到的結果是

http://localhost/submit?name=%D5%C5%C8%FD

所以我們經常看到在瀏覽器里面有眾多的類似與“%D5%C5%C8%FD”這樣的字符串,就是表明被UTF-8編碼過了。由于UTF-8是跨各種平臺的通用編碼方式,因此比較常用于各種語言文字的傳輸載體。
相對應的,在接受方需要進行反向的解碼即可,代碼如下:

new String( request.getParameter("name").getBytes("8859_1"), "gb2312" );

這里可能會有一些疑問,為什么用“8859_1”來解碼。事實上,我在第一次嘗試的時候也曾使用“UTF-8”來嘗試解碼,結果出現亂碼失敗。究其原因,盡管“張三”被編碼成了“%D5%C5%C8%FD”來傳輸,但是在傳輸過程中,“%D5%C5%C8%FD”仍舊需要由“8859_1”來編碼打包成HTTP,因此,在接收端,自然先需要由“8859_1”來還原到“%D5%C5%C8%FD”的“UTF-8”格式,然后再由“UTF-8”還原到“GB2312”。
所以這樣也不難理解為什么所謂“瀏覽器地址欄是不支持中文”,不能直接用中文而要用“UTF-8”來通過“8859_1”來打包了,原因就是“%D5%C5%C8%FD”這串類似于密碼般的字符串本身就是西文字符,用“8859_1”編解碼沒有任何問題。而中文由于是2byte一個漢字,直接用西文方式來編解碼自然就會出現問題。這也就是為什么稱“UTF-8”為“跨各種平臺的通用編碼方式”了。
背景小資料:
由于“UTF-8”是通用編碼方式,因此所有的語言格式均可以轉換為“UTF-8”,在日益國際的今天,多語言的系統要求越來越多,因此強烈建議使用“UTF-8”來做為系統統一的編解碼方式,從而徹底解決中文亂碼的問題。
“UTF-8”為了能做到兼容所有語言的編解碼,因此每一個字符均用2個byte來編碼。這樣就造成了存西文字符時需要多一倍的空間。這也算是為了通用而付出的代價了。
2)中級方法,對web伺服器進行配置
可想而知,相對于“堆”寫大量代碼,配置一下web伺服器config文件來解決中文亂碼問題就顯得優雅許多。但是由于各種web伺服器的情況不同,其配置方法也不盡相同。因此,其兼容性是個比較大的問題。
這里列舉一下,如何通過修改Tomcat的conf配置文件來解決中文亂碼的問題。
找到Tomcat的配置文件server.xml中的Connector這一行,為其添加一個如下的屬性

tomcat4 中 get 與 post 的編碼是一樣的,所以只要在過濾器中通過 request.setCharacterEncoding 設定一次就可以解決 get 與 post 的問題。
然而,在 tomcat5 中,get 與 post 的處理是分開進行的,對get的處理通過 前面的URIEncoding進行處理,對post的內容依然通過 request.setCharacterEncoding 處理,為了保持兼容,就有了這個設定(useBodyEncodingForURI="true" 使用與 Body 一樣的編碼來處理 URI, 這個設定是為了與 tomcat4保持兼容)。




3)高級方法,編寫filter過濾器,對“POST”和“GET”獨立過濾處理。
高級方法,顧名思義,就是可以脫離于任何平臺,同時又免去冗余的隊旗代碼工作的解決方案——編寫過濾器,Filter。
首先編寫一個過濾器SetCharacterEncodingFilter

public class SetCharacterEncodingFilter implements Filter {
/**
        * The default character encoding to set for requests that pass through
        * this filter.
        */
protected String encoding = null;
/**
        * The filter configuration object we are associated with.  If this value
        * is null, this filter instance is not currently configured.
        */
   protected FilterConfig filterConfig = null;
   /**
       * Should a character encoding specified by the client be ignored?
       */    
protected boolean ignore = true;
 // --------------------------------------------------------- Public Methods
   /**
    * Take this filter out of service.
    */
   public void destroy() {
       this.encoding = null;
       this.filterConfig = null;
   }
/**
    * Select and set (if specified) the character encoding to be used to
    * interpret request parameters for this request.
    *
    * @param request The servlet request we are processing
    * @param result The servlet response we are creating
    * @param chain The filter chain we are processing
    *
    * @exception IOException if an input/output error occurs
    * @exception ServletException if a servlet error occurs
    */
   public void doFilter(ServletRequest request, ServletResponse response,
                        FilterChain chain)
   throws IOException, ServletException {
 // Conditionally select and set the character encoding to be used
       if (ignore || (request.getCharacterEncoding() == null)) {
           String encoding = selectEncoding(request);
           if(encoding != null){
               HttpServletRequest httpServletRequest = (HttpServletRequest) request;
               if(httpServletRequest.getMethod().toLowerCase().equals("post")){
   //如果是POST方法
                   request.setCharacterEncoding(encoding);
               }
               else{
                 //如果是GET方法
                   //非常抱歉,我還有沒有找到很好的對應get方法的代碼
                   //一旦完成了這部分代碼,馬上添加在這里。
                   //!·#¥%……—*()——+|
               }
           }
       }
 // Pass control on to the next filter
       chain.doFilter(request, response);
   }
   /**
    * Place this filter into service.
    *
    * @param filterConfig The filter configuration object
    */
   public void init(FilterConfig filterConfig) throws ServletException {
   this.filterConfig = filterConfig;
       this.encoding = filterConfig.getInitParameter("encoding");
       String value = filterConfig.getInitParameter("ignore");
       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;
   }
 // ------------------------------------------------------ Protected Methods
   /**
    * Select an appropriate character encoding to be used, based on the
    * characteristics of the current request and/or filter initialization
    * parameters.  If no character encoding should be set, return
    * <code>null</code>.
    * <p>
    * The default implementation unconditionally returns the value configured
    * by the <strong>encoding</strong> initialization parameter for this
    * filter.
    *
    * @param request The servlet request we are processing
    */
   protected String selectEncoding(ServletRequest request) {
       return (this.encoding);
   }
}

編寫完過濾器以后,需要對其進行部署,也就是在web.xml中做個配置:
在<display-name>標簽之后,添加:

   <filter>
       <filter-name>Set Character Encoding</filter-name>
       <filter-class>com.zavax.utility.filters.SetCharacterEncodingFilter</filter-class>
           <init-param>
               <param-name>encoding</param-name>
               <param-value>UTF8</param-value>
           </init-param>
           <init-param>
               <param-name>ignore</param-name>
               <param-value>true</param-value>
           </init-param>
       </filter>
   <filter-mapping>
       <filter-name>Set Character Encoding</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>