Tomcat在處理GET和POST請(qǐng)求時(shí)產(chǎn)生的亂碼問(wèn)題
本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝
有個(gè)朋友寫(xiě)JSP程序時(shí),在Servlet中取請(qǐng)求參數(shù)時(shí)出現(xiàn)了亂碼,當(dāng)然,這種亂碼問(wèn)題再簡(jiǎn)單不過(guò)了。由于在JSP中使用了GBK作用頁(yè)面的編碼,那么提交的中文信息自然也會(huì)被按著GBK進(jìn)行編碼,為%xx格式的GBK編碼。
要解決這個(gè)問(wèn)題可以說(shuō)是方法多多。最簡(jiǎn)單的就是使用request.setCharacterEncoding方法設(shè)置編碼格式,如下面的代碼所示:
request.setCharacterEncoding("GBK");
在設(shè)置完編碼格式之后,就可以直接通過(guò)request.getParameter方法來(lái)獲得請(qǐng)求參數(shù)中的中文信息了。當(dāng)然,為了方便,還可以在過(guò)濾器中加入上面的語(yǔ)句,這樣所有的Servlet都可以直接使用 request.getParameter方法來(lái)獲得請(qǐng)求參數(shù)中的中文信息了。 除了這兩種方法,還可以不使用request.setCharacterEncoding("GBK"),而使用下面的語(yǔ)言來(lái)轉(zhuǎn)換編碼:
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
但為了更快解決這個(gè)問(wèn)題,我就直接告訴這位朋友使用了setCharacterEncoding方法來(lái)設(shè)置編碼。但是說(shuō)來(lái)奇怪,還是出現(xiàn)亂碼,沒(méi)有任何解決問(wèn)題的跡象。 最郁悶的事就是使用了自己認(rèn)為100%能解決問(wèn)題的方法,而這種方法卻一點(diǎn)都沒(méi)起作用。
最后又讓朋友試了最后一種方法,說(shuō)來(lái)奇怪,竟然好使了。當(dāng)然,這也沒(méi)什么可奇怪的,本來(lái)就應(yīng)該好使,但奇就奇在setCharacterEncoding方法并沒(méi)有去掉,也就是說(shuō),同時(shí)使用了下面兩條語(yǔ)句,竟然得到了正常的中文請(qǐng)求參數(shù)值:
按著常理來(lái)說(shuō),這是不可能的,既然使用了setCharacterEncoding方法設(shè)置成了GBK,再使用new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK")來(lái)轉(zhuǎn)換,得到的應(yīng)該是?????,不可能是正常的中文,只有將setCharacterEncoding方法去了,以ISO-8859-1格式保存的字符串才可以用ISO-8859-1格式還原,再用GBK重新保存成Java字符串(這一步實(shí)際上就是GBK轉(zhuǎn)Unicode)。
但經(jīng)過(guò)仔細(xì)思考后,決定看下JSP代碼是如何寫(xiě)的。不看不知道,一看嚇一跳,原來(lái)<form>在提交時(shí)使用的是GET,而未用POST,這當(dāng)然沒(méi)什么了不起的,用什么都可以,但對(duì)編碼就有問(wèn)題了。自從Tomcat5.x開(kāi)始,GET和POST方法提交的信息,Tomcat采用了不同的方式來(lái)處理編碼,對(duì)于POST請(qǐng)求,Tomcat會(huì)仍然使用request.setCharacterEncoding方法所設(shè)置的編碼來(lái)處理,如果未設(shè)置,則使用默認(rèn)的iso-8859-1編碼。而GET請(qǐng)求則不同,Tomcat對(duì)于GET請(qǐng)求并不會(huì)考慮使用request.setCharacterEncoding方法設(shè)置的編碼,而會(huì)永遠(yuǎn)使用iso-8859-1編碼,而這位朋友使用的正好是GET請(qǐng)求,因此,tomcat將會(huì)使用iso-8859-1將提交的字節(jié)轉(zhuǎn)換成字符串。
解決的方法有兩個(gè):
1. 將GET請(qǐng)求改成POST請(qǐng)求,然后就可以使用request.setCharacterEncoding方法設(shè)置編碼,并使用request.getParameter方法直接獲得中文請(qǐng)求參數(shù)了。
2. 不用改GET請(qǐng)求,在Servlet中使用如下的代碼來(lái)得到中文請(qǐng)求參數(shù)。
綜上所述,如果使用了GET請(qǐng)求,則setCharacterEncoding方法不起作用,只能使用上面的代碼來(lái)解決,而使用POST請(qǐng)求,盡管setCharacterEncoding方法起作用,但使用上面的代碼仍然好使(在這時(shí)不能使用setCharacterEncoding方法將編碼格式設(shè)置成非iso-8859-1格式)。因此,如果想讓Servlet可以同時(shí)處理GET和POST請(qǐng)求中的中文信息,除了判斷這兩種方法外,還可以使用上面的代碼來(lái)同時(shí)處理這兩種請(qǐng)求的中文信息。
筆者建議使用如下的代碼來(lái)獲得中文請(qǐng)求參數(shù):
因?yàn)樯厦娴拇a是利用了Java的編碼能力,對(duì)于所有的Web服務(wù)器都會(huì)有效,而setCharacterEncoding方法是通過(guò)Web服務(wù)器支持的,并不是所有的Web服務(wù)器都會(huì)對(duì)該方法有很好的支持。
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining
有個(gè)朋友寫(xiě)JSP程序時(shí),在Servlet中取請(qǐng)求參數(shù)時(shí)出現(xiàn)了亂碼,當(dāng)然,這種亂碼問(wèn)題再簡(jiǎn)單不過(guò)了。由于在JSP中使用了GBK作用頁(yè)面的編碼,那么提交的中文信息自然也會(huì)被按著GBK進(jìn)行編碼,為%xx格式的GBK編碼。
要解決這個(gè)問(wèn)題可以說(shuō)是方法多多。最簡(jiǎn)單的就是使用request.setCharacterEncoding方法設(shè)置編碼格式,如下面的代碼所示:
request.setCharacterEncoding("GBK");
在設(shè)置完編碼格式之后,就可以直接通過(guò)request.getParameter方法來(lái)獲得請(qǐng)求參數(shù)中的中文信息了。當(dāng)然,為了方便,還可以在過(guò)濾器中加入上面的語(yǔ)句,這樣所有的Servlet都可以直接使用 request.getParameter方法來(lái)獲得請(qǐng)求參數(shù)中的中文信息了。 除了這兩種方法,還可以不使用request.setCharacterEncoding("GBK"),而使用下面的語(yǔ)言來(lái)轉(zhuǎn)換編碼:
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
但為了更快解決這個(gè)問(wèn)題,我就直接告訴這位朋友使用了setCharacterEncoding方法來(lái)設(shè)置編碼。但是說(shuō)來(lái)奇怪,還是出現(xiàn)亂碼,沒(méi)有任何解決問(wèn)題的跡象。 最郁悶的事就是使用了自己認(rèn)為100%能解決問(wèn)題的方法,而這種方法卻一點(diǎn)都沒(méi)起作用。
最后又讓朋友試了最后一種方法,說(shuō)來(lái)奇怪,竟然好使了。當(dāng)然,這也沒(méi)什么可奇怪的,本來(lái)就應(yīng)該好使,但奇就奇在setCharacterEncoding方法并沒(méi)有去掉,也就是說(shuō),同時(shí)使用了下面兩條語(yǔ)句,竟然得到了正常的中文請(qǐng)求參數(shù)值:
request.setCharacterEncoding("GBK");
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
System.out.println(name); // 正常輸出中文請(qǐng)求參數(shù)
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
System.out.println(name); // 正常輸出中文請(qǐng)求參數(shù)
按著常理來(lái)說(shuō),這是不可能的,既然使用了setCharacterEncoding方法設(shè)置成了GBK,再使用new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK")來(lái)轉(zhuǎn)換,得到的應(yīng)該是?????,不可能是正常的中文,只有將setCharacterEncoding方法去了,以ISO-8859-1格式保存的字符串才可以用ISO-8859-1格式還原,再用GBK重新保存成Java字符串(這一步實(shí)際上就是GBK轉(zhuǎn)Unicode)。
但經(jīng)過(guò)仔細(xì)思考后,決定看下JSP代碼是如何寫(xiě)的。不看不知道,一看嚇一跳,原來(lái)<form>在提交時(shí)使用的是GET,而未用POST,這當(dāng)然沒(méi)什么了不起的,用什么都可以,但對(duì)編碼就有問(wèn)題了。自從Tomcat5.x開(kāi)始,GET和POST方法提交的信息,Tomcat采用了不同的方式來(lái)處理編碼,對(duì)于POST請(qǐng)求,Tomcat會(huì)仍然使用request.setCharacterEncoding方法所設(shè)置的編碼來(lái)處理,如果未設(shè)置,則使用默認(rèn)的iso-8859-1編碼。而GET請(qǐng)求則不同,Tomcat對(duì)于GET請(qǐng)求并不會(huì)考慮使用request.setCharacterEncoding方法設(shè)置的編碼,而會(huì)永遠(yuǎn)使用iso-8859-1編碼,而這位朋友使用的正好是GET請(qǐng)求,因此,tomcat將會(huì)使用iso-8859-1將提交的字節(jié)轉(zhuǎn)換成字符串。
解決的方法有兩個(gè):
1. 將GET請(qǐng)求改成POST請(qǐng)求,然后就可以使用request.setCharacterEncoding方法設(shè)置編碼,并使用request.getParameter方法直接獲得中文請(qǐng)求參數(shù)了。
2. 不用改GET請(qǐng)求,在Servlet中使用如下的代碼來(lái)得到中文請(qǐng)求參數(shù)。
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
綜上所述,如果使用了GET請(qǐng)求,則setCharacterEncoding方法不起作用,只能使用上面的代碼來(lái)解決,而使用POST請(qǐng)求,盡管setCharacterEncoding方法起作用,但使用上面的代碼仍然好使(在這時(shí)不能使用setCharacterEncoding方法將編碼格式設(shè)置成非iso-8859-1格式)。因此,如果想讓Servlet可以同時(shí)處理GET和POST請(qǐng)求中的中文信息,除了判斷這兩種方法外,還可以使用上面的代碼來(lái)同時(shí)處理這兩種請(qǐng)求的中文信息。
筆者建議使用如下的代碼來(lái)獲得中文請(qǐng)求參數(shù):
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
因?yàn)樯厦娴拇a是利用了Java的編碼能力,對(duì)于所有的Web服務(wù)器都會(huì)有效,而setCharacterEncoding方法是通過(guò)Web服務(wù)器支持的,并不是所有的Web服務(wù)器都會(huì)對(duì)該方法有很好的支持。
《Android開(kāi)發(fā)完全講義(第2版)》(本書(shū)版權(quán)已輸出到臺(tái)灣)
http://product.dangdang.com/product.aspx?product_id=22741502
《Android高薪之路:Android程序員面試寶典 》http://book.360buy.com/10970314.html
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining
posted on 2008-09-05 15:48 銀河使者 閱讀(3066) 評(píng)論(8) 編輯 收藏 所屬分類: java 、web 、 原創(chuàng)