1. 程式人生 > >關於亂碼問題的解決與HttpServletResponse中的方法

關於亂碼問題的解決與HttpServletResponse中的方法

表單提交數據亂碼 響應數據亂碼 httpservletresponse


關於亂碼問題的解決

會有亂碼現象,其實就是因為字符集編碼不一致的問題,就好像中國人和外國人談話一樣,互相不懂對方在說啥。字符集編碼也是如此,本來就是一段GBK編碼的文字,卻要用utf-8的編碼格式去解碼,就當然是雞同鴨講會出現亂碼啦,這個時候就得使用GBK編碼的格式去解碼才不會出問題。如果互相都是使用的GBK編碼後,那就像中國人和中國人都說普通話一樣,就能聽懂對方在說什麽,這樣才不會出現亂碼。

在web開發中,請求或響應數據時出現亂碼,往往就是客戶端和服務端的編碼不一致的問題所導致的。

不過在介紹如何解決亂碼的問題前,我們先看看HttpServletRequest中關於獲得表單數據的一些方法,雖然在上一篇也介紹了使用方式,不過關於亂碼和拿到具體的值這方面沒有涉及到:


獲得和設置表單數據方法(如果是上傳文件的話則無法獲取文件中的數據):

方法名稱

作用

setCharacterEncoding(String)

設置提交上來表單的文本編碼

getParameter(String)

得到表單中某一個指定的name屬性的值

getParameterMap()

獲得所有的鍵值對(name/value)

getParameterNames()

獲得所有的name屬性的值:

getParameterValues(String)

獲得重復的name屬性的值


既然和表單有關,那麽就得先寫一個簡單的html表單代碼,我們可以在Eclipse中創建一個html文件:

技術分享

技術分享


可能使用Eclipse編寫HTML的代碼不太方便,我們也可以使用一個專門編寫html代碼的工具來編寫Eclipse裏已經創建了的html文件,我這裏使用HBuilder作為示例:

  1. 復制Eclipse中的html文件所在目錄的路徑:

技術分享


  1. 在HBuilder中點擊文件,然後選擇打開目錄把復制的文件路徑粘貼進去,並為這個工程起一個新的名稱:

技術分享

技術分享


工程目錄如下:

技術分享

如圖,可以看到index.html已經在這個工程下了,我們可以在HBuilder中編輯這個html文件,編輯的內容會同步到Eclipse,因為它倆訪問的都是同一個目錄同一個html文件。


  1. 我在HBuilder編輯的代碼如下:

技術分享


  1. 再看看Eclipse發生了什麽:

技術分享

可以看到代碼是同步的。


瀏覽器運行結果:

技術分享


以下使用實際代碼演示常用的幾個獲得表單數據的方法,代碼示例:

技術分享

技術分享


在Eclipse中執行html文件,Eclipse有一個內置的瀏覽器:

技術分享

如果要在其他的瀏覽器則需要使用這個URL地址:

http://localhost:8080/TestResponse/index.html

不要直接在HBuilder中運行這個html文件,因為它的URL是指向HBuilder的工程路徑的。


控制臺打印結果:

技術分享

如圖,可以看到我們將所有的值都獲得到手了。


獲得表單數據的時候要註意一個問題:當你需要獲得一個屬性的值時,如果得到的結果為null,那麽就是因為表單數據中並沒有這個屬性的存在。例如我獲得一個不存在的屬性:

技術分享


控制臺打印結果:

技術分享

可以看到結果為null,所以當你獲得表單數據進行某些操作時,出現了空指針異常的話,很有可能就是因為代碼上寫錯了獲得了一個不存在的屬性。


如果表單數據中的某個屬性值沒有寫,那麽獲得的將是一個空字符串,而非null,例如:


技術分享


控制臺打印結果:

技術分享

如圖,並沒有打印null,而是打印空白,這個空白就是一個空字符串:’’




會出現亂碼的情況,以及解決方法:

現在我們修改一下代碼把表單提交的方法改為post,再運行一次,看看控制臺的打印結果,html代碼示例:

技術分享


Java代碼示例:

技術分享


提交的表單:

技術分享


控制臺的打印結果:

技術分享


可以看到控制臺中的打印結果出現了不能識別的字符,解決方法很簡單,使用setCharacterEncoding(String)方法,設置表單提交的數據的編碼格式即可:

技術分享


運行結果:

技術分享


註意:除了在Java代碼中需要設置編碼格式,在html文件中也要設置好編碼格式,如果html中不設置編碼格式的話,即便在Java代碼中使用了setCharacterEncoding(String)方法設置了也沒有用,所以這是雙向的,例如我把html文件中設置編碼格式的標簽給刪掉:

技術分享

可以看到在網頁上顯示都是亂碼(這是因為Eclipse內置的瀏覽器原因,一般市面上的瀏覽器提前預設了字符編碼,所以不會出現這種情況)


控制臺打印結果:

技術分享

果然出現了不能識別的字符,所以html文件也是需要設置好編碼的,不然的話就會出現亂碼的情況。


下面來看看瀏覽器的地址欄中為什麽能夠顯示中文:

技術分享


這其實是因為瀏覽器轉碼了,可以把這個URL復制到記事本中:

技術分享

可以看到是一堆的編碼,並沒有顯示中文,所以實際上瀏覽器就是把這個編碼給轉換成了中文而已。

只要不屬於128個字符內的字符,在地址欄中都會轉換成這種格式的編碼,這些編碼格式是采用的16進制的編碼格式,以上面這文本示例編碼對應的中文:

技術分享

如圖,每一個16進制編碼都是以%開頭,這是utf-8編碼的中文,所以一個中文字對應3個16進制編碼。

如果是GBK編碼格式的中文則是一個中文字對應2個16進制編碼,但是GBK編碼格式轉換成的16進制編碼不能被瀏覽器轉換,會仍然顯示著16進制編碼:

技術分享


中文字對應的16進制編碼:

技術分享

如圖,GBK編碼格式的中文字和utf-8編碼的中文字不一樣,是2個16進制編碼對應一個中文字。


關於客戶端請求數據方面的亂碼情況就介紹這麽多,另外響應數據中出現亂碼的情況和解決方法在介紹HttpServletResponse方法部分進行說明。


思維導圖:

技術分享





HttpServletResponse中的方法

HttpServletResponse接口類型的對象是封裝服務端響應數據的,所以這個對象中的方法都是與響應數據相關。以下羅列一些常用的方法:

方法名稱

作用

encodeURL(String)

對給定的URL進行編碼

sendError(int)

發出錯誤狀態碼

sendError(int, String)

發出錯誤狀態碼,並輸出一個字符串

sendRedirect(String)

跳轉頁面

getOutputStream()

得到8位的輸出流

getWriter()

得到16位的輸出流

setBufferSize(int)

設置緩存流大小


下面使用實際的例子,演示以上方法的使用方式:

技術分享


編輯響應頭一類的方法:

方法名稱

作用

setCharacterEncoding(String)

設置響應數據的編碼格式

setContentLengthLong(long)

告訴瀏覽器響應的數據長度

setContentType(String)

告訴瀏覽器本次響應的數據類型


代碼示例:

技術分享

在服務端設置響應數據的編碼格式是很有必要的,這麽做同樣的也是為了避免出現亂碼的問題。例如以下這個示例,我不設置響應數據的編碼格式,並輸出一段中文,看看會發生什麽,代碼示例:

技術分享


運行結果:

技術分享

如圖,可以看到,沒有設置響應數據的編碼格式的話,輸出中文就會無法被識別。

這種問題設置一下響應數據的編碼格式就好了,但是服務端設置的編碼格式,要與瀏覽器端的編碼格式對應上,如果不對應的話仍然會是亂碼,代碼示例:

技術分享


運行結果:

技術分享




添加新的響應頭數據:

方法名稱

作用

addDateHeader(String, long)

添加一個長整型的時間值

addHeader(String, String)

添加一對鍵/值(值的類型為字符串類型)

addIntHeader(String, int)

添加一對鍵/值(值的類型為整型類型)

代碼示例:

技術分享


打開TCP/IP Monitor窗口,可以看到以上代碼添加進響應頭的數據:

技術分享



獲得設置的響應頭信息:

方法名稱

作用

getHeader(String)

參數為鍵,獲得該鍵的值

getHeaderNames()

獲得所有的鍵

getHeaders(String)

參數為鍵,獲得拆分的值

代碼示例:

技術分享


控制臺打印結果:

技術分享



修改響應頭信息:

方法名稱

作用

setDateHeader(String, long)

修改一個長整型的時間值

setHeader(String, String)

修改指定的鍵的值(值的類型為字符串類型)

setIntHeader(String, int)

修改指定的鍵的值(值的類型為整型類型)

代碼示例:

技術分享


TCP/IP Monitor窗口:

技術分享



總結:

  • 解決客戶端表單提交數據亂碼的問題,需要使用setCharacterEncoding(String)方法,設置好與客戶端對應的編碼格式。

  • 解決服務端響應數據亂碼的問題,則使用setCharacterEncoding(String)方法,設置好對應的編碼格式。

  • HttpServletRequest是封裝請求數據的對象,所以它的方法都是與客戶端請求信息相關的。

  • HttpServletResponse是封裝響應數據的對象,所以它的方法都是與服務端響應信息相關的。





本文出自 “zero” 博客,請務必保留此出處http://zero01.blog.51cto.com/12831981/1980454

關於亂碼問題的解決與HttpServletResponse中的方法