您現(xiàn)在的位置:首頁(yè) > 綜合 > 特別關(guān)注 > 正文

今日訊!JavaWeb day8 Request和Response快速入門(mén)(下)Response

時(shí)間:2023-02-27 17:12:36    來(lái)源:騰訊云    

Response對(duì)象

前面講解完Request對(duì)象,接下來(lái)我們回到剛開(kāi)始的那張圖:


【資料圖】

在這里插入圖片描述
Request:使用request對(duì)象來(lái)==獲取==請(qǐng)求數(shù)據(jù)Response:使用response對(duì)象來(lái)==設(shè)置==響應(yīng)數(shù)據(jù)

Reponse的繼承體系和Request的繼承體系也非常相似:

在這里插入圖片描述

介紹完Response的相關(guān)體系結(jié)構(gòu)后,接下來(lái)對(duì)于Response我們需要學(xué)習(xí)如下內(nèi)容:

Response設(shè)置響應(yīng)數(shù)據(jù)的功能介紹Response完成重定向Response響應(yīng)字符數(shù)據(jù)Response響應(yīng)字節(jié)數(shù)據(jù)

3.1 Response設(shè)置響應(yīng)數(shù)據(jù)功能介紹

HTTP響應(yīng)數(shù)據(jù)總共分為三部分內(nèi)容,分別是==響應(yīng)行、響應(yīng)頭、響應(yīng)體==,對(duì)于這三部分內(nèi)容的數(shù)據(jù),respone對(duì)象都提供了哪些方法來(lái)進(jìn)行設(shè)置?

響應(yīng)行
在這里插入圖片描述

對(duì)于響應(yīng)頭,比較常用的就是設(shè)置響應(yīng)狀態(tài)碼:

void setStatus(int sc);
響應(yīng)頭
在這里插入圖片描述

設(shè)置響應(yīng)頭鍵值對(duì):

void setHeader(String name,String value);
響應(yīng)體
在這里插入圖片描述

對(duì)于響應(yīng)體,是通過(guò)字符、字節(jié)輸出流的方式往瀏覽器寫(xiě),

獲取字符輸出流:

PrintWriter getWriter();

獲取字節(jié)輸出流

ServletOutputStream getOutputStream();

介紹完這些方法后,后面我們會(huì)通過(guò)案例把這些方法都用一用,首先先來(lái)完成下重定向的功能開(kāi)發(fā)。

3.2 Respones請(qǐng)求重定向

==Response重定向(redirect):一種資源跳轉(zhuǎn)方式。==
在這里插入圖片描述

(1)瀏覽器發(fā)送請(qǐng)求給服務(wù)器,服務(wù)器中對(duì)應(yīng)的資源A接收到請(qǐng)求

(2)資源A現(xiàn)在無(wú)法處理該請(qǐng)求,就會(huì)給瀏覽器響應(yīng)一個(gè)302的狀態(tài)碼+location的一個(gè)訪問(wèn)資源B的路徑

(3)瀏覽器接收到響應(yīng)狀態(tài)碼為302就會(huì)重新發(fā)送請(qǐng)求到location對(duì)應(yīng)的訪問(wèn)地址去訪問(wèn)資源B

(4)資源B接收到請(qǐng)求后進(jìn)行處理并最終給瀏覽器響應(yīng)結(jié)果,這整個(gè)過(guò)程就叫==重定向==

重定向的實(shí)現(xiàn)方式:
resp.setStatus(302);resp.setHeader("location","資源B的訪問(wèn)路徑");

具體如何來(lái)使用,我們先來(lái)看下需求:

在這里插入圖片描述

針對(duì)上述需求,具體的實(shí)現(xiàn)步驟為:

1.創(chuàng)建一個(gè)ResponseDemo1類,接收/resp1的請(qǐng)求,在doGet方法中打印resp1....

2.創(chuàng)建一個(gè)ResponseDemo2類,接收/resp2的請(qǐng)求,在doGet方法中打印resp2....

3.在ResponseDemo1的方法中使用

response.setStatus(302);

response.setHeader("Location","/request-demo/resp2") 來(lái)給前端響應(yīng)結(jié)果數(shù)據(jù)

4.啟動(dòng)測(cè)試

(1)創(chuàng)建ResponseDemo1類

@WebServlet("/resp1")public class ResponseDemo1 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("resp1....");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

(2)創(chuàng)建ResponseDemo2類

@WebServlet("/resp2")public class ResponseDemo2 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("resp2....");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

(3)在ResponseDemo1的doGet方法中給前端響應(yīng)數(shù)據(jù)

@WebServlet("/resp1")public class ResponseDemo1 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("resp1....");        //重定向        //1.設(shè)置響應(yīng)狀態(tài)碼 302        response.setStatus(302);        //2. 設(shè)置響應(yīng)頭 Location        response.setHeader("Location","/request-demo/resp2");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

(4)啟動(dòng)測(cè)試

訪問(wèn)http://localhost:8080/request-demo/resp1,就可以在控制臺(tái)看到如下內(nèi)容:

在這里插入圖片描述

說(shuō)明/resp1/resp2都被訪問(wèn)到了。到這重定向就已經(jīng)完成了。

雖然功能已經(jīng)實(shí)現(xiàn),但是從設(shè)置重定向的兩行代碼來(lái)看,會(huì)發(fā)現(xiàn)除了重定向的地址不一樣,其他的內(nèi)容都是一模一樣,所以request對(duì)象給我們提供了簡(jiǎn)化的編寫(xiě)方式為:

resposne.sendRedirect("/request-demo/resp2")

所以第3步中的代碼就可以簡(jiǎn)化為:

@WebServlet("/resp1")public class ResponseDemo1 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("resp1....");        //重定向        resposne.sendRedirect("/request-demo/resp2");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}
重定向的特點(diǎn)瀏覽器地址欄路徑發(fā)送變化

當(dāng)進(jìn)行重定向訪問(wèn)的時(shí)候,由于是由瀏覽器發(fā)送的兩次請(qǐng)求,所以地址會(huì)發(fā)生變化

在這里插入圖片描述
可以重定向到任何位置的資源(服務(wù)內(nèi)容、外部均可)

因?yàn)榈谝淮雾憫?yīng)結(jié)果中包含了瀏覽器下次要跳轉(zhuǎn)的路徑,所以這個(gè)路徑是可以任意位置資源。

兩次請(qǐng)求,不能在多個(gè)資源使用request共享數(shù)據(jù)

因?yàn)闉g覽器發(fā)送了兩次請(qǐng)求,是兩個(gè)不同的request對(duì)象,就無(wú)法通過(guò)request對(duì)象進(jìn)行共享數(shù)據(jù)

介紹完==請(qǐng)求重定向==和==請(qǐng)求轉(zhuǎn)發(fā)==以后,接下來(lái)需要把這兩個(gè)放在一塊對(duì)比下:

在這里插入圖片描述

以后到底用哪個(gè),還是需要根據(jù)具體的業(yè)務(wù)來(lái)決定。

3.3 路徑問(wèn)題

問(wèn)題1:轉(zhuǎn)發(fā)的時(shí)候路徑上沒(méi)有加/request-demo而重定向加了,那么到底什么時(shí)候需要加,什么時(shí)候不需要加呢?
在這里插入圖片描述

其實(shí)判斷的依據(jù)很簡(jiǎn)單,只需要記住下面的規(guī)則即可:

瀏覽器使用:需要加虛擬目錄(項(xiàng)目訪問(wèn)路徑)服務(wù)端使用:不需要加虛擬目錄

對(duì)于轉(zhuǎn)發(fā)來(lái)說(shuō),因?yàn)槭窃诜?wù)端進(jìn)行的,所以不需要加虛擬目錄

對(duì)于重定向來(lái)說(shuō),路徑最終是由瀏覽器來(lái)發(fā)送請(qǐng)求,就需要添加虛擬目錄。

掌握了這個(gè)規(guī)則,接下來(lái)就通過(guò)一些練習(xí)來(lái)強(qiáng)化下知識(shí)的學(xué)習(xí):

req.getRequestDispatcher("路徑")resp.sendRedirect("路徑")

答案:

1.超鏈接,從瀏覽器發(fā)送,需要加2.表單,從瀏覽器發(fā)送,需要加3.轉(zhuǎn)發(fā),是從服務(wù)器內(nèi)部跳轉(zhuǎn),不需要加4.重定向,是由瀏覽器進(jìn)行跳轉(zhuǎn),需要加。
問(wèn)題2:在重定向的代碼中,/request-demo是固定編碼的,如果后期通過(guò)Tomcat插件配置了項(xiàng)目的訪問(wèn)路徑,那么所有需要重定向的地方都需要重新修改,該如何優(yōu)化?
在這里插入圖片描述

答案也比較簡(jiǎn)單,我們可以在代碼中動(dòng)態(tài)去獲取項(xiàng)目訪問(wèn)的虛擬目錄,具體如何獲取,我們可以借助前面咱們所學(xué)習(xí)的request對(duì)象中的getContextPath()方法,修改后的代碼如下:

@WebServlet("/resp1")public class ResponseDemo1 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("resp1....");        //簡(jiǎn)化方式完成重定向        //動(dòng)態(tài)獲取虛擬目錄        String contextPath = request.getContextPath();        response.sendRedirect(contextPath+"/resp2");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

重新啟動(dòng)訪問(wèn)測(cè)試,功能依然能夠?qū)崿F(xiàn),此時(shí)就可以動(dòng)態(tài)獲取項(xiàng)目訪問(wèn)的虛擬路徑,從而降低代碼的耦合度。

3.4 Response響應(yīng)字符數(shù)據(jù)

要想將字符數(shù)據(jù)寫(xiě)回到瀏覽器,我們需要兩個(gè)步驟:

通過(guò)Response對(duì)象獲取字符輸出流: PrintWriter writer = resp.getWriter();通過(guò)字符輸出流寫(xiě)數(shù)據(jù): writer.write("aaa");

接下來(lái),我們實(shí)現(xiàn)通過(guò)些案例把響應(yīng)字符數(shù)據(jù)給實(shí)際應(yīng)用下:

返回一個(gè)簡(jiǎn)單的字符串aaa
/** * 響應(yīng)字符數(shù)據(jù):設(shè)置字符數(shù)據(jù)的響應(yīng)體 */@WebServlet("/resp3")public class ResponseDemo3 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");        //1. 獲取字符輸出流        PrintWriter writer = response.getWriter(); writer.write("aaa");    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}
在這里插入圖片描述
返回一串html字符串,并且能被瀏覽器解析
PrintWriter writer = response.getWriter();//content-type,告訴瀏覽器返回的數(shù)據(jù)類型是HTML類型數(shù)據(jù),這樣瀏覽器才會(huì)解析HTML標(biāo)簽response.setHeader("content-type","text/html");writer.write("

aaa

");
在這里插入圖片描述

==注意:==一次請(qǐng)求響應(yīng)結(jié)束后,response對(duì)象就會(huì)被銷毀掉,所以不要手動(dòng)關(guān)閉流。

返回一個(gè)中文的字符串你好,需要注意設(shè)置響應(yīng)數(shù)據(jù)的編碼為utf-8
//設(shè)置響應(yīng)的數(shù)據(jù)格式及數(shù)據(jù)的編碼response.setContentType("text/html;charset=utf-8");writer.write("你好");
在這里插入圖片描述

3.3 Response響應(yīng)字節(jié)數(shù)據(jù)

要想將字節(jié)數(shù)據(jù)寫(xiě)回到瀏覽器,我們需要兩個(gè)步驟:

通過(guò)Response對(duì)象獲取字節(jié)輸出流:ServletOutputStream outputStream = resp.getOutputStream();通過(guò)字節(jié)輸出流寫(xiě)數(shù)據(jù): outputStream.write(字節(jié)數(shù)據(jù));

接下來(lái),我們實(shí)現(xiàn)通過(guò)些案例把響應(yīng)字符數(shù)據(jù)給實(shí)際應(yīng)用下:

返回一個(gè)圖片文件到瀏覽器
/** * 響應(yīng)字節(jié)數(shù)據(jù):設(shè)置字節(jié)數(shù)據(jù)的響應(yīng)體 */@WebServlet("/resp4")public class ResponseDemo4 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1. 讀取文件        FileInputStream fis = new FileInputStream("d://a.jpg");        //2. 獲取response字節(jié)輸出流        ServletOutputStream os = response.getOutputStream();        //3. 完成流的copy        byte[] buff = new byte[1024];        int len = 0;        while ((len = fis.read(buff))!= -1){            os.write(buff,0,len);        }        fis.close();    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}
在這里插入圖片描述

上述代碼中,對(duì)于流的copy的代碼還是比較復(fù)雜的,所以我們可以使用別人提供好的方法來(lái)簡(jiǎn)化代碼的開(kāi)發(fā),具體的步驟是:

(1)pom.xml添加依賴

    commons-io    commons-io    2.6

(2)調(diào)用工具類方法

//fis:輸入流//os:輸出流IOUtils.copy(fis,os);

優(yōu)化后的代碼:

/** * 響應(yīng)字節(jié)數(shù)據(jù):設(shè)置字節(jié)數(shù)據(jù)的響應(yīng)體 */@WebServlet("/resp4")public class ResponseDemo4 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //1. 讀取文件        FileInputStream fis = new FileInputStream("d://a.jpg");        //2. 獲取response字節(jié)輸出流        ServletOutputStream os = response.getOutputStream();        //3. 完成流的copy      IOUtils.copy(fis,os);        fis.close();    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doGet(request, response);    }}

關(guān)鍵詞: HTTP 編程算法

上一篇:
下一篇:

凡本網(wǎng)注明“XXX(非中國(guó)微山網(wǎng))提供”的作品,均轉(zhuǎn)載自其它媒體,轉(zhuǎn)載目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)和其真實(shí)性負(fù)責(zé)。

特別關(guān)注