這篇文章給大家分享的是有關(guān)J2EE Web組件中中文及相關(guān)問題的示例分析的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
創(chuàng)新互聯(lián)公司是專業(yè)的湟中網(wǎng)站建設(shè)公司,湟中接單;提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行湟中網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊,希望更多企業(yè)前來合作!
XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />
三、 向服務(wù)器發(fā)送中文
雖然大家一般都不用JSP甚至servlet來處理處理客戶提交的數(shù)據(jù)或訪問請求參數(shù),但JSP的使用或更新總是比Servlet或 JavaBean來得方便(至少在tomcat 4.0.4中是如此,因為我們常常不得不為修改了Servlet或JavaBean而重啟服務(wù)器),所以在這里我們還是要用JSP來訪問請求參數(shù)了。
不管是在JSP還是在Servlet中,我們都是用ServletRequest(或其子類)的方法getParameter(String name)來訪問請求參數(shù)的,這個方法返回的是String,也就是說我們能得到的是已經(jīng)對Inte.NET傳來的字節(jié)流解碼所得的字符串。如果服務(wù)器能對這些字節(jié)流進(jìn)行正確的解碼,那將是件完美的事。其實說來也很簡單,要做到這一點只需要服務(wù)器知道這些字節(jié)流在客戶端是用什么編碼進(jìn)行編碼也就行了。如圖 2-17我們希望decoding==encoding。
圖 3-1 數(shù)據(jù)從瀏覽器到服務(wù)器
可理想與現(xiàn)實往往是沒有交集的,我們怎么也不能讓服務(wù)器知道這些字節(jié)到底是用什么編碼被編碼的,即使在萬維網(wǎng)相關(guān)技術(shù)的主要設(shè)計組織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ù)器知道這個編碼是什么(如果你知道該怎么做,一定請記得告訴我),所以在缺省情況下,Tomcat 4.0.4又一廂情愿的用起了ISO8859-1來對客戶端提交的數(shù)據(jù)進(jìn)行解碼。如圖 2-17,decoding=ISO8859-1,可如果encoding!=ISO8859-1呢,很明顯這就是一個數(shù)據(jù)錯誤傳輸了。注意,我們這里所講的數(shù)據(jù),僅僅是客戶端給服務(wù)器發(fā)送的數(shù)據(jù)中的實體(Entity Body)中的數(shù)據(jù)。
1. 誰決定了Encoding
誰決定了瀏覽器的當(dāng)前Web頁通過Form向Internet(最終的對象當(dāng)然是服務(wù)器)發(fā)送數(shù)據(jù)字節(jié)流的編碼呢?當(dāng)然是瀏覽器了。那瀏覽器又是靠什么決定這個編碼的呢?那是繼承的瀏覽器解碼當(dāng)前頁(它當(dāng)然也要對當(dāng)前Web頁解碼了,別忘了任何文件或Internet上的元數(shù)據(jù)都是字節(jié))所使用的decoding了,其實說是繼承也不全對,后面你就會發(fā)現(xiàn)的。
2. 靠什么決定了Encoding
大約是這六個方面來的信息使瀏覽器決定用什么encoding:
1) xsl所決定的
2) 實體(Entity Body)中的特殊標(biāo)記
3) 用戶手動對該Web頁設(shè)置的decoding
4) 響應(yīng)頭(Response Header Field)中的Content-Type
5) HTML元素META中的charset
6) 瀏覽器以前所用的decoding
它們的優(yōu)先級可能會因為瀏覽器的不同而不同,但在IE6.0中是遞減的,微軟這種做法確實曖昧、耐人尋味,難怪它會在瀏覽器大戰(zhàn)中取得勝利。下面僅對這六點一一解釋。
XSL(eXtensible Stylesheet Language, 可擴(kuò)展樣式單語言)可以方便地將XML(eXtensible Markup Language, 可擴(kuò)展標(biāo)記語言)轉(zhuǎn)換為其他很多種內(nèi)容,我們這里只關(guān)心它把XML轉(zhuǎn)換為HTML,而對瀏覽器編碼設(shè)置的影響。如果該XSL遵循 W3C在1998年發(fā)布的有關(guān)XSL的第一個工作草案標(biāo)準(zhǔn)(設(shè)置XSL文件中的xmlns:xsl="http://www.w3.org/TR/WD-xsl"),則可以通過在XSL中添加元素meta,并作相類似的設(shè)置達(dá)到設(shè)置瀏覽器編碼的目的:
如果該XSL是事實上的XSLT(eXtensible Stylesheet Language Transformation, 可擴(kuò)展樣式單轉(zhuǎn)換語言),即xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”,則瀏覽器編碼無條件使用UTF=16,即使在XSL文件中添加meta元素來設(shè)置編碼都將被忽略。
實體是指服務(wù)器給瀏覽器返回的數(shù)據(jù)中的實體,也可以簡單理解為返回數(shù)據(jù)中除附加頭和空白行之外的所有數(shù)據(jù)。在前面說過,windows 2000 Server(我實驗所用的操作系統(tǒng))會在以UTF-8編碼的文件前加三個流氓字節(jié)(0xEF0xBB0xBF),如果當(dāng)前Web頁是靜態(tài)資源,則服務(wù)器會不加任何處理直接把這個Web 頁返回到客戶端,如果這個靜態(tài)Web頁也是在Windows 2000 Server中生成的話,那么實體的最初三個字節(jié)將是0xEF0xBB0xBF,瀏覽器很快檢測到這三個字節(jié),于是就用UTF-8對正確解碼,后面那四點都會被忽略。
手動設(shè)置decoding就是在瀏覽器窗口中對編碼進(jìn)行設(shè)置,這是明確的告訴瀏覽器該Web頁應(yīng)該使用的編碼,用戶永遠(yuǎn)是對的。
Tomcat 4.0.4是不會在返回靜態(tài)Web頁設(shè)置響應(yīng)頭中的Content-Type,我們在JSP中所使用的:
<%@ page="" contenttype="text/html;charset=gb2312">
或在Servlet中使用的:
response.setContentType(“text/html;charset=gb21312”);
就是對響應(yīng)頭(Response Header)中的Content-Type的設(shè)置,它的值遵循MIME(Multipurpose Internet Mail Extension protocol, 多用途的網(wǎng)際郵件擴(kuò)充協(xié)議)規(guī)范,如圖 3-2,請求JSP頁面http://localhost/scqdac/t.jsp在客戶端收到的所有數(shù)據(jù),0x7d是實體中有效數(shù)據(jù)的長度。
圖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)沒有什么意義了,沒有誰會去理會它。關(guān)于響應(yīng)頭中的Content-Type,RFC2616中有詳細(xì)的定義和說明,請參閱:http://www.ietf.org/rfc/rfc2616.txt。
我們也可以通過設(shè)置Web頁中的HTML元素meta來達(dá)到設(shè)置Web頁編碼的目的:
關(guān)于HTML文檔的字符集(Document Character Set)請參閱《HTML 4.01 Specification》,http://www.w3c.org/TR/html401/html401.html(你同時還可以了解到HTML元素form的屬性enctype的設(shè)置以及它的作用)。
如果實在找不到charset及相關(guān)的信息,瀏覽器就使用最近一次使用過的編碼。
在前面提到了瀏覽器的編碼并不完全繼承于decoding,當(dāng)解碼Web頁面所使用的decoding是UTF-16時,向服務(wù)器發(fā)送數(shù)據(jù)的實體還是使用UTF-8,至少在IE6.0的默認(rèn)設(shè)置下是如此的。還有一個有趣的就是當(dāng)encoding=ISO8859-1時,請求頭(Request Header Field)
Content-Type:application/x-www-form-urlencoded
時,通過Form向服務(wù)器發(fā)送數(shù)據(jù)“我是中國人”(name=”text”)時,被編碼成:
%26%2325105%3B%26%2326159%3B%26%2320013%3B%26%2322269%3B%
26%2320154%3B
這的確是一種有趣的編碼方式,我們略加分析就可以發(fā)現(xiàn)這個轉(zhuǎn)義字符串就是
我是中國人
那么在服務(wù)器端我們通過
request.getParameter(“text”);
所得到的字符串也將是”我是中國人”,這明顯是SGML(Standard Generalized Markup Language, 標(biāo)準(zhǔn)通用標(biāo)記語言)所采用的實體字符嘛,HTML當(dāng)然也就能很好地處理它了,所以如果form屬性action所對應(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中沒有這個方法)。但我們還是可以讓ServletRequest把字節(jié)串還給我們,那就是執(zhí)行它的逆運算,用ISO8859-1編碼:
String str = request.getParameter(“text”);
byte bs[] = str.getBytes(“ISO8859-1”);
這時所得的bs,我們有足夠的理由相信它完全就是客戶端發(fā)給服務(wù)器的,因為用ISO8859-1對字節(jié)流解碼,是不會失真的,它得到的字符串,所有的字符高位字節(jié)都等于0,也就是說用ISO8859-1對它編碼,也不會丟失數(shù)據(jù),我們將得到本來的字節(jié)串。
4. 重新解碼
只要我們對這些字節(jié)串用正確的編碼重新解碼,我們將得到客戶提交的真實字符,也許它們和客戶端的字符的內(nèi)碼不同,但絕對是相同的字符。
String str = request.getParameter(“text”);
byte bs[] = str.getBytes(“ISO8859-1”);
String text = new String(bs, ”GBK”);
當(dāng)然最簡單和有效的莫過于:
request.setCharacterEncoding(“GBK”);
String text = request.getParameter(“text”);
有時我們在學(xué)習(xí)中沒有使用String的第二個參數(shù),直接使用
String text = new String(bs);
其實是我們系統(tǒng)的缺省編碼是GBK,而String正是引用了這個缺省編碼。
也許在這個時候,我們才真正地感覺到,如果能夠知道客戶端瀏覽器使用了什么編碼,那將是多么愉快的事,可是我們不能。不要指望ServletRequest.getCharacterEncoding()能給你帶來什么,如果沒有在服務(wù)器端明確使用ServletRequest對象的方法:setCharacterEncoding(String encoding)設(shè)置該對象所描述的請求中的數(shù)據(jù)的編碼,那么該對象的getCharacterEncoding()將返回null,而我們認(rèn)為的完美組合:
request.setCharacterEncoding(request. getCharacterEncoding());
不管getCharacterEncoding()有沒有幫助,都是沒有意義的——你本就是從我這里知道的,我還用得著你告訴我么。
既然決定瀏覽器編碼的六種方法中,有三種都可以被服務(wù)器所使用(但我們的確不屑于用第一種方法,盡管在IE面前它是最有效的)。如果向服務(wù)器提交數(shù)據(jù)的表單是包含在一個靜態(tài)Web頁面中的,那么我們就設(shè)置HTML元素meta的屬性,如果該表單是包含在JSP的,我們就設(shè)置page指令中的contentType。那么在處理該表單所提交的數(shù)據(jù)時,我們可以用相應(yīng)的編碼對字節(jié)串重解碼。但不要大意,這種方法并不是可完全信任的,因為我們的用戶可能使用了六種方法中的第二種方法重置了瀏覽器的編碼,幸運的是如果Web頁中的不是所有的信息都是英文字符的話,用戶還是不會無聊地執(zhí)行這種非法操作,除非他真的想得到亂碼。
感謝各位的閱讀!關(guān)于“J2EE Web組件中中文及相關(guān)問題的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!