国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Servlet第四篇【request對象常用方法、應(yīng)用】

raise_yang / 1270人閱讀

摘要:瀏覽器的中文數(shù)據(jù)提交給服務(wù)器,以編碼對中文編碼,當(dāng)我在讀取數(shù)據(jù)的時候,拿到的當(dāng)然是亂碼。接下來使用方式傳遞中文數(shù)據(jù),把表單的方式改成即可當(dāng)我們訪問的時候,又出現(xiàn)亂碼了于是我按照上面的方式,把對象設(shè)置編碼為試試結(jié)果還是亂碼。

什么是HttpServletRequest
HttpServletRequest對象代表客戶端的請求,當(dāng)客戶端通過HTTP協(xié)議訪問服務(wù)器時,HTTP請求頭中的所有信息都封裝在這個對象中,開發(fā)人員通過這個對象的方法,可以獲得客戶這些信息。

簡單來說,要得到瀏覽器信息,就找HttpServletRequest對象

HttpServletRequest常用方法 獲得客戶機(jī)【瀏覽器】信息

getRequestURL方法返回客戶端發(fā)出請求時的完整URL。

getRequestURI方法返回請求行中的資源名部分。

getQueryString 方法返回請求行中的參數(shù)部分。

getPathInfo方法返回請求URL中的額外路徑信息。額外路徑信息是請求URL中的位于Servlet的路徑之后和查詢參數(shù)之前的內(nèi)容,它以“/”開頭。

getRemoteAddr方法返回發(fā)出請求的客戶機(jī)的IP地址

getRemoteHost方法返回發(fā)出請求的客戶機(jī)的完整主機(jī)名

getRemotePort方法返回客戶機(jī)所使用的網(wǎng)絡(luò)端口號

getLocalAddr方法返回WEB服務(wù)器的IP地址。

getLocalName方法返回WEB服務(wù)器的主機(jī)名

獲得客戶機(jī)請求頭

getHeader方法

getHeaders方法

getHeaderNames方法

獲得客戶機(jī)請求參數(shù)(客戶端提交的數(shù)據(jù))

getParameter方法

getParameterValues(String name)方法

getParameterNames方法

getParameterMap方法

HttpServletRequest應(yīng)用 防盜鏈

什么是防盜鏈呢?比如:我現(xiàn)在有海賊王最新的資源,想要看海賊王的要在我的網(wǎng)頁上看?,F(xiàn)在別的網(wǎng)站的人看到我有海賊王的資源,想要把我的資源粘貼在他自己的網(wǎng)站上。這樣我獨(dú)家的資源就被一個CTRL+C和CTRL+V搶走了?而反盜鏈就是不能被他們CRTL+C和CRTL+V

下面我模擬一下場景?,F(xiàn)在我首頁先有一個超鏈接,指向著海賊王最新資源

當(dāng)我點(diǎn)進(jìn)去,就能看到海賊王最新資源了

其他的人可以通過復(fù)制粘貼我的地址,放到它們的網(wǎng)頁上

這樣我就劃不來啦【我的廣告你來沒看呢!】。想要看我的資源,就必須經(jīng)過我的首頁點(diǎn)進(jìn)去看。

想要實(shí)現(xiàn)這樣的效果,就要獲取Referer這個消息頭,判斷Referer是不是從我的首頁來的。如果不是從我的首頁來的,跳轉(zhuǎn)回我的首頁。

        //獲取到網(wǎng)頁是從哪里來的
        String referer = request.getHeader("Referer");

        //如果不是從我的首頁來或者從地址欄直接訪問的,
        if ( referer == null || !referer.contains("localhost:8080/zhongfucheng/index.jsp") ) {

            //回到首頁去
            response.sendRedirect("/zhongfucheng/index.jsp");
            return;
        }

        //能執(zhí)行下面的語句,說明是從我的首頁點(diǎn)擊進(jìn)來的,那沒問題,照常顯示
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("路飛做了XXXXxxxxxxxxxxxxxxxx");

首先按正常預(yù)想的,別人從首頁點(diǎn)擊我的資源,訪問我海賊王最新的資源

能夠成功訪問到資源

如果我在瀏覽器直接輸入地址【此時Referer是為null的】,我們來看看

跳回到首頁上,不能訪問到海賊王資源

再試試,如果別人粘貼了我的資源url,在它的網(wǎng)頁上掛了一個網(wǎng)址呢。

在別人網(wǎng)頁上點(diǎn)擊的時候

又跳回到了我的首頁了。

表單提交數(shù)據(jù)【通過post方式提交數(shù)據(jù)】
用戶名
密碼
性別
愛好 游泳 跑步 飛翔
你的來自于哪里
詳細(xì)說明:

在Servlet111中獲取到提交的數(shù)據(jù),代碼如下

        //設(shè)置request字符編碼的格式
        request.setCharacterEncoding("UTF-8");

        //通過html的name屬性,獲取到值
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String gender = request.getParameter("gender");

        //復(fù)選框和下拉框有多個值,獲取到多個值
        String[] hobbies = request.getParameterValues("hobbies");
        String[] address = request.getParameterValues("address");

        //獲取到文本域的值
        String description = request.getParameter("textarea");

        //得到隱藏域的值
        String hiddenValue = request.getParameter("aaa");

        ....各種System.out.println().......

向表單輸入數(shù)據(jù)

Servlet111得到表單帶過來的數(shù)據(jù),最后的一個數(shù)據(jù)是隱藏域帶過來的。

超鏈接方式提交數(shù)據(jù)

常見的get方式提交數(shù)據(jù)有使用超鏈接,sendRedirect()

格式如下:

    sendRedirect("servlet的地址?參數(shù)名="+參數(shù)值 &"參數(shù)名="+參數(shù)值);

我們來使用一下,通過超鏈接將數(shù)據(jù)帶給瀏覽器

     使用超鏈接將數(shù)據(jù)帶給瀏覽器

在Servlet111接收數(shù)據(jù)

        //接收以username為參數(shù)名帶過來的值
        String username = request.getParameter("username");
        System.out.println(username);

注意看瀏覽器左下角

服務(wù)器成功接收到瀏覽器發(fā)送過來的數(shù)據(jù)

并且,傳輸數(shù)據(jù)明文的出現(xiàn)在瀏覽器的地址欄上

sendRedirect()和超鏈接類似,在這里就不贅述了

解決中文亂碼問題

細(xì)心的朋友會發(fā)現(xiàn),我在獲取表單數(shù)據(jù)的時候,有這句代碼request.setCharacterEncoding("UTF-8");,如果沒有這句代碼,會發(fā)生什么事呢?我們看看。

再重新填寫數(shù)據(jù)

在服務(wù)器查看提交過來的數(shù)據(jù),所有的中文數(shù)據(jù)都亂碼了

來這里我們來分析一下亂碼的原因,在前面的博客中我已經(jīng)介紹了,Tomcat服務(wù)器默認(rèn)編碼是ISO 8859-1,而瀏覽器使用的是UTF-8編碼。瀏覽器的中文數(shù)據(jù)提交給服務(wù)器,Tomcat以ISO 8859-1編碼對中文編碼,當(dāng)我在Servlet讀取數(shù)據(jù)的時候,拿到的當(dāng)然是亂碼。而我設(shè)置request的編碼為UTF-8,亂碼就解決了。

接下來使用get方式傳遞中文數(shù)據(jù),把表單的方式改成get即可

當(dāng)我們訪問的時候,又出現(xiàn)亂碼了!

于是我按照上面的方式,把request對象設(shè)置編碼為UTF-8試試

        request.setCharacterEncoding("UTF-8");
        String name = request.getParameter("name");

結(jié)果還是亂碼。這是為什么呢?我明明已經(jīng)把編碼設(shè)置成UTF-8了,按照post方式,亂碼問題已經(jīng)解決了!。我們來看看get和post方式的區(qū)別在哪?為什么post方式設(shè)置了request編碼就可以解決亂碼問題,而get方式不能呢。

首先我們來看一下post方法是怎么進(jìn)行參數(shù)傳遞的。當(dāng)我們點(diǎn)擊提交按鈕的時候,數(shù)據(jù)封裝進(jìn)了Form Data中,http請求中把實(shí)體主體帶過去了【傳輸?shù)臄?shù)據(jù)稱之為實(shí)體主體】,既然request對象封裝了http請求,所以request對象可以解析到發(fā)送過來的數(shù)據(jù),于是只要把編碼設(shè)置成UTF-8就可以解決亂碼問題了。

而get方式不同,它的數(shù)據(jù)是從消息行帶過去的,沒有封裝到request對象里面,所以使用request設(shè)置編碼是無效的。

要解決get方式亂碼問題也不難,我們既然知道Tomcat默認(rèn)的編碼是ISO 8859-1,那么get方式由消息體帶過去給瀏覽器的時候肯定是用ISO 8859-1編碼了。

        //此時得到的數(shù)據(jù)已經(jīng)是被ISO 8859-1編碼后的字符串了,這個是亂碼
        String name = request.getParameter("username");

        //亂碼通過反向查ISO 8859-1得到原始的數(shù)據(jù)
        byte[] bytes = name.getBytes("ISO8859-1");

        //通過原始的數(shù)據(jù),設(shè)置正確的碼表,構(gòu)建字符串
        String value = new String(bytes, "UTF-8");

上面的代碼有些難理解,我畫張圖說明一下:

經(jīng)過我們手工轉(zhuǎn)換,再來訪問一下

好的,成功解決掉亂碼問題了。

除了手工轉(zhuǎn)換,get方式還可以改Tomcat服務(wù)器的配置來解決亂碼,但是不推薦使用,這樣不靈活。

我們都知道Tomcat默認(rèn)的編碼是ISO 8859-1,如果在Tomcat服務(wù)器的配置下改成是UTF-8的編碼,那么就解決服務(wù)器在解析數(shù)據(jù)的時候造成亂碼問題了

在8080端口的Connector上加入URIEncoding="utf-8",設(shè)置Tomcat的訪問該端口時的編碼為utf-8,從而解決亂碼,這種改法是固定使用UTF-8編碼的

    

設(shè)置了編碼后,沒有做任何手工轉(zhuǎn)換,成功拿到數(shù)據(jù)

、

當(dāng)然也有另一種改服務(wù)器編碼的方式。設(shè)置Tomcat的訪問該端口時的編碼為頁面的編碼,這種改法是隨著頁面的編碼而變

    

設(shè)置編碼為UTF-8

        request.setCharacterEncoding("UTF-8");
        String name = request.getParameter("name");

再次訪問

手寫超鏈接如果附帶中文參數(shù)問題,要URL重寫,在JSP博客中會講到

總結(jié):

post方式直接改request對象的編碼

get方式需要手工轉(zhuǎn)換編碼

get方式也可以修改Tomcat服務(wù)器的編碼,不推薦,因?yàn)闀蕾嚪?wù)器了!

提交數(shù)據(jù)能用post就用post

實(shí)現(xiàn)轉(zhuǎn)發(fā)

之前講過使用response的sendRedirect()可以實(shí)現(xiàn)重定向,做到的功能是頁面跳轉(zhuǎn),使用request的getRequestDispatcher.forward(request,response)實(shí)現(xiàn)轉(zhuǎn)發(fā),做到的功能也是頁面跳轉(zhuǎn),他們有什么區(qū)別呢?現(xiàn)在我先來說下轉(zhuǎn)發(fā)

代碼如下所示

        //獲取到requestDispatcher對象,跳轉(zhuǎn)到index.jsp
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/index.jsp");

        //調(diào)用requestDispatcher對象的forward()實(shí)現(xiàn)轉(zhuǎn)發(fā),傳入request和response方法
        requestDispatcher.forward(request, response);

訪問Servlet111

上面已經(jīng)說了,可以通過sendRedirect()重定向可以在資源尾部添加參數(shù)提交數(shù)據(jù)給服務(wù)器。那么轉(zhuǎn)發(fā)能不能提交數(shù)據(jù)給服務(wù)器呢?

答案明顯是可以的,并且使用這種方法非常頻繁

在講ServletContext的時候,曾經(jīng)說過Servlet之間可以通過ServletContext實(shí)現(xiàn)通訊,ServletContext也能稱之為域?qū)ο?/strong>。而request也可以稱之為域?qū)ο?/strong>,只不過ServletContext的域是整個web應(yīng)用,而request的域僅僅代表一次http請求

下面我們來使用request實(shí)現(xiàn)Servlet之間的通訊,Servlet111代碼

        //以username為關(guān)鍵字存zhongfucheng值
        request.setAttribute("username", "zhongfucheng");

        //獲取到requestDispatcher對象
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Servlet222");

        //調(diào)用requestDispatcher對象的forward()實(shí)現(xiàn)轉(zhuǎn)發(fā),傳入request和response方法
        requestDispatcher.forward(request, response);

Servlet222代碼

        //獲取到存進(jìn)request對象的值
        String userName = (String) request.getAttribute("username");

        //在瀏覽器輸出該值
        response.getWriter().write("i am :"+userName);

訪問Servlet111看下效果

如上圖所示,Servlet222成功拿到了request對象在Servlet111存進(jìn)的數(shù)據(jù)

現(xiàn)在問題又來了,我們可以使用ServletContext和request實(shí)現(xiàn)Servlet之間的通訊,那么我們用哪一種呢?一般的原則:可以使用request就盡可能使用request。因?yàn)镾ervletContext代表著整個web應(yīng)用,使用ServletContext會消耗大量的資源,而request對象會隨著請求的結(jié)束而結(jié)束,資源會被回收。使用request域進(jìn)行Servlet之間的通訊在開發(fā)中是非常頻繁的

轉(zhuǎn)發(fā)的時序圖

請求轉(zhuǎn)發(fā)的細(xì)節(jié)

如果在調(diào)用forward方法之前,在Servlet程序中寫入的部分內(nèi)容已經(jīng)被真正地傳送到了客戶端,forward方法將拋出IllegalStateException異常。 也就是說:不要在轉(zhuǎn)發(fā)之前寫數(shù)據(jù)給瀏覽器

我們來試試是不是真的會出現(xiàn)異常。

        OutputStream outputStream = response.getOutputStream();
        outputStream.write("--------------------------------------------".getBytes());

        //關(guān)閉流,確保讓數(shù)據(jù)到瀏覽器中
        outputStream.close();
        
        //跳轉(zhuǎn)
        request.getRequestDispatcher("/Foot").forward(request, response);

訪問的時候,看到瀏覽器可以輸出數(shù)據(jù),Tomcat后臺拋出了異常

如果在調(diào)用forward方法之前向Servlet引擎的緩沖區(qū)中寫入了內(nèi)容,只要寫入到緩沖區(qū)中的內(nèi)容還沒有被真正輸出到客戶端,forward方法就可以被正常執(zhí)行,原來寫入到輸出緩沖區(qū)中的內(nèi)容將被清空,但是,已寫入到HttpServletResponse對象中的響應(yīng)頭字段信息保持有效。

轉(zhuǎn)發(fā)和重定向的區(qū)別 實(shí)際發(fā)生位置不同,地址欄不同

轉(zhuǎn)發(fā)是發(fā)生在服務(wù)器的

轉(zhuǎn)發(fā)是由服務(wù)器進(jìn)行跳轉(zhuǎn)的,細(xì)心的朋友會發(fā)現(xiàn),在轉(zhuǎn)發(fā)的時候,瀏覽器的地址欄是沒有發(fā)生變化的,在我訪問Servlet111的時候,即使跳轉(zhuǎn)到了Servlet222的頁面,瀏覽器的地址還是Servlet111的。也就是說瀏覽器是不知道該跳轉(zhuǎn)的動作,轉(zhuǎn)發(fā)是對瀏覽器透明的。通過上面的轉(zhuǎn)發(fā)時序圖我們也可以發(fā)現(xiàn),實(shí)現(xiàn)轉(zhuǎn)發(fā)只是一次的http請求,一次轉(zhuǎn)發(fā)中request和response對象都是同一個。這也解釋了,為什么可以使用request作為域?qū)ο筮M(jìn)行Servlet之間的通訊。

重定向是發(fā)生在瀏覽器的

重定向是由瀏覽器進(jìn)行跳轉(zhuǎn)的,進(jìn)行重定向跳轉(zhuǎn)的時候,瀏覽器的地址會發(fā)生變化的。曾經(jīng)介紹過:實(shí)現(xiàn)重定向的原理是由response的狀態(tài)碼和Location頭組合而實(shí)現(xiàn)的。這是由瀏覽器進(jìn)行的頁面跳轉(zhuǎn)實(shí)現(xiàn)重定向會發(fā)出兩個http請求,request域?qū)ο笫菬o效的,因?yàn)樗皇峭粋€request對象

用法不同

很多人都搞不清楚轉(zhuǎn)發(fā)和重定向的時候,資源地址究竟怎么寫。有的時候要把應(yīng)用名寫上,有的時候不用把應(yīng)用名寫上。很容易把人搞暈。記住一個原則:給服務(wù)器用的直接從資源名開始寫,給瀏覽器用的要把應(yīng)用名寫上

request.getRequestDispatcher("/資源名 URI").forward(request,response)

轉(zhuǎn)發(fā)時"/"代表的是本應(yīng)用程序的根目錄【zhongfucheng】

response.send("/web應(yīng)用/資源名 URI");

重定向時"/"代表的是webapps目錄

能夠去往的URL的范圍不一樣

轉(zhuǎn)發(fā)是服務(wù)器跳轉(zhuǎn)只能去往當(dāng)前web應(yīng)用的資源

重定向是瀏覽器跳轉(zhuǎn),可以去往任何的資源

傳遞數(shù)據(jù)的類型不同

轉(zhuǎn)發(fā)的request對象可以傳遞各種類型的數(shù)據(jù),包括對象

重定向只能傳遞字符串

跳轉(zhuǎn)的時間不同

轉(zhuǎn)發(fā)時:執(zhí)行到跳轉(zhuǎn)語句時就會立刻跳轉(zhuǎn)

重定向:整個頁面執(zhí)行完之后才執(zhí)行跳轉(zhuǎn)

轉(zhuǎn)發(fā)和重定向使用哪一個?

根據(jù)上面說明了轉(zhuǎn)發(fā)和重定向的區(qū)別也可以很容易概括出來。轉(zhuǎn)發(fā)是帶著轉(zhuǎn)發(fā)前的請求的參數(shù)的。重定向是新的請求。

典型的應(yīng)用場景:

轉(zhuǎn)發(fā): 訪問 Servlet 處理業(yè)務(wù)邏輯,然后 forward 到 jsp 顯示處理結(jié)果,瀏覽器里 URL 不變

重定向: 提交表單,處理成功后 redirect 到另一個 jsp,防止表單重復(fù)提交,瀏覽器里 URL 變了

RequestDispatcher再說明

RequestDispatcher對象調(diào)用forward()可以實(shí)現(xiàn)轉(zhuǎn)發(fā)上面已經(jīng)說過了。RequestDispatcher還有另外一個方法include(),該方法可以實(shí)現(xiàn)包含,有什么用呢?

我們在寫網(wǎng)頁的時候,一般網(wǎng)頁的頭部和尾部是不需要改變的。如果我們多個地方使用Servlet輸出網(wǎng)頭和網(wǎng)尾的話,需要把代碼重新寫一遍。而使用RequestDispatcher的include()方法就可以實(shí)現(xiàn)包含網(wǎng)頭和網(wǎng)尾的效果了。

我們來操作吧!現(xiàn)在我有網(wǎng)頭和網(wǎng)尾的Servlet

使用Servlet111將網(wǎng)頭和網(wǎng)尾包含

        request.getRequestDispatcher("/Head").include(request, response);

        response.getWriter().write("--------------------------------------------");


        request.getRequestDispatcher("/Foot").include(request, response);

訪問一下Servlet111,成功把網(wǎng)頭和網(wǎng)尾包含了

如果文章有錯的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號:Java3y

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68442.html

相關(guān)文章

  • Java3y文章目錄導(dǎo)航

    摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號:Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...

    KevinYan 評論0 收藏0
  • 一起來學(xué)SpringBoot | 四篇:整合Thymeleaf模板

    摘要:在使用上述模板,默認(rèn)從下加載。介紹是現(xiàn)代化服務(wù)器端的模板引擎,不同與其它幾種模板的是的語法更加接近,并且具有很高的擴(kuò)展性。特點(diǎn)支持無網(wǎng)絡(luò)環(huán)境下運(yùn)行,由于它支持原型,然后在標(biāo)簽里增加額外的屬性來達(dá)到模板數(shù)據(jù)的展示方式。 SpringBoot 是為了簡化 Spring 應(yīng)用的創(chuàng)建、運(yùn)行、調(diào)試、部署等一系列問題而誕生的產(chǎn)物,自動裝配的特性讓我們可以更好的關(guān)注業(yè)務(wù)本身而不是外部的XML配置,...

    TZLLOG 評論0 收藏0
  • JSP四篇【EL表達(dá)式介紹、獲取各類數(shù)據(jù)、11個內(nèi)置對象、執(zhí)行運(yùn)算、回顯數(shù)據(jù)、自定義函數(shù)、fn方法

    什么是EL表達(dá)式? 表達(dá)式語言(Expression Language,EL),EL表達(dá)式是用${}括起來的腳本,用來更方便的讀取對象! EL表達(dá)式主要用來讀取數(shù)據(jù),進(jìn)行內(nèi)容的顯示! 為什么要使用EL表達(dá)式? 為什么要使用EL表達(dá)式,我們先來看一下沒有EL表達(dá)式是怎么樣讀取對象數(shù)據(jù)的吧! 在1.jsp中設(shè)置了Session屬性 向session設(shè)置一個屬性 在2...

    flyer_dev 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<