spring的filter與tomcat的get和post

lastwinner發表於2008-02-18
使用Tomcat 5.0.20,我們使用Form submit 的資料將會以ISO8859-1處理,我們必須自己將字串轉換為GB2312/GBK(簡體中文),在web程式中,對所有的 request.getParameter("xx"); 作了 toGBKString() 的處理,發現還是出現了中文問題,中文還是可能變成亂碼! 
經過分析,發現問題出在 QueryString的處理上,在使用 Tomcat 4.x時,對於 SUBMIT 時無論採用 GET or POST,Tomcat server 對 parameters 的處理都採用ISO8859-1處理,但在 Tomcat 5.x 版,將get請求獨立出來,如果Form 的 Method 採用 GET 及或者在 URL 上的寫中文,上傳到 Tomcat時,無論如何轉碼,都是亂碼,即使使用 URLEncode結果也一樣。
透過研究tomcat的文件可以找到解決辦法,在$TOMCAT_HOME/webapps/tomcat-docs/config/http.html 中寫道
URIEncoding:

This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used. 

useBodyEncodingForURI:

This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitely set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false
以上 Tomcat 引數,是設定在 server.xml 中的 http 中,必須設定這兩個引數其中之一。
URIEncoding 設定為 URIEncoding="ISO-8859-1" 指定為 "ISO-8859-1" 編碼,讓 QueryString 的編碼與 post body 相同。
useBodyEncodingForURI 用來相容 Tomcat 4.x 版的,值是 "true" or "false",指 "要不要讓 QueryString 與 POST BODY 採用相同的編碼 ",設成 true,就可以做到 "ISO-8859-1" 編碼。 
建議採用 URIEncoding 的設定,因為 useBodyEncodingForURI是為了相容 Tomcat 4.X。不過按照原文的說明,這兩個引數都不設,Tomcat 也應該採用 "ISO-8859-1" 的編碼,為什末還是有問題呢?
只好看 Tomcat Source Code了
在org.apache.tomcat.util.http.Parameters類,Tomcat用來處理QueryString,
private String urlDecode(ByteChunk bc, String enc)
        throws IOException {
        if( urlDec==null ) {
            urlDec=new UDecoder();   
        }
        urlDec.convert(bc);
        String result = null;
        if (enc != null) {
            bc.setEncoding(enc);
            result = bc.toString();
        } else {
            CharChunk cc = tmpNameC;
            cc.allocate(bc.getLength(), -1);
            // Default encoding: fast conversion
            byte[] bbuf = bc.getBuffer();
            char[] cbuf = cc.getBuffer();
            int start = bc.getStart();
            for (int i = 0; i                 cbuf[i] = (char) (bbuf[i + start] & 0xff);
            }
            cc.setChars(cbuf, 0, bc.getLength());
            result = cc.toString();
            cc.recycle();
        }
        return result;
    }
    tomcat處理 QueryString時,如果沒有設定 encode,並沒有採用 ISO-8859-1 的編碼,而是用 fast conversion 來處理,才會造成中文問題,所以必須在 Server.xml 中加上 URLEncoding 的引數才行.
    Connector 的設定
    
    所以在使用 Tomcat 4 透過 GET or POST 的方式傳引數時,通常都是使用 Filter 的方式解決中文傳引數的問題。
但是到了 Tomcat 5.0.20 之後,解決中文傳引數的問題,就必須考慮是使用 GET or POST,兩種的方式不同。
使用 GET 的方式 
String name = new String((request.getParameter("name")).getBytes("ISO-8859-1"),"GBK");
使用 POST 的方式
request.setCharacterEncoding("GBK");

如果設定URIEncoding="UTF-8"和使用 IE, 設定總是以 UTF8傳送URL,你還可以用spring的filter與tomcat的get和post

使用Filter的處理 :先判斷是使用那種方式( GET or POST),假若是用 GET 的方式就採用第一個;若使用POST 方式,就採用第二個

HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if (httpServletRequest.getMethod().equals("POST")) 
{        request.setCharacterEncoding("UTF-8");} 
else if (httpServletRequest.getMethod().equals("GET"))
 {
         //進行處理
 }
 注意spring的filter病沒有解決這個問題,以下是他的程式碼
protected void doFilterInternal(
   HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
   throws ServletException, IOException {
  
  if (this.forceEncoding || request.getCharacterEncoding() == null) {
   request.setCharacterEncoding(this.encoding);
  }
  filterChain.doFilter(request, response);
 }

 來源:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29867/viewspace-174280/,如需轉載,請註明出處,否則將追究法律責任。

相關文章