Java Web乱码分析及解决方案
1.? 什么是URL編碼。
URL編碼是一種瀏覽器用來(lái)打包表單輸入的格式,瀏覽器從表單中獲取所有的name和其對(duì)應(yīng)的value,將他們以name/value編碼方式作為URL的一部分或者分離的發(fā)送到服務(wù)器上。
?
2.? URL編碼規(guī)則。
每對(duì)name/value由&分開(kāi),每對(duì)來(lái)自表單的name/value用=分開(kāi)。如果用戶(hù)沒(méi)有輸入值的那個(gè)name依舊會(huì)出現(xiàn)不過(guò)就是沒(méi)有值。
URL編碼是在字符ASCII碼的十六進(jìn)制數(shù)的前面加上%。例如\(她的十六進(jìn)制數(shù)表示為5c)的URL編碼就是%5c。
?
3.? 簡(jiǎn)單介紹亂碼和http請(qǐng)求
其實(shí)做web開(kāi)發(fā)亂碼問(wèn)題是經(jīng)常出現(xiàn)的,有了上面編碼的基礎(chǔ)之后下面來(lái)看看亂碼。
1)? 亂碼問(wèn)題是web開(kāi)發(fā)過(guò)程中經(jīng)常遇到的問(wèn)題,主要原因就是URL中使用了非ASCII碼造成服務(wù)器后臺(tái)程序解析出現(xiàn)亂碼的問(wèn)題。
2)? URL中最容易出現(xiàn)中文的地方就是在QueryString的參數(shù)值還有Servletpath中。
3)? 簡(jiǎn)單用一個(gè)圖來(lái)說(shuō)明一下http請(qǐng)求的流程:
?
第一步:瀏覽器把URL經(jīng)過(guò)編碼送給服務(wù)器;
第二步:服務(wù)器把這些請(qǐng)求解碼處理完畢之后將顯示的內(nèi)容進(jìn)行編碼發(fā)送給客戶(hù)端瀏覽器;
第三步:瀏覽器按照指定的編碼顯示網(wǎng)頁(yè)
post請(qǐng)求
詳細(xì)剖析POST提交如何編碼以及服務(wù)器如何解碼以及亂碼解決方案
對(duì)于POST方式,表單中的參數(shù)值對(duì)是通過(guò)request包發(fā)送給服務(wù)器,此時(shí)瀏覽器會(huì)根據(jù)網(wǎng)頁(yè)的ContentType("text/html; charset=GBK")中指定的編碼進(jìn)行對(duì)表單中的數(shù)據(jù)進(jìn)行編碼,然后發(fā)給服務(wù)器。
在服務(wù)器端的程序中我們可以通過(guò)
Request.setCharacterEncoding()設(shè)置編碼,然后通過(guò)
request.getParameter獲得正確的數(shù)據(jù)。
這里出現(xiàn)亂碼可以通過(guò)Request.setCharacterEncoding()直接解決。
get請(qǐng)求
對(duì)于GET方式,我們知道它的提交是將請(qǐng)求數(shù)據(jù)附加到URL后面作為參數(shù),這樣依賴(lài)亂碼就會(huì)很容易出現(xiàn),因?yàn)閿?shù)據(jù)name和value很有可能就是傳遞的為非ASCII碼。
當(dāng)URL拼接后,瀏覽器對(duì)其進(jìn)行encode,然后發(fā)送到服務(wù)器。具體規(guī)則見(jiàn)URL編碼規(guī)則。
這里詳細(xì)說(shuō)一下encode的過(guò)程中容易出現(xiàn)的問(wèn)題,在這個(gè)過(guò)程中我們要明白需要URL encode的字符一般都是非ASCII碼字符,所以我們就能知道出現(xiàn)亂碼主要是URL中附加了中文或特殊字符做成的,另一個(gè)要知道URL encode到底是以什么樣的編碼方式對(duì)字符進(jìn)行編碼的,其實(shí)這個(gè)編碼方式是由瀏覽器決定的,不同的瀏覽器和同一瀏覽器的不同設(shè)置影響了URL的編碼,所以為了避免我們不需要的編碼,我們可以通過(guò)java代碼或javaspcript代碼統(tǒng)一進(jìn)行控制。
完成了URL encode之后URL就成了ASCII范圍內(nèi)的字符了,然后就以iso-8859-1的編碼方式轉(zhuǎn)換為二進(jìn)制隨著請(qǐng)求頭一起發(fā)送出去。
到了服務(wù)器之后,首先服務(wù)器會(huì)先用iso-8859-1進(jìn)行解碼,服務(wù)器獲取的數(shù)據(jù)都是ASCII范圍內(nèi)的請(qǐng)求頭字符,其中請(qǐng)求URL里面帶有參數(shù)數(shù)據(jù),如果是中衛(wèi)或特殊字符,那么encode后的%XY(編碼規(guī)則中的十六進(jìn)制數(shù))通過(guò)request.setCharacterEncoding()是不管用的。這時(shí)候我們就能發(fā)現(xiàn)出現(xiàn)亂碼的根本原因就是客戶(hù)端一般是通過(guò)用UTF-8或GBK等對(duì)數(shù)據(jù)進(jìn)行encode的,到了服務(wù)器卻用iso-8859-1方式decoder顯然不行。
這里的解決方式有兩種,
?通常上,我們的請(qǐng)求都會(huì)首先發(fā)給Web容器(下面以Tomcat為例),URL也會(huì)被Web容器解碼,對(duì)于Tomcat容器來(lái)說(shuō),我們可以在conf/server.xml的connector標(biāo)簽中增加URL解碼參數(shù),默認(rèn)容器對(duì)URL的使用ISO-8859-1解碼。
?
[html]?view plain?copy?
? ??上面的是Tomcat的默認(rèn)設(shè)定,可以給標(biāo)簽添加URIEncoding屬性來(lái)指定URL的解碼方案。(PS:標(biāo)簽寫(xiě)法是URI不是URL)
? ??如果不想使用這種硬解碼方案,還可以指定另一個(gè)屬性:useBodyEncodingForURI,這個(gè)屬性用來(lái)告訴Web容器,如果request指定了解碼方案,則使用request.setCharacterEncoding指定的編碼來(lái)解碼URL。
第二種方案沒(méi)有經(jīng)過(guò)測(cè)試,如果有需要可以嘗試下。詳細(xì)資料可以參考下面的Tomcat官方文檔:
http://wiki.apache.org/tomcat/FAQ/CharacterEncoding#Q2
? ??此外,如果不想修改容器的全局配置,畢竟有時(shí)候容器里可能不止我們一個(gè)應(yīng)用,那么我們還可以采用下面的做法來(lái)提取參數(shù):
?
[java]?view plain?copy
? ??上面的做法,我們要確定Web容器對(duì)URL的解碼用的是ISO8859-1,因?yàn)椴慌懦渌诵薷牧巳萜髋渲没蛉萜髋渲帽旧肀容^奇葩的可能。
?
總結(jié)
以上是生活随笔為你收集整理的Java Web乱码分析及解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JavaScript程序员必备的5个de
- 下一篇: SSL/TLS协议运行机制