request,response亂碼問題分析及解決總結

 剛纔回顧以前的項目時,突然發現了這個老朋友,剛入坑時,這個問題可是折磨了我許久,因爲剛進公司時,負責一個GBK編碼的老項目改造,出現了不少亂碼問題,藉此機會總結一下,若也能給新入坑的夥伴一絲幫助那就更好了~:)。

問題背景


  • request亂碼指的是:瀏覽器向服務器發送的請求參數中包含中文字符,服務器獲取到的請求參數的值是亂碼;
  • response亂碼指的是:服務器向瀏覽器發送的數據包含中文字符,瀏覽器中顯示的是亂碼;

原因分析


 不管是request亂碼還是response亂碼,其實都是由於客戶端(瀏覽器)跟服務器端採用的編碼格式不一致造成的。

  • request亂碼:瀏覽器向服務器發送請求,因爲瀏覽器與服務器之間的通信實質上是socket流,所以要先將請求參數(字符)轉換成字節,也就是編碼過程,服務器接收到請求參數後進行解碼(字節轉字符),然後封裝到request對象中。如果客戶端的編碼與服務器端的解碼不統一,就會導致通過request獲取到的請求參數的值是亂碼。
  • response亂碼:服務器發給瀏覽器的數據默認是按照ISO-8859-1編碼,瀏覽器接收到數據後按照默認的字符集進行解碼後顯示,如果瀏覽器的默認解碼字符集不是ISO-8859-1,就出現亂碼。

推薦方式


 若準備建一個新項目,那麼web應用所有文件推薦都一致採用UTF-8編碼,通過配置編碼過濾器(見方法一)以及設置應用服務器請求編碼都爲UTF-8(見方法二中解決get請求亂碼部分), 可以有效避免出現亂碼問題。

解決方法


方法一:配置編碼過濾器

spring項目可以如下配置:
在web.xml中配置:org.springframework.web.filter.CharacterEncodingFilter

<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>*.do </url-pattern> 
</filter-mapping>

方法二:設置 request 和 response 的編碼 ( 頁面編碼必須爲 utf-8 )

解決post請求亂碼:

Action中:

request.setCharacterEncoding("UTF-8");//設置傳值編碼,解決request亂碼,即解決後臺接收參數亂碼
response.setContentType("text/html;charset=UTF-8");//設置傳輸編碼,解決response亂碼,即解決頁面顯示亂碼

 該方法必須在response.getWriter()之前進行設置,等同於:

response.setHeader("contentType", "text/html; charset=utf-8”);

它其實會覆蓋response.setCharacterEncoding("utf-8”)

解決get請求亂碼:

 URL中的字符串的編碼和解碼是由瀏覽器和應用服務器的配置決定的,get方式提交的參數會跟在請求行中的uri後邊,服務器按照默認的iso-8859-1進行解碼,我們的程序不能設置,不要期望用request.setCharacterEncoding()方法能設置URL中參數值解碼時的字符集,但我們可以通過修改服務器端對uri參數的默認編碼來解決get請求(url傳參)的亂碼問題:

(1)對於Tomcat:
 在server.xml中,設置元素的屬性URIEncoding="UTF-8”即可,作用是告訴服務器servlet解碼URL時採用的編碼。

<Connector port="8080" protocol="HTTP/1.1"
               maxThreads="150" connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8"/>

 其實還可以同時設置元素的屬性useBodyEncodingForURI=“true”,意思是請求體和uri使用相同的編碼格式。

<Connector port="8080" ... useBodyEncodingForURI="true" />

 通過設置這兩個屬性,既可以解決get方式的亂碼,又可以解決 post方式的亂碼。

注意:通過修改server.xml指定服務器對get和post統一按照utf-8解碼,要求tomcat管理下的所有web應用都要使用utf-8編碼,即所有的jsp、html頁面都使用utf-8編碼。

(2)對於 weblogic服務器
在weblogic.xml中設置:

<input-charset>
  <java-charset-name>GBK</java-charset-name>
</input-charset>

方法三:轉碼UTF-8(只適合解決少量棘手問題)

Action中:

String ss=new String(param.getBytes("ISO-8859-1"),"utf-8"); //轉碼爲UTF-8,其中param是前臺傳來的字符串參數,

方法四:encodeURI()兩次編碼後臺解碼(只適合解決少量棘手問題)

1、在javascript中利用encodeURI()兩次嵌套對URL中的中文參數進行編碼
2、在後臺獲取到進過前端encodeURI()編碼後的字符串,使用decode(String str,String ecn)方法進行解碼

實例:
jsp中傳參:

"param="+encodeURI(encodeURI(param))

Action接收參數:

param=java.net.URLDecoder.decode((String) getParameter("param"), "UTF-8");

參考文獻

http://www.iteye.com/problems/42143
http://blog.csdn.net/yzhz

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