前面講解完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ù)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ā)。
(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ù)來決定。
/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)目訪問的虛擬路徑,從而降低代碼的耦合度。
要想將字符數(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("你好");
要想將字節(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); }}
凡本網(wǎng)注明“XXX(非中國微山網(wǎng))提供”的作品,均轉(zhuǎn)載自其它媒體,轉(zhuǎn)載目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)和其真實(shí)性負(fù)責(zé)。
南昌豐益肛腸醫(yī)院長期以來積極響應(yīng)國家醫(yī)改號召,在檢查費(fèi)用、診療環(huán)節(jié)、藥品方面完全是平價管理,公正、公平、合理是南昌豐益的收費(fèi)理念,實(shí)
2023-02-27 15:54
□記者付玉婷報(bào)道本報(bào)濟(jì)南2月26日訊 當(dāng)前,全省氣溫回升較快,大風(fēng)天氣增多,有效降水較常年同期偏少,重點(diǎn)林區(qū)持續(xù)干旱,森林防滅火工作進(jìn)入
2023-02-27 14:47
搶占新風(fēng)口沖刺大市場日照打造“海洋預(yù)制菜之都”來自挪威的三文魚經(jīng)過開片、去刺、熏制等工藝流程變成煙熏三文魚片,來自俄羅斯的北極甜蝦、
2023-02-27 15:00
未成年人中,有這樣一群特殊的孩子——孤困兒童。他們有的是孤兒,有的父母在服刑,有的生活在精神病家庭,童年缺少關(guān)愛與陪伴,生活苦澀而灰
2023-02-27 14:53
□記者孫源澤王浩奇報(bào)道本報(bào)濟(jì)寧2月26日訊今天晚上,“2023山東迎春消費(fèi)季”暨“運(yùn)河之都·惠享濟(jì)寧”啟動儀式在濟(jì)寧舉行?;顒佑缮綎|省商務(wù)廳
2023-02-27 14:59
山東面向海內(nèi)外招聘三千五百名青年博士后招收人數(shù)歷年最多,引才經(jīng)費(fèi)創(chuàng)歷史新高近日,省人力資源社會保障廳公開發(fā)布2023年度山東省博士后招聘
2023-02-27 14:58
腫眼泡的存在使很多雙眼睛失去了本身應(yīng)有的光彩,因此困擾了很多女性,不僅看上去臃腫,無神,還使眼睛看上去更小,讓除去腫眼泡的想法越來越強(qiáng)
2023-02-27 14:04
保定華美整形美容醫(yī)院怎么樣?華美顧客說:推薦大家過來顧客說:服務(wù)態(tài)度很好,彭院長手術(shù)做的很精湛很值得信賴!顧客說:雙眼皮李院給我做的非常
2023-02-27 11:24
如何清理ie緩存?1、點(diǎn)擊右上角的工具按鈕,2、點(diǎn)擊internet選項(xiàng)按鈕,3、點(diǎn)擊瀏覽歷史記錄的"刪除"按鈕,4、打開一個彈窗,選擇具體要清除
2023-02-27 10:23
蒲公英的吃法是什么?蒲公英喜光還是喜陰?小編搜集整理了相關(guān)資料,一起來了解下吧!蒲公英別名黃花地丁、婆婆丁、華花郎等,為菊科多年生草
2023-02-27 10:17