要解決這個問題可以說是方法多多。最簡單的就是使用request.setCharacterEncoding方法設置編碼格式,如下面的代碼所示:
request.setCharacterEncoding("GBK");
在設置完編碼格式之後,就可以直接通過request.getParameter方法來獲得請求參數中的中文信息了。當然,爲了方便,還可以在過濾器中加入上面的語句,這樣所有的Servlet都可以直接使用 request.getParameter方法來獲得請求參數中的中文信息了。 除了這兩種方法,還可以不使用request.setCharacterEncoding("GBK"),而使用下面的語言來轉換編碼:
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
但爲了更快解決這個問題,我就直接告訴這位朋友使用了setCharacterEncoding方法來設置編碼。但是說來奇怪,還是出現亂碼,沒有任何解決問題的跡象。 最鬱悶的事就是使用了自己認爲100%能解決問題的方法,而這種方法卻一點都沒起作用。
最後又讓朋友試了最後一種方法,說來奇怪,竟然好使了。當然,這也沒什麼可奇怪的,本來就應該好使,但奇就奇在setCharacterEncoding方法並沒有去掉,也就是說,同時使用了下面兩條語句,竟然得到了正常的中文請求參數值:
request.setCharacterEncoding("GBK");
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
System.out.println(name); // 正常輸出中文請求參數
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
System.out.println(name); // 正常輸出中文請求參數
按着常理來說,這是不可能的,既然使用了setCharacterEncoding方法設置成了GBK,再使用new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK")來轉換,得到的應該是?????,不可能是正常的中文,只有將setCharacterEncoding方法去了,以ISO-8859-1格式保存的字符串纔可以用ISO-8859-1格式還原,再用GBK重新保存成Java字符串(這一步實際上就是GBK轉Unicode)。
但經過仔細思考後,決定看下JSP代碼是如何寫的。不看不知道,一看嚇一跳,原來<form>在提交時使用的是GET,而未用POST,這當然沒什麼了不起的,用什麼都可以,但對編碼就有問題了。自從Tomcat5.x開始,GET和POST方法提交的信息,Tomcat採用了不同的方式來處理編碼,對於POST請求,Tomcat會仍然使用request.setCharacterEncoding方法所設置的編碼來處理,如果未設置,則使用默認的iso-8859-1編碼。而GET請求則不同,Tomcat對於GET請求並不會考慮使用request.setCharacterEncoding方法設置的編碼,而會永遠使用iso-8859-1編碼,而這位朋友使用的正好是GET請求,因此,tomcat將會使用iso-8859-1將提交的字節轉換成字符串。
解決的方法有兩個:
1. 將GET請求改成POST請求,然後就可以使用request.setCharacterEncoding方法設置編碼,並使用request.getParameter方法直接獲得中文請求參數了。
2. 不用改GET請求,在Servlet中使用如下的代碼來得到中文請求參數。
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
綜上所述,如果使用了GET請求,則setCharacterEncoding方法不起作用,只能使用上面的代碼來解決,而使用POST請求,儘管setCharacterEncoding方法起作用,但使用上面的代碼仍然好使(在這時不能使用setCharacterEncoding方法將編碼格式設置成非iso-8859-1格式)。因此,如果想讓Servlet可以同時處理GET和POST請求中的中文信息,除了判斷這兩種方法外,還可以使用上面的代碼來同時處理這兩種請求的中文信息。
筆者建議使用如下的代碼來獲得中文請求參數:
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "GBK");
因爲上面的代碼是利用了Java的編碼能力,對於所有的Web服務器都會有效,而setCharacterEncoding方法是通過Web服務器支持的,並不是所有的Web服務器都會對該方法有很好的支持。