<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    tbwshc

    解決jsp參數(shù)傳遞亂碼的問(wèn)題

    計(jì)算機(jī)生于美國(guó),英語(yǔ)是他的母語(yǔ),而英語(yǔ)以外的其它語(yǔ)言對(duì)他來(lái)說(shuō)都是外語(yǔ)。他跟我們一樣,不管外語(yǔ)掌握到什么程度,也不會(huì)像母語(yǔ)那樣使用得那么好,時(shí)常也會(huì)出一些“拼寫(xiě)錯(cuò)誤”問(wèn)題。
     

         亂碼的出現(xiàn)根本原因在于編碼和解碼使用了不同的編碼方案。比如用GBK編碼的文件,用UTF-8去解碼結(jié)果肯定都是火星文。所以要解決這個(gè)問(wèn)題,中心思想就在于使用統(tǒng)一的編碼方案。

     

         jsp頁(yè)面間的參數(shù)傳遞有以下幾種方式:1、表單(form)的提交。2、直接使用URL后接參數(shù)的形式(超級(jí)鏈接)。3、如果兩個(gè)jsp頁(yè)面在兩個(gè)不同的窗口中,并且這兩個(gè)窗口是父子的關(guān)系,子窗口中的jsp也可以使用javascript和DOM(window.opener.XXX.value)來(lái)取得父窗口中的jsp的輸入元素的值。下面就前兩種方式中出現(xiàn)的亂碼問(wèn)題做一下剖析。

     

         1、表單(form)的提交實(shí)現(xiàn)參數(shù)頁(yè)面間的傳遞

         在介紹表單傳遞參數(shù)的內(nèi)容之前,先來(lái)了解一些預(yù)備知識(shí)。表單的提交方式和請(qǐng)求報(bào)文中對(duì)漢字的處理。

     

         表單的提交方式:

         通常使用的表單的提交方式主要是:post和get兩種。兩者的區(qū)別在于:post方式是把數(shù)據(jù)內(nèi)容放在請(qǐng)求的數(shù)據(jù)正文部分,沒(méi)有長(zhǎng)度的限制;get方式則是把數(shù)據(jù)內(nèi)容直接跟在請(qǐng)求的頭部的URL后面,有長(zhǎng)度的限制。下面是同一個(gè)頁(yè)面兩種方式的請(qǐng)求報(bào)許文。

    Requesttest.jsp代碼 
    <%@ page language="java" contentType="text/html; charset=UTF-8" 
        pageEncoding="UTF-8"%>  
    <!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>Insert title here</title>  
    </head>  
    <body>  
    <%-- post方式提交表單 --%>  
    <form action="http://localhost:8888/EncodingTest/requestresult.jsp" method="post">  
        UserName:<input type="text" name="username"/>  
        Password:<input type="password" name="password"/>  
        <input type="submit" value="Submit">  
    </form>  
    </body>  
    </html> 
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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>Insert title here</title> </head> <body> <%-- post方式提交表單 --%> <form action="http://localhost:8888/EncodingTestb/requestresult.jsp" method="post"> UserName:<input type="text" name="username"/> Password:<input type="password" name="password"/> <input type="submit" value="Submit"> </form> </body> </html>
          在上面的請(qǐng)求頁(yè)面的username輸入框里輸入的是“世界杯”三個(gè)漢字,password輸入框中輸入"123"后按下Submit按鈕提交請(qǐng)求。截獲到的請(qǐng)求報(bào)文如下:

    Post方式的請(qǐng)求報(bào)文代碼 
    POST /EncodingTest/requestresult.jsp HTTP/1.1 
    Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*  
    Referer: http://localhost:8080/TomcatJndiTest/requesttest.jsp  
    Accept-Language: zh-cn  
    User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; aff-kingsoft-ciba; .NET CLR 2.0.50727)  
    Content-Type: application/x-www-form-urlencoded  
    Accept-Encoding: gzip, deflate  
    Host: localhost:8888 
    Content-Length: 49 
    Connection: Keep-Alive  
    Cache-Control: no-cache  
     
    username=%E4%B8%96%E7%95%8C%E6%9D%AF&password=123 
    POST /EncodingTest/requestresult.jsp HTTP/1.1 Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* Referer: http://localhost:8080/TomcatJndiTest/requesttest.jsp Accept-Language: zh-cn User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; aff-kingsoft-ciba; .NET CLR 2.0.50727) Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate Host: localhost:8888 Content-Length: 49 Connection: Keep-Alive Cache-Control: no-cache username=%E4%B8%96%E7%95%8C%E6%9D%AF&password=123
          以上報(bào)文內(nèi)容,可以看出post方式的請(qǐng)求報(bào)文是有專(zhuān)門(mén)的數(shù)據(jù)部的。,

          下面的同一請(qǐng)求頁(yè)面的get提交方式的請(qǐng)求報(bào)文:

    Get方式的請(qǐng)求報(bào)文代碼 
    GET /EncodingTest/requestresult.jsp?username=%E4%B8%96%E7%95%8C%E6%9D%AF&password=123 HTTP/1.1 
    Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*  
    Referer: http://localhost:8080/TomcatJndiTest/requesttest.jsp  
    Accept-Language: zh-cn  
    User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; aff-kingsoft-ciba; .NET CLR 2.0.50727)  
    Accept-Encoding: gzip, deflate  
    Host: localhost:8888 
    Connection: Keep-Alive 
    GET /EncodingTest/requestresult.jsp?username=%E4%B8%96%E7%95%8C%E6%9D%AF&password=123 HTTP/1.1 Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* Referer: http://localhost:8080/TomcatJndiTest/requesttest.jsp Accept-Language: zh-cn User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; aff-kingsoft-ciba; .NET CLR 2.0.50727) Accept-Encoding: gzip, deflate Host: localhost:8888 Connection: Keep-Alive
         以上報(bào)文內(nèi)容,可以看出get方式的請(qǐng)求報(bào)文沒(méi)有專(zhuān)門(mén)的數(shù)據(jù)部,數(shù)據(jù)是直接跟在url的后面。

     

           請(qǐng)求報(bào)文中對(duì)漢字的處理:

           從上面兩種報(bào)文可以看出頁(yè)面上輸入的“世界杯”三個(gè)漢字被替換成了"%E4%B8%96%E7%95%8C%E6%9D%AF”這樣一個(gè)字符串,然后發(fā)給服務(wù)器的。看到這,可能會(huì)有兩個(gè)問(wèn)題:?jiǎn)栴}一、這個(gè)字符串是什么?問(wèn)題二、為什么要做這樣的替換?

     

          這個(gè)字符串是“世界杯”這三個(gè)漢字對(duì)應(yīng)的"UTF-8”編碼"E4B896E7958CE69DAF"在每個(gè)字節(jié)前追加一個(gè)"%"后形成的。至于為什么要做這樣的轉(zhuǎn)化,我的理解是:因?yàn)檎?qǐng)求報(bào)文會(huì)以"ISO-8859-1"的編碼方式編碼后,通過(guò)網(wǎng)絡(luò)流的方式傳送到服務(wù)器端。"ISO-8859-1"僅支持?jǐn)?shù)字、英文字母和一些特殊字符,所以像漢字等這樣的字符"ISO-8859-1"是不認(rèn)識(shí)的。所以就必須先給這些"ISO-8859-1"不支持的字符做個(gè)“整形”手術(shù)。這樣才能正確的將頁(yè)面上的信息傳送到服務(wù)器端。

     

          這時(shí)可能又會(huì)有另外一個(gè)問(wèn)題:上面的例子中為什么會(huì)選用"UTF-8"編碼,其它的編碼方案可以嗎?答案是可以的。在jsp頁(yè)面代碼的頭部有這樣一段代碼"<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>"其中charset的值就是瀏覽器在提交請(qǐng)求報(bào)文前,對(duì)請(qǐng)求報(bào)文做“整形”手術(shù)時(shí)用的字符集,同是也是瀏覽器解釋服務(wù)器的響應(yīng)頁(yè)面時(shí)的字符集。

     

          在了解了以上內(nèi)容后,開(kāi)始剖析表單方式傳遞參數(shù)的亂碼問(wèn)題。

          以上例為例,點(diǎn)擊"Submit"按鈕后,瀏覽器將做完“整形”手術(shù)后的請(qǐng)求報(bào)文發(fā)送給WEB服務(wù)器上的Servlet容器,容器在收到這個(gè)請(qǐng)求報(bào)文后,會(huì)解析這個(gè)請(qǐng)求報(bào)文并用這個(gè)報(bào)文的信息生成一個(gè)HttpServletRequest對(duì)象,然后將這個(gè)HttpServletRequest對(duì)象傳給這個(gè)頁(yè)面所要請(qǐng)求的jsp或Servlet(上例中為"requestresult.jsp")。在這個(gè)被請(qǐng)求的jsp或Servlet(上例中為"requestresult.jsp")中,使用HttpServletRequest對(duì)象的getParameter("")方法來(lái)取得上一頁(yè)面?zhèn)鱽?lái)的參數(shù)。默認(rèn)情況下,這一方法使用的是"ISO-8859-1"來(lái)解碼,所以對(duì)于英文或數(shù)字的參數(shù)值自然能正確取得,但對(duì)于漢字這樣的字符是解不出來(lái)的,因?yàn)槟菐讉€(gè)漢字曾經(jīng)做過(guò)“整形”手術(shù),已經(jīng)認(rèn)不出來(lái)了。要想再把它們認(rèn)出來(lái),那就得要把手術(shù)的主刀醫(yī)生找到,然后再做一次“還原”手術(shù)。下面提供的幾個(gè)方案,可用于不同的情況。

     

    方案一代碼 
    <%String str = new String(request.getParameter("username").getBytes("ISO-8859-1"),"utf-8"); %>  
    Username:<%=str %> 
    <%String str = new String(request.getParameter("username").getBytes("ISO-8859-1"),"utf-8"); %> Username:<%=str %>
          既然request.getParameter("username")默認(rèn)情況下返回的字符串是用"ISO-8859-1"解出來(lái)的,那就先把這個(gè)不可辨認(rèn)的字符串再用"ISO-8859-1"來(lái)打散,也就是:request.getParameter("username").getBytes("ISO-8859-1")。最后再用跟你的頁(yè)面的charset一致的字符集來(lái)重組這個(gè)字符串:new String(request.getParameter("username").getBytes("ISO-8859-1"),"utf-8")。這樣就能見(jiàn)到它的廬山真面目了。

     

          方案一是一種比較萬(wàn)能的方法,不管是post還是get都適用,但可以看出它的缺點(diǎn)是:對(duì)于每個(gè)可能出現(xiàn)漢字的參數(shù)都要顯示的做這么一段處理。一個(gè)兩個(gè)還行,要是很多的話(huà),那就應(yīng)該考慮一下是不是可以選用下一種方案。

      

    方案二代碼 
    <%request.setCharacterEncoding("UTF-8"); %> 
    <%request.setCharacterEncoding("UTF-8"); %>
          方案二是在頁(yè)面的最開(kāi)始或者是在該頁(yè)面中使用的第一個(gè)request.getParameter("")方法之前加上上述一段代碼,它的作用是用作為參數(shù)傳入的編碼集去覆蓋request對(duì)象中的默認(rèn)的"ISO-8859-1"編碼集。這樣request.getParameter("")方法就會(huì)用新的編碼集去解碼,因?yàn)?UTF-8"支持中文,所以作為參數(shù)傳過(guò)來(lái)的“世界杯”三個(gè)漢字就能正確的接收到了。但關(guān)于request.setCharacterEncoding("")方法,API文檔中有如下的說(shuō)明:

     

          Overrides the name of the character encoding used in the body of this request. This method must be called prior to reading request parameters or reading input using getReader(). Otherwise, it has no effectb.

     

          所以方案二只對(duì)post方式提交的請(qǐng)求有效,因?yàn)閰?shù)都在request的body區(qū)。而對(duì)get方式提交的請(qǐng)求則是無(wú)效的,這時(shí)你會(huì)發(fā)現(xiàn)同樣的做法但顯示的還是亂碼。所以你的請(qǐng)求要是是以get方式提交的話(huà),那你還是乖乖的選用方案一吧!

     

          從上面的敘述可以知道,方案二需要在每個(gè)頁(yè)面的前頭加上<%request.setCharacterEncoding("UTF-8"); %>這段代碼,這樣做是不是也挺累的,所以我們想到了使用過(guò)濾器來(lái)幫助我們做這件事兒,那就清爽、簡(jiǎn)單多了。

    Encodingfilter代碼 
    public class EncodingFilter implements Filter {  
          
        private String charset;  
        @Override  
        public void destroy() {  
            // TODO Auto-generated method stub  
        }  
     
        @Override  
        public void doFilter(ServletRequest request, ServletResponse response,  
                FilterChain chain) throws IOException, ServletException {  
            //用init方法取得的charset覆蓋被攔截下來(lái)的request對(duì)象的charset  
            request.setCharacterEncoding(this.charset);  
            //將請(qǐng)求移交給下一下過(guò)濾器,如果還有的情況下。  
            chain.doFilter(request, response);  
        }  
     
        @Override  
        public void init(FilterConfig config) throws ServletException {  
            //從web.xml中的filter的配制信息中取得字符集  
            this.charset = config.getInitParameter("charset");  
        }  

    public class EncodingFilter implements Filter { private String charset; @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //用init方法取得的charset覆蓋被攔截下來(lái)的request對(duì)象的charset request.setCharacterEncoding(this.charset); //將請(qǐng)求移交給下一下過(guò)濾器,如果還有的情況下。 chain.doFilter(request, response); } @Override public void init(FilterConfig config) throws ServletException { //從web.xml中的filter的配制信息中取得字符集 this.charset = config.getInitParameter("charset"); } }
            要想這個(gè)過(guò)濾器生效,還得到web.xml里加入下面的配制信息。

    Web.xml代碼 
    <filter>  
       <filter-name>EncodingFilter</filter-name>  
       <filter-class>cn.eric.encodingtest.filter.EncodingFilter</filter-class>  
       <init-param>  
           <param-name>charset</param-name>  
           <param-value>UTF-8</param-value>  
       </init-param>  
    </filter>  
    <filter-mapping>  
       <filter-name>EncodingFilter</filter-name>  
       <url-pattern>/*</url-pattern>  
    </filter-mapping> 
    <filter> <filter-name>EncodingFilter</filter-name> <filter-class>cn.eric.encodingtest.filter.EncodingFilter</filter-class> <init-param> <param-name>charset</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
     

            2、直接使用URL后接參數(shù)的形式(超級(jí)鏈接)。

            有些時(shí)候可能會(huì)遇到通過(guò)一個(gè)超級(jí)鏈接來(lái)把參數(shù)傳到下一個(gè)頁(yè)面,而剛好這個(gè)參數(shù)的值有可能會(huì)出現(xiàn)中文的情況。就像下面這樣:

             <a href="./jstlresult.jsp?content=世界杯">Go South Africa

             跟form提交有些不同的是:當(dāng)你點(diǎn)擊這個(gè)超級(jí)鏈接后在瀏覽器的地址欄里看到的是http://localhost:8080/TomcatJndiTest/jstlresult.jsp?content=世界杯,而不是http://localhost:8080/TomcatJndiTest/jstlresult.jsp?content=%E4%B8%96%E7%95%8C%E6%9D%AF

    這里瀏覽器并沒(méi)有幫我們把這個(gè)轉(zhuǎn)化工作搞定,所以這里要自己動(dòng)手,豐衣足食了。做法如下:

            <a href="./jstlresult.jsp?content=<%=java.net.URLEncoder.encode("世界杯","utf-8") %>">Go South Africa

            這樣的話(huà)在第二個(gè)頁(yè)面就能使用<%String str = new String(request.getParameter("content").getBytes("ISO-8859-1"),"utf-8"); %>的方法來(lái)正確的得到這個(gè)參數(shù)值了。

     

            總結(jié)一下:

            1、post提交的方式:使用過(guò)濾器,將到達(dá)頁(yè)面前的request對(duì)象中的字符編碼設(shè)定成跟你頁(yè)面統(tǒng)一的編碼。

            2、get提交的方式:<%String str = new String(request.getParameter("content").getBytes("ISO-8859-1"),"utf-8"); %>這樣的字符串重組的方法。

            3、超級(jí)鏈接方式:先將鏈接url中的漢字用java.net.URLEncoder.encode("paramValue","charset")方法處理一下,下面的做法參照2。

    posted on 2012-06-18 13:28 chen11-1 閱讀(6956) 評(píng)論(3)  編輯  收藏

    Feedback

    # re: 解決jsp參數(shù)傳遞亂碼的問(wèn)題[未登錄](méi) 2012-09-07 14:43 a

    果然有人  回復(fù)  更多評(píng)論   

    # re: 解決jsp參數(shù)傳遞亂碼的問(wèn)題 2014-04-28 09:49 visitor

    非常不錯(cuò),感謝分享  回復(fù)  更多評(píng)論   

    # re: 解決jsp參數(shù)傳遞亂碼的問(wèn)題 2014-12-23 14:06 額外

    問(wèn)問(wèn)  回復(fù)  更多評(píng)論   


    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产精品免费大片| 99久久免费国产精品特黄| 亚洲国产天堂在线观看| 国产乱子精品免费视观看片| 亚洲国产成人精品激情| 亚洲国产成人精品女人久久久| 免费在线观看一级片| 亚洲中字慕日产2020| 无码不卡亚洲成?人片| 免费成人在线视频观看| 亚洲中文无码mv| 亚洲精品午夜无码电影网| 岛国片在线免费观看| 男女作爱在线播放免费网站| 亚洲高清中文字幕免费| 国产精品亚洲一区二区三区在线| 成年男女免费视频网站| 999zyz**站免费毛片| 亚洲成aⅴ人片久青草影院按摩| 久久精品国产精品亚洲色婷婷| 在线观看成人免费| 一级毛片全部免费播放| 亚洲av乱码一区二区三区按摩 | 成人最新午夜免费视频| 国产精品九九久久免费视频| 亚洲乱码中文论理电影| 亚洲精品一品区二品区三品区| 国产免费看插插插视频| 无码少妇精品一区二区免费动态| 美女免费视频一区二区三区| 亚洲国语在线视频手机在线| 久久精品国产亚洲AV不卡| 大学生高清一级毛片免费| 18成禁人视频免费网站| 中文在线免费看视频| 美女免费视频一区二区三区| 自拍日韩亚洲一区在线| 日韩精品亚洲人成在线观看| 久久99亚洲综合精品首页| 国产精品成人免费综合| 97无码免费人妻超级碰碰夜夜 |