springweb開發中編碼亂碼問題解析

由於平時開發過程當中總遇到亂碼的問題,很煩惱,所以總結了一下,加深了本身的印象,有些粗糙,有不正確的地方歡迎指正。最有效的是本身擼碼模擬一下全部可能出現亂碼的狀況。html

爲何會出現亂碼

一句話就能說明問題: 字符在保存時的編碼格式若是和要顯示(解碼)時的編碼格式不同的話,就會出現亂碼問題。所以咱們的先後端編碼通常都一導致用UTF-8.git

幾種亂碼解析

  • "??"亂碼分析:
    ISO-8859-1 僅能編碼非英文字符,因此非英文字符被其編碼時會被轉換爲 0x3F(即?的 ASCII 編碼,也是 UTF-8 編碼),這時編碼已經真被轉成不可逆的亂碼了。以後不管用兼容 ASCII 的哪一種編碼方案解碼還原出的字符串都是"?"。
  • "²âÊÔ"亂碼分析:
    ISO-8859-1 僅能表示非英文字符,因此使用其解碼時會嚴格按一個字節一個字節地進行解析(這種操做其實對編碼沒構成破壞,還能夠從新用 ISO-8859-1 獲取字節流後再用正確的編碼方式解碼獲得正確的字符串)。
  • "����"亂碼分析:
    用 UTF-8 解碼經 GB18030 編碼的字節流時發現四個字節均爲 UTF-8 非法字節流,因此直接轉化爲了�。

決定編碼的因素

一個http請求通過的環節:github

瀏覽器--->服務器---->瀏覽器web

在這個環節中每一步都會有影響編碼的因素:ajax

1.頁面編碼

HTML meta data 中的 charsetspring

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>hello</title>
</head>複製代碼

2.瀏覽器編碼

瀏覽器編碼的設置和頁面編碼不一致會致使頁面文字顯示亂碼
後端

Jietu20171013-001221.jpg-303.2kB
Jietu20171013-001221.jpg-303.2kB

3.ajax請求

ajaxGet
AjaxGet中的查詢參數會受瀏覽器編碼影響,因此最好使用 encodeURI 或 encodeURIComponent 手動顯式地將整個 URL 或者查詢字符串按 UTF-8 編碼。
ajaxPost
ajaxPost 請求時對於 URI 和請求體都是默認按 utf-8 編碼,而不受 content type 影響。 因此 ajaxPost 不亂碼的必要條件是將服務端 request 中的 characterEncoding 設爲"utf-8"。瀏覽器

4.spring編碼

經過類org.springframework.web.filter.CharacterEncodingFilter,定義request和response的編碼。這是由於在spring源碼裏默認用的是ISO-8859-1,對中文支持很差,所以這裏配置成UTF-8.
在web.xml裏配置tomcat

<filter>
        <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>複製代碼

CharacterEncodingFilter類具備encoding和forceEncoding兩個屬性,其中encoding是表示設置request的編碼,forceEncoding表示是否同時設置response的編碼。bash

5.tomcat配置

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

Tomcat的conf裏的server.xml裏的配置,通常配置成UTF-8,也有配置成ISO-8859-1,這裏的配置在發起get請求時會對uri進行編碼,所以須要進行處理,否則會出現亂碼。可是對post請求的body不會產生影響。
解決方法:

$.ajax({
        url:"/hello?param=" + encodeURI(encodeURI($("#before").html())),
        type:"GET",
        contentType:"application/x-www-form-urlencoded; charset=utf-8",
        success:function(result){
            $("#after").val(result);
        }
    });複製代碼

對get請求的url裏的參數進行兩次encodeURI;

@RequestMapping(value = "/hello",method = RequestMethod.GET,produces = "text/plain;charset=UTF-8")
    @ResponseBody
    public String index(@RequestParam("param") String param) throws UnsupportedEncodingException {

        String newParam = URLDecoder.decode(param,"utf-8");
        String handleMsg = "後臺處理後數據:";
        String result = handleMsg + newParam;
        return result;
    }複製代碼

後臺獲取參數時進行一次解碼,這樣獲取到的參數就不會出現亂碼。

代碼地址:github.com/PanPanda/en…

參考:深刻分析 web 請求響應中的編碼問題

相關文章
相關標籤/搜索