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

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

時間:2023-02-27 17:12:36    來源:騰訊云    

Response對象

前面講解完Request對象,接下來我們回到剛開始的那張圖:


【資料圖】

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

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

在這里插入圖片描述

介紹完Response的相關(guān)體系結(jié)構(gòu)后,接下來對于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)體==,對于這三部分內(nèi)容的數(shù)據(jù),respone對象都提供了哪些方法來進(jìn)行設(shè)置?

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

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

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

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

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

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

獲取字符輸出流:

PrintWriter getWriter();

獲取字節(jié)輸出流

ServletOutputStream getOutputStream();

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

3.2 Respones請求重定向

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

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

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

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

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

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

具體如何來使用,我們先來看下需求:

在這里插入圖片描述

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

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

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

3.在ResponseDemo1的方法中使用

response.setStatus(302);

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

4.啟動測試

(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)啟動測試

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

在這里插入圖片描述

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

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

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

所以第3步中的代碼就可以簡化為:

@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)行重定向訪問的時候,由于是由瀏覽器發(fā)送的兩次請求,所以地址會發(fā)生變化

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

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

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

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

介紹完==請求重定向==和==請求轉(zhuǎn)發(fā)==以后,接下來需要把這兩個放在一塊對比下:

在這里插入圖片描述

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

3.3 路徑問題

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

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

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

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

對于重定向來說,路徑最終是由瀏覽器來發(fā)送請求,就需要添加虛擬目錄。

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

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

答案:

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

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

@WebServlet("/resp1")public class ResponseDemo1 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        System.out.println("resp1....");        //簡化方式完成重定向        //動態(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);    }}

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

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

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

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

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

返回一個簡單的字符串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ù),這樣瀏覽器才會解析HTML標(biāo)簽response.setHeader("content-type","text/html");writer.write("

aaa

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

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

返回一個中文的字符串你好,需要注意設(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ù)寫回到瀏覽器,我們需要兩個步驟:

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

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

返回一個圖片文件到瀏覽器
/** * 響應(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);    }}
在這里插入圖片描述

上述代碼中,對于流的copy的代碼還是比較復(fù)雜的,所以我們可以使用別人提供好的方法來簡化代碼的開發(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(非中國微山網(wǎng))提供”的作品,均轉(zhuǎn)載自其它媒體,轉(zhuǎn)載目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)和其真實(shí)性負(fù)責(zé)。

特別關(guān)注