Servlet接收JSP引數亂碼問題解決辦法
 
環境:
apache-tomcat-6.0.24.zip
jdk1.6.0_16
WindosXP 簡體中文版
Netbeans6.8
 
目標:
解決Servlet接收到JSP傳遞的引數後亂碼問題,亂碼發生在Servlet一方。
 
JSP向Serlvet傳遞引數有兩種方式,一種是GET方式,另一種是POST方式,為了解決亂碼問題,必須對這兩種方式工作原理有個深刻理解才行。
 
這裡先寫一個簡單的JSP(工程所有的原始碼檔案編碼均為GBK),裡面有兩種提交引數的方式:
<%@page contentType=”text/html” pageEncoding=”GBK”%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”
     “http://www.w3.org/TR/html4/loose.dtd”>

<html>
        <head>
                <meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
                <title>JSP Page</title>
        </head>
        <body>
                <h1>頁面提交中文測試!</h1>
                <h2>GET方式</h2>
                <a href=”/testweb/TestServlet?param=中文”>GET方式提交中文測試</a>
                <h2>POST方式</h2>
                <form action=”/testweb/TestServlet” method=”post”>
                        <input type=”text” name=”param” value=”中文”/>
                        <button type=”submit” name=”提交中文引數測試” value=”提交中文引數測試”/>
                </form>
        </body>
</html>

 
然後定義一個Servlet接收提交的引數。
 
這裡強調一點,在此使用的tomcat沒有經過任何的修改與配置。
當頁面通過兩種方式請求Servlet的時候,引數的編碼原本為GBK,在通過HTTP服務將請求傳送出去的時候,會將引數重新按照ISO-8859-1編碼後傳送。因此,不管GET或POST方式,Servlet接收到的引數資料的編碼均為ISO-8859-1,必須重新轉碼為GBK,才能正確顯示中文引數。
 
 
1、GET方式的請求與接收過程
頁面中引數“param=中文”的編碼原本為GBK,當用GET方式傳送引數的時候,引數值會被Web伺服器從GBK轉碼為ISO-8859-1。
Servlet接收到的GET請求引數的編碼當然為ISO-8859-1了,對於中文肯定顯示不了,因此要將ISO-8859-1轉換為GBK就可以正常顯示中文了。
                String param = request.getParameter(“param”);
                String x = new String(param.getBytes(“ISO-8859-1”), “GBK”);
                System.out.println(“GET方式獲取的中文引數值:” + x);
 
 
2、POST方式請求與接收過程
頁面中引數“param=中文”的編碼原本為GBK,當點選頁面中提交按鈕後,引數會以GBK編碼格式傳送給Servlet,因此Servlet接收引數的時候必須將請求的編碼明確設定為GBK,這樣才能正確接收中文。
                request.setCharacterEncoding(“GBK”);
                String param = request.getParameter(“param”);
                System.out.println(“POST方式獲取的中文引數值:” + param);
 
或者,可以按照get方式來接收post的引數:
                String param = request.getParameter(“param”);
                String x = new String(param.getBytes(“ISO-8859-1”), “GBK”);
                System.out.println(“GET方式獲取的中文引數值:” + x);
 
 
疑問:為什麼在GET方式下不設定請求的編碼格式呢?原因是GET方式使用的編碼為ISO-8859-1,用GBK、UTF-8等接收效果都是一樣的(都是一堆字母和符號),編不編都一個樣,如果指定ISO-8859-1編碼是多一翻手續,如果指定了非ISO-8859-1編碼,是腦子還不清醒,沒搞明白這個原理,因此,GET方式就不要指定請求的編碼了。
 
下面看看Servlet的寫法:
package jweb.lavasoft;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DealPageParamServlet extends HttpServlet {

        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException {
                String param = request.getParameter(“param”);
                String x = new String(param.getBytes(“ISO-8859-1”), “GBK”);
                System.out.println(“GET方式獲取的中文引數值:” + x);
        }

        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                        throws ServletException, IOException {
                request.setCharacterEncoding(“GBK”);
                String param = request.getParameter(“param”);
                System.out.println(“POST方式獲取的中文引數值:” + param);
        }
}

 
其實,只要搞明白了編碼過程,遇到亂碼問題就能從容應對了。
常常見到有人遇到亂碼了,就開始修改Tocmat的server.xml的配置檔案,或者新增過濾器等等,糊里糊塗搞,大多數情況問題都能解決掉,其實也僅僅是個瞎貓逮住個死耗子。