Web開發過程中亂碼問題

Springmvc、get/post提交亂碼

淡泊以明志,寧靜以致遠

昨天在用springmvc開發Web項目時,遇到了亂碼問題,弄了將近5個小時才弄好。希望我遇到的問題可以幫助到大家。
【問題描述】我在JSP頁面通過超鏈接訪問Controller,請求的地址中有中文,例如

<a href="http://localhost:8080/mydemo/user/save?uname='中'">鏈接</a>

但是到達Controller中取出來確實亂碼。爲什麼會產生亂碼呢?怎樣處理這樣的亂碼呢?在徹底解決這個問題之前,我們需要對編碼、解碼的基礎知識有一定的瞭解。這就是所謂的“工欲善其事,必先利其器”。

一、編碼的基礎知識

(一)爲什麼要編碼?

我們和瀏覽器交互使用的是字符,我們發送給服務器的請求在網路間是通過字節流傳輸的。所以,我們發送的請求要結果編碼,服務器接收到請求後要進行解碼。

(二)什麼是編碼和解碼?

這裏寫圖片描述
上面就是編碼、解碼和字符集的基礎概念。編碼有兩種方式:第一種就是通過字符集進行編碼和解碼;第二種就是URI編碼、URI解碼
當然在進行URI編碼時,也要有對應的字符集。比如,“中”通過URI編碼後的結果是“%E4%B8%AD%”。這裏同樣使用了utf-8字符集。(”中”的urf-8編碼是”E4B8AD”)很容易看出來,URI編碼就是將一個字符串用%+對應的字符集編碼組織的字符串來表示的。

(三)URI編碼(理解重點)

什麼時候會進行URI編碼呢?URI編碼會對我們發送請求的地址進行編碼。例如上面。

<a href="http://localhost:8080/mydemo/user/save?uname='中'">鏈接</a>

URI會對後面請求的地址進行編碼。默認是由瀏覽器進行的。不同的瀏覽器,在不同的操作系統中在進行URI編碼時,採用的字符集不同。所以,我們的解決方案是在頁面先通過JavaScript中的URLEncode函數對中文先進行URI編碼,這樣我們就可以指定字符集了。然後把編好碼的結果放到地址中,進行請求。
但是,我遇到的問題並不是這個問題。因爲如果我們不手動進行URI編碼,瀏覽器也會根據網頁中的charset中指定的字符集進行編碼。

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page contentType="text/html;charset=utf-8"%>

(四)從頁碼請求到服務器接收請求後流程圖

①原URL(請求地址)
②Get提交,瀏覽器根據http頭的Content-Type的charset對URL進行URI編碼

<%@ page contentType="text/html;charset=utf-8"%>

Post提交,瀏覽器根據http頭的

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

對URL進行URI編碼。
或者利用Javascript使用指定字符集手動對URL進行編碼。
④編碼後的URL全是ASCII碼。
⑤然後瀏覽器把URL以iso-8859-1編碼方式轉換成二進制的字節碼,進行網路傳輸。這裏有個理解重點:iso-8859-1中是沒有中文的。
⑥隨請求頭一起發送出去(get無實體,post有實體)
⑦服務器接收到瀏覽器發送過來的URL,並用iso-8859-1進行解碼
⑧網頁一般都會有meta頭的charset選項,服務器根據此進行再次解碼(post表單提交過來的也會根據此編碼進行解碼)。但是這個只使用於post方式提交的請求。
⑨最後就得到正確的值。

然而到達這裏問題似乎還是沒有解決,不過問題的原因可以推測出來了。問題就是iso-8859-1中是沒有中文的。通過get方式提交的請求,URL還是會根據服務器默認的iso-8859-1進行解碼,沒有對應的中文解碼,所以產生了亂碼。

(五)URIEncoding和useBodyEncodingForURI

在我開發過程中用的是Tomcat 6x,所以我又去了解了一下Tomcat對Get的URL解碼相關知識。
Tomcat默認是按iso-8859-1進行URL解析,而iso-8859-1中沒有中文,所以產生亂碼,這裏剛纔分析過了。
常見的解決方式是:在tomcat的server.xml下的connetor屬性中增加URIEncoding或者useBodyEncodingForURI屬性。
按照tomcat-docs/config/http.html文檔的說明
**URIEncoding:**This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
**useBodyEncodingForURI:**This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding.

也就是說,
useBodyEncodingForURI參數表示是否用request.setCharacterEncoding參數對URL提交的數據和表單中GET方式提交的數據進行重新編碼,在默認情況下,該參數爲false。
URIEncoding參數指定對所有GET方式請求進行統一的重新編碼(解碼)的編碼。
URIEncoding和useBodyEncodingForURI區別是,URIEncoding是對所有GET方式的請求的數據進行統一的重新編碼,而useBodyEncodingForURI則是根據響應該請求的頁面的request.setCharacterEncoding參數對數據進行的重新編碼,不同的頁面可以有不同的重新編碼的編碼。

所以,最終的解決方案就出來咯。在tomcat的server.xml下的connetor屬性中增加URIEncoding屬性。
這裏寫圖片描述

最後,補充一個相關的知識點:
大家都知道,我們在使用springmvc進行Web項目開發時,會在web.xml中配置字符編碼過濾器。

<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>

但是這個配置是針對post請求的。這下關於編碼使用的就相對完整了。


最後感謝一下參考博客,謝謝您們的分享:
http://blog.csdn.net/superch0054/article/details/9325793

http://www.cnblogs.com/liukemng/p/4178882.html

http://blog.sina.com.cn/s/blog_8a18c33d0101aabe.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章