Java web中常見編碼亂碼問題(一)

  最近在看Java web中中文編碼問題,特此記錄下。html

  本文將會介紹常見編碼方式和Java web中遇到中文亂碼問題的常看法決方法:前端

1、常見編碼方式:

    一、ASCII 碼java

       衆所周知,這是最簡單的編碼。它總共能夠表示128個字符,0~31是控制字符如換行、回車、刪web

    除等,32~126是打印字符,能夠經過鍵盤輸入而且可以顯示出來的。spring

    二、ISO-8859-1apache

      它是基於ASCII碼基礎上擴展的,它總共能表示256個字符,涵蓋了大多數西歐語言字符。詳見後端

    ISO-8859-1 編碼    該編碼不支持中文,舉箇中文編碼栗子:瀏覽器

    字符串「I am 君山」用 ISO-8859-1 編碼,下面是編碼結果:tomcat

    

    因爲ISO-8859-1 是單字節編碼且不支持中文,直接將中文字符轉成‘3f’, 3f也就是常見的"?"字符服務器

    三、GB2312

      它是雙字節編碼,共包含6763個漢字。

    四、GBK

      漢字內碼擴展規範,是基於GB2312上拓展的,加入了更多的漢字,能表示21003個漢字。它的編碼

    是和GB2312兼容的。也就是說用GB2312編碼的漢字能夠用GBK來解碼,而且不會亂碼。倒過來就不完

    全能夠了,由於GB2312描述的漢字比GBK少。

    五、UTF-16

      UTF-16是基於Unicode上定義的, 用兩個字節來表示Unicode的轉換格式,它採用定長的表示方法,

    即不能什麼字符均可以用兩個字節表示。兩個字節是16個bit,因此就作UTF-16。(Unicode 囊括了世界

    上全部語言,全部語言都可經過Unicode來相互翻譯,詳解 Unicode 編碼

    六、UTF-8

      因爲UTF-16統一採用兩個字節來表示一個字符, 有不少字符用一個字節表示便可。因此存儲空間放

    大了一倍,還會增長網絡傳輸的流量,因此推出了UTF-8。 UTF-8採用了一種變長技術,每一個編碼區域有

    不一樣的字碼長度。

    經過上面介紹和對比,對於中文字符的處理我想UTF-8是最理想的中文編碼。

2、常見亂碼問題分析

    一、中文變成看不懂的字符

      若是一串中文字符變成了一串看不懂的字符如:"Ì Ô £ ¡Î Ò Ï²»¶ £ ¡",這種狀況一般是編碼

    字符集與解碼時所用的字符集不一致所形成的。好比使用GBK編碼,若是使用ISO-8859-1解碼

    的話結果就是這樣。

    二、一個漢字變成了一個問號

      若是編碼和解碼的字符集都是一致的,那麼能夠肯定該字符編碼不支持中文,例如:ISO-8859-1

    三、一個漢字變成了兩個問號

      中文通過屢次編碼且其中有一次編碼或者解碼使用了不支持中文的字符集 

 

3、常見案例分析(tomct+google)

    一、參數傳輸亂碼

      背景:從jsp中傳參數(包括中文)請求後臺數據,在後臺獲取到的請求參數亂碼。

      1.1 前端編碼設置,先講解下jsp中編碼的配置:

        a、其中contentType中charset用來設置服務器發送給客戶端時的內容編碼;pageEncoding 用

      來設置JSP源文件自己和響應正文中的字符編碼。通俗的說pageEncoding是jsp文件自己的編碼,若是

      pageEncoding設置爲ISO-8859-1,則jsp頁面中不能保存中文字符,會自動提示你是否要設置爲UTF-8.

        b、jsp文件編碼字符集默認爲ISO-8859-1, JSP源文件字符集時,優先級爲pageEncoding>

      contentType。若是都沒有設置,默認ISO-8859-1。

        c、設置響應輸出的字符集時,優先級爲contentType>pageEncoding。若是都沒有設置,默認

      ISO-8859-1。

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

      綜上所述,解決該問題亂碼的第一步要設置jsp中的編碼,最好統一爲UTF-8。

      exmaple(亂碼示例):

      

      頁面效果以下:

        

      1.2 後端編碼設置

        a、首先要設置tomcat編碼,其中要了解兩個參數(conf/server.xml):URIEncoding 和

        useBodyEncodingForURI,能夠查看官方文檔說明:

        http://tomcat.apache.org/tomcat-7.0-doc/config/http.html, 如下是我理解:

          1)URIEncoding是對全部GET方式的請求的數據進行統一的從新編碼,默認編碼爲

         ISO-8859-1(針對URI上的請求參數)

          2)useBodyEncodingForURI:此設置僅適用於請求的查詢字符串(針對請求體中內容)。

         與URIEncoding不一樣,它不影響請求URI的路徑部分。若是不知道請求字符編碼(瀏覽器不提供,

        而且SetCharacterEncodingFilter不設置或使用Request.setCharacterEncoding方法的類

        似過濾器),默認編碼始終爲「ISO-8859-1」。URIEncoding設置對此默認值沒有影響。

        該參數爲false。通俗的說:

        true表示get和post的編碼保持一致,post方式的編碼是什麼,get方式的編碼就是什麼。

        false表示get和post的字符編碼各自設置,互相沒有關係。

        example1(只設置URIEncoding):  

         server.xml

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

        controller:

        @RequestMapping(value = "/testURI", method=RequestMethod.POST)
        @ResponseBody
        public String testURI(HttpServletRequest request){
            String username = request.getParameter("username");
            String nickname = request.getParameter("nickname");
            System.out.println("姓名:" + username + ", 暱稱:" + nickname);
            return "姓名:" + username + ", 性別:" + nickname;
        }

        jsp:

      <form action="${pageContext.request.contextPath }/testURI.html?username=張三" method="post">
          <input type="text" name="nickname" value="老張三"/>
          <input type="submit" value="提交"/>
      </form>

        輸出結果:     姓名:張三, 暱稱:è€å¼ ä¸

        從結果中能夠看出, URIEncoding只對URI中的參數進行編碼。  

      example2:只修改controller中代碼,就都會顯示正常

      @RequestMapping(value = "/testURI", method=RequestMethod.POST)
      @ResponseBody
      public String testURI(HttpServletRequest request) throws UnsupportedEncodingException{
          request.setCharacterEncoding("UTF-8");
          String username = request.getParameter("username");
          String nickname = request.getParameter("nickname");
          System.out.println("姓名:" + username + ", 暱稱:" + nickname);
          return "姓名:" + username + ", 性別:" + nickname;
      }    

    其實第二種作法並非很方便,通常經過設置URIEncoding+encodingFilter便可解決。

    example3(一般作法):

    web.xml代碼以下,其他跟example1同樣便可。

  <filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

     example4:

      @RequestMapping(value = "/testURI", method=RequestMethod.POST)
      @ResponseBody
      public String testURI(HttpServletRequest request) throws UnsupportedEncodingException{   request.setCharacterEncoding("UTF-8");   String username = request.getParameter("username");    String nickname = request.getParameter("nickname");   System.out.println("姓名:" + username + ", 暱稱:" + nickname);   return "姓名:" + username + ", 性別:" + nickname;   } 

    若是隻設置URIEncoding=ISO-8859-1,request.setCharacterEncoding("UTF-8");只會

    對請求體中的參數進行編碼,因此username是亂碼的。

     

    example5: 在example4的基礎上設置useBodyEncodingForURI="true"

    設置useBodyEncodingForURI=true時,就會將請求參數和請求體中的參數根據

    request.setCharacterEncoding或者contentType中的字符集編碼。

    

 

 

本文先記錄至此,參考文獻有《深刻分析Java web解析》《tomcat docs》

相關文章
相關標籤/搜索