溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

J2EE Web組件中中文及相關(guān)問題的示例分析

發(fā)布時(shí)間:2022-01-13 09:33:23 來源:億速云 閱讀:115 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關(guān)J2EE Web組件中中文及相關(guān)問題的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

 XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />

三、  服務(wù)器發(fā)送中文

雖然大家一般都不用JSP甚至servlet來處理處理客戶提交的數(shù)據(jù)或訪問請(qǐng)求參數(shù),但JSP的使用或更新總是比Servlet或 JavaBean來得方便(至少在tomcat 4.0.4中是如此,因?yàn)槲覀兂32坏貌粸樾薷牧薙ervlet或JavaBean而重啟服務(wù)器),所以在這里我們還是要用JSP來訪問請(qǐng)求參數(shù)了。

不管是在JSP還是在Servlet中,我們都是用ServletRequest(或其子類)的方法getParameter(String name)來訪問請(qǐng)求參數(shù)的,這個(gè)方法返回的是String,也就是說我們能得到的是已經(jīng)對(duì)Inte.NET傳來的字節(jié)流解碼所得的字符串。如果服務(wù)器能對(duì)這些字節(jié)流進(jìn)行正確的解碼,那將是件完美的事。其實(shí)說來也很簡(jiǎn)單,要做到這一點(diǎn)只需要服務(wù)器知道這些字節(jié)流在客戶端是用什么編碼進(jìn)行編碼也就行了。如圖 2-17我們希望decoding==encoding。

ASPectratio="t" v:ext="edit">J2EE Web組件中中文及相關(guān)問題的示例分析2003-10-241629040.gif" o:title="2-17show">

圖 3-1 數(shù)據(jù)從瀏覽器到服務(wù)器

可理想與現(xiàn)實(shí)往往是沒有交集的,我們?cè)趺匆膊荒茏尫?wù)器知道這些字節(jié)到底是用什么編碼被編碼的,即使在萬維網(wǎng)相關(guān)技術(shù)的主要設(shè)計(jì)組織w3c(World Wide web Consortium)的《HTML 4.01 Specification》和Internet工程任務(wù)組(Internet Engineering Task Force, IETF)定義HTTP1.1的rfc2616(《Hypertext Transfer Protocol -- HTTP/1.1》)中也沒有發(fā)現(xiàn)有什么相關(guān)的推薦辦法,能在現(xiàn)有的瀏覽器和HTML Web頁下讓服務(wù)器知道這個(gè)編碼是什么(如果你知道該怎么做,一定請(qǐng)記得告訴我),所以在缺省情況下,Tomcat 4.0.4又一廂情愿的用起了ISO8859-1來對(duì)客戶端提交的數(shù)據(jù)進(jìn)行解碼。如圖 2-17,decoding=ISO8859-1,可如果encoding!=ISO8859-1呢,很明顯這就是一個(gè)數(shù)據(jù)錯(cuò)誤傳輸了。注意,我們這里所講的數(shù)據(jù),僅僅是客戶端給服務(wù)器發(fā)送的數(shù)據(jù)中的實(shí)體(Entity Body)中的數(shù)據(jù)。

1.  誰決定了Encoding

誰決定了瀏覽器的當(dāng)前Web頁通過Form向Internet(最終的對(duì)象當(dāng)然是服務(wù)器)發(fā)送數(shù)據(jù)字節(jié)流的編碼呢?當(dāng)然是瀏覽器了。那瀏覽器又是靠什么決定這個(gè)編碼的呢?那是繼承的瀏覽器解碼當(dāng)前頁(它當(dāng)然也要對(duì)當(dāng)前Web頁解碼了,別忘了任何文件或Internet上的元數(shù)據(jù)都是字節(jié))所使用的decoding了,其實(shí)說是繼承也不全對(duì),后面你就會(huì)發(fā)現(xiàn)的。

2.  靠什么決定了Encoding

大約是這六個(gè)方面來的信息使瀏覽器決定用什么encoding:

1)  xsl所決定的

2)  實(shí)體(Entity Body)中的特殊標(biāo)記

3)  用戶手動(dòng)對(duì)該Web頁設(shè)置的decoding

4)  響應(yīng)頭(Response Header Field)中的Content-Type

5)  HTML元素META中的charset

6)  瀏覽器以前所用的decoding

它們的優(yōu)先級(jí)可能會(huì)因?yàn)闉g覽器的不同而不同,但在IE6.0中是遞減的,微軟這種做法確實(shí)曖昧、耐人尋味,難怪它會(huì)在瀏覽器大戰(zhàn)中取得勝利。下面僅對(duì)這六點(diǎn)一一解釋。

XSL(eXtensible Stylesheet Language, 可擴(kuò)展樣式單語言)可以方便地將XML(eXtensible Markup Language, 可擴(kuò)展標(biāo)記語言)轉(zhuǎn)換為其他很多種內(nèi)容,我們這里只關(guān)心它把XML轉(zhuǎn)換為HTML,而對(duì)瀏覽器編碼設(shè)置的影響。如果該XSL遵循 W3C在1998年發(fā)布的有關(guān)XSL的第一個(gè)工作草案標(biāo)準(zhǔn)(設(shè)置XSL文件中的xmlns:xsl="http://www.w3.org/TR/WD-xsl"),則可以通過在XSL中添加元素meta,并作相類似的設(shè)置達(dá)到設(shè)置瀏覽器編碼的目的:

如果該XSL是事實(shí)上的XSLT(eXtensible Stylesheet Language Transformation, 可擴(kuò)展樣式單轉(zhuǎn)換語言),即xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”,則瀏覽器編碼無條件使用UTF=16,即使在XSL文件中添加meta元素來設(shè)置編碼都將被忽略。

實(shí)體是指服務(wù)器給瀏覽器返回的數(shù)據(jù)中的實(shí)體,也可以簡(jiǎn)單理解為返回?cái)?shù)據(jù)中除附加頭和空白行之外的所有數(shù)據(jù)。在前面說過,windows 2000 Server(我實(shí)驗(yàn)所用的操作系統(tǒng))會(huì)在以UTF-8編碼的文件前加三個(gè)流氓字節(jié)(0xEF0xBB0xBF),如果當(dāng)前Web頁是靜態(tài)資源,則服務(wù)器會(huì)不加任何處理直接把這個(gè)Web 頁返回到客戶端,如果這個(gè)靜態(tài)Web頁也是在Windows 2000 Server中生成的話,那么實(shí)體的最初三個(gè)字節(jié)將是0xEF0xBB0xBF,瀏覽器很快檢測(cè)到這三個(gè)字節(jié),于是就用UTF-8對(duì)正確解碼,后面那四點(diǎn)都會(huì)被忽略。

手動(dòng)設(shè)置decoding就是在瀏覽器窗口中對(duì)編碼進(jìn)行設(shè)置,這是明確的告訴瀏覽器該Web頁應(yīng)該使用的編碼,用戶永遠(yuǎn)是對(duì)的。

Tomcat 4.0.4是不會(huì)在返回靜態(tài)Web頁設(shè)置響應(yīng)頭中的Content-Type,我們?cè)贘SP中所使用的:

<%@ page="" contenttype="text/html;charset=gb2312">

或在Servlet中使用的:

response.setContentType(“text/html;charset=gb21312”);

就是對(duì)響應(yīng)頭(Response Header)中的Content-Type的設(shè)置,它的值遵循MIME(Multipurpose Internet Mail Extension protocol, 多用途的網(wǎng)際郵件擴(kuò)充協(xié)議)規(guī)范,如圖 3-2,請(qǐng)求JSP頁面http://localhost/scqdac/t.jsp在客戶端收到的所有數(shù)據(jù),0x7d是實(shí)體中有效數(shù)據(jù)的長(zhǎng)度。

J2EE Web組件中中文及相關(guān)問題的示例分析

圖3-2服務(wù)器通過http協(xié)議返回給瀏覽器的所有數(shù)據(jù)

由圖中可以看出,響應(yīng)頭中的Content-Type與HTML中的meta的Content-Type完全無關(guān),這是可以理解的。t.jsp的所有源代碼如下:

<%@ page="" contenttype="text/html;charset=gb2312">

 

JSP文件中的

已經(jīng)沒有什么意義了,沒有誰會(huì)去理會(huì)它。關(guān)于響應(yīng)頭中的Content-Type,RFC2616中有詳細(xì)的定義和說明,請(qǐng)參閱:http://www.ietf.org/rfc/rfc2616.txt。

我們也可以通過設(shè)置Web頁中的HTML元素meta來達(dá)到設(shè)置Web頁編碼的目的:

關(guān)于HTML文檔的字符集(Document Character Set)請(qǐng)參閱《HTML 4.01 Specification》,http://www.w3c.org/TR/html401/html401.html(你同時(shí)還可以了解到HTML元素form的屬性enctype的設(shè)置以及它的作用)。

如果實(shí)在找不到charset及相關(guān)的信息,瀏覽器就使用最近一次使用過的編碼。

在前面提到了瀏覽器的編碼并不完全繼承于decoding,當(dāng)解碼Web頁面所使用的decoding是UTF-16時(shí),向服務(wù)器發(fā)送數(shù)據(jù)的實(shí)體還是使用UTF-8,至少在IE6.0的默認(rèn)設(shè)置下是如此的。還有一個(gè)有趣的就是當(dāng)encoding=ISO8859-1時(shí),請(qǐng)求頭(Request Header Field)

Content-Type:application/x-www-form-urlencoded

時(shí),通過Form向服務(wù)器發(fā)送數(shù)據(jù)“我是中國人”(name=”text”)時(shí),被編碼成:

%26%2325105%3B%26%2326159%3B%26%2320013%3B%26%2322269%3B%

26%2320154%3B

這的確是一種有趣的編碼方式,我們略加分析就可以發(fā)現(xiàn)這個(gè)轉(zhuǎn)義字符串就是

我是中國人

那么在服務(wù)器端我們通過

request.getParameter(“text”);

所得到的字符串也將是”我是中國人”,這明顯是SGML(Standard Generalized Markup Language, 標(biāo)準(zhǔn)通用標(biāo)記語言)所采用的實(shí)體字符嘛,HTML當(dāng)然也就能很好地處理它了,所以如果form屬性action所對(duì)應(yīng)的JSP中有:

<%=request.getparameter(“text”)%>

那么瀏覽器將重現(xiàn)“我是中國人”。所以我們可以由得它,當(dāng)然也可以很容易地處理它,畢竟它是標(biāo)準(zhǔn)的東西。

3.  把字節(jié)串還給我們

服務(wù)器在沒有得到我們的通知的情況下,自我主張地執(zhí)行了類似

String str = new String(bytes,”ISO8859-1”);

的操作,而且還不讓我們能夠直接獲得客戶傳輸?shù)淖止?jié)串(Servlet api中沒有這個(gè)方法)。但我們還是可以讓ServletRequest把字節(jié)串還給我們,那就是執(zhí)行它的逆運(yùn)算,用ISO8859-1編碼:

String str = request.getParameter(“text”);

byte bs[] = str.getBytes(“ISO8859-1”);

這時(shí)所得的bs,我們有足夠的理由相信它完全就是客戶端發(fā)給服務(wù)器的,因?yàn)橛肐SO8859-1對(duì)字節(jié)流解碼,是不會(huì)失真的,它得到的字符串,所有的字符高位字節(jié)都等于0,也就是說用ISO8859-1對(duì)它編碼,也不會(huì)丟失數(shù)據(jù),我們將得到本來的字節(jié)串。

4.  重新解碼

只要我們對(duì)這些字節(jié)串用正確的編碼重新解碼,我們將得到客戶提交的真實(shí)字符,也許它們和客戶端的字符的內(nèi)碼不同,但絕對(duì)是相同的字符。

String str = request.getParameter(“text”);

byte bs[] = str.getBytes(“ISO8859-1”);

String text = new String(bs, ”GBK”);

當(dāng)然最簡(jiǎn)單和有效的莫過于:

request.setCharacterEncoding(“GBK”);

String text = request.getParameter(“text”);

有時(shí)我們?cè)趯W(xué)習(xí)中沒有使用String的第二個(gè)參數(shù),直接使用

String text = new String(bs);

其實(shí)是我們系統(tǒng)的缺省編碼是GBK,而String正是引用了這個(gè)缺省編碼。

也許在這個(gè)時(shí)候,我們才真正地感覺到,如果能夠知道客戶端瀏覽器使用了什么編碼,那將是多么愉快的事,可是我們不能。不要指望ServletRequest.getCharacterEncoding()能給你帶來什么,如果沒有在服務(wù)器端明確使用ServletRequest對(duì)象的方法:setCharacterEncoding(String encoding)設(shè)置該對(duì)象所描述的請(qǐng)求中的數(shù)據(jù)的編碼,那么該對(duì)象的getCharacterEncoding()將返回null,而我們認(rèn)為的完美組合:

request.setCharacterEncoding(request. getCharacterEncoding());

不管getCharacterEncoding()有沒有幫助,都是沒有意義的——你本就是從我這里知道的,我還用得著你告訴我么。

既然決定瀏覽器編碼的六種方法中,有三種都可以被服務(wù)器所使用(但我們的確不屑于用第一種方法,盡管在IE面前它是最有效的)。如果向服務(wù)器提交數(shù)據(jù)的表單是包含在一個(gè)靜態(tài)Web頁面中的,那么我們就設(shè)置HTML元素meta的屬性,如果該表單是包含在JSP的,我們就設(shè)置page指令中的contentType。那么在處理該表單所提交的數(shù)據(jù)時(shí),我們可以用相應(yīng)的編碼對(duì)字節(jié)串重解碼。但不要大意,這種方法并不是可完全信任的,因?yàn)槲覀兊挠脩艨赡苁褂昧肆N方法中的第二種方法重置了瀏覽器的編碼,幸運(yùn)的是如果Web頁中的不是所有的信息都是英文字符的話,用戶還是不會(huì)無聊地執(zhí)行這種非法操作,除非他真的想得到亂碼。

感謝各位的閱讀!關(guān)于“J2EE Web組件中中文及相關(guān)問題的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI