HttpServletResponse
第一章 HTTP響應詳解
前面的文章我們學習了HTTP請求協定及HttpServletRequest對象,今天我們來學習HTTP協定中的另一部分:HTTP響應協定及HttpServletResponse對象。
1、HTTP響應封包
HTTP是基于請求和響應的協定,一次請求對應一次響應。請求和響應的資料格式都遵從HTTP的超文本傳輸協定。與HTTP的請求一樣,HTTP響應的資料也分為3部分:響應行 ,響應頭 ,響應體 這3部分組成。請求是通過浏覽器将資料傳送到伺服器,而響應是将伺服器處理的結果回送到浏覽器。
2、使用抓包工具檢視響應資料
建立一個web項目,在web項目的web檔案夾下建立一個hello.html頁面。将下面的代碼複制到hello.html頁面中,啟動項目,通過:url:http://localhost:8080/hello.html通路這個頁面。使用chrome工具抓包。
【示例】hello.html靜态頁面
xml複制代碼<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>get請求</h2>
<form action="/getServlet" method="get">
使用者名:<input type="text" name="username" value="suoge" /> <br/>
密碼:<input type="text" name="password" value="1234" /> <br/>
<input type="submit" value="get送出" />
</form>
<h2>post請求</h2>
<form action="/postServlet" method="post">
使用者名:<input type="text" name="username" value="suoge" /> <br/>
密碼:<input type="text" name="password" value="1234" /> <br/>
<input type="submit" value="post送出" />
</form>
</body>
</html>
分别建立GetServlet和PostServlet,代碼如下:
GetServlet的代碼如下:
scala複制代碼@WebServlet("/getServlet")
public class GetServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//給浏覽器響應資料
response.getWriter().print("hello response");
}
}
PostServlet的代碼如下:
scala複制代碼@WebServlet("/postServlet")
public class PostServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//給浏覽器響應資料
response.getWriter().print("hello response");
}
}
抓取的響應封包如下圖所示:
說明:
1)由于浏覽器的原因,浏覽器會把請求行和響應行資訊放在了一起;
2)get和post請求的響應沒有差別;
【響應行】
響應行格式:協定/版本 狀态碼
如:HTTP/1.1 200 ;
常見狀态碼:
狀态碼 | 狀态碼描述 | 說明 |
200 | OK | 請求已成功,請求所希望的響應頭或資料體将随此響應傳回。出現此狀态碼是表示正常狀态。 |
302 | Move temporarily | 重定向,請求的資源臨時從不同的 位址響應請求。 |
304 | Not Modified | 從浏覽器緩存中讀取資料,不從伺服器重新擷取資料。例如,使用者第一次從浏覽器通路伺服器端圖檔資源,以後在通路該圖檔資源的時候就不會再從伺服器上加載而直接到浏覽器緩存中加載,這樣效率更高。 |
404 | Not Found | 請求資源不存在。通常是使用者路徑編寫錯誤,也可能是伺服器資源已删除。 |
403 | Forbidden | 伺服器已經了解請求,但是拒絕執行它 |
405 | Method Not Allowed | 請求行中指定的請求方法不能被用于請求相應的資源 |
500 | Internal Server Error | 伺服器内部錯誤。通常程式抛異常 |
【響應頭】
響應頭也是用的鍵值對key:value,伺服器基于響應頭通知浏覽器的行為。
常見的響應頭 :
響應頭Key | 響應頭value |
location | 指定響應的路徑,需要與狀态碼302配合使用,完成重定向 |
content-Type | 響應正文的類型(MIME類型,屬于伺服器裡面的一種類型,例如檔案在window系統有自己的類型,.txt .doc .jpg。檔案在伺服器中也有自己的類型),同時還可以解決亂碼問題。例如:text/html;charset=UTF-8 |
content-disposition | 通過浏覽器以附件形式解析正文,例如:attachment;filename=xx.zip |
refresh | 頁面重新整理,例如:3;url=www.itcast.cn //三秒重新整理頁面到www.itcast.cn |
說明:
MimeType:辨別資料類型
bash複制代碼最早的HTTP協定中,并沒有附加的資料類型資訊,所有傳送的資料都被客戶程式解釋為超文本标記語言HTML 文檔,而為了支援多媒體資料類型,HTTP協定中就使用了附加在文檔之前的MIME資料類型資訊來辨別資料類型。
MIME意為多功能Internet郵件擴充,它設計的最初目的是為了在發送電子郵件時附加多媒體資料,讓郵件客戶程式能根據其類型進行處理。然而當它被HTTP協定支援之後,它的意義就更為顯著了。它使得HTTP傳輸的不僅是普通的文本,而變得豐富多彩。
每個MIME類型由兩部分組成,前面是資料的大類别,例如聲音audio、圖象image等,後面定義具體的種類。
常見的MIME類型(通用型):
windows tomcat
超文本标記語言文本 .html text/html ***
xml文檔 .xml text/xml
XHTML文檔 .xhtml application/xhtml+xml
普通文本 .txt text/plain ***
PDF文檔 .pdf application/pdf
Microsoft Word檔案 .word application/msword
PNG圖像 .png image/png ***
GIF圖形 .gif image/gif
JPEG圖形 .jpeg,.jpg image/jpeg
......
【響應體】
響應體,就是伺服器發送給浏覽器的資料。目前浏覽器向伺服器請求的資源是hello.html,是以伺服器給浏覽器響應的資料是一個html頁面。
請求資源路徑:
響應結果:
如果請求是servlet,那麼浏覽器的響應體接收到的是servlet響應的資料:
總結:
響應行:協定版本号 狀态碼 200(一切正常) 404(找不到資源路徑) 500(伺服器報異常) 302(和location一起使用,實作重定向) 304(從浏覽器緩存中讀取資料) 405(伺服器的servlet沒有重寫doGet和doPost方法)
響應頭:
location 指定響應的路徑
content-type:告訴浏覽器檔案格式,告訴浏覽器不要解析html檔案,解決中文亂碼問題
refresh 定時重新整理
content-disposition 以附件形式展示圖檔等資源
響應體:
伺服器處理的結果響應到浏覽器中
第二章 HttpServletResponse對象
遇到問題 : 伺服器接受用戶端的請求之後,處理請求之後,伺服器如何将對應的資料響應給用戶端呢?
解決方案 : 一切皆對象,Servlet程式接受用戶端請求之後,通過HttpServletResponse對象來完成向用戶端的響應。
通過該對象,将資料傳回給用戶端。
1、HttpServletResponse對象作用
HttpServletResponse對象代表伺服器響應,tomcat建立HttpServletResponse對象,并将該對象作為參數傳遞給servlet的service方法。
這個對象的作用:
設定響應行、頭、體
下面,就這幾方面對HttpServletResponse對象的常用API進行詳細講解。
2、HttpServletResponse對象常用API
2.1【響應行】
響應行:協定/版本 如:HTTP/1.1 200 。這裡邊的資訊,我們通常隻會用到狀态碼,操作狀态碼的方法setStatus(int code);
方法 | 說明 |
setStatus(int code) | 向浏覽器發送狀态碼 |
【常用狀态碼】
對應的狀态碼響應狀态碼常量 | 說明 |
200 | 響應成功 |
404 | 資源路徑錯誤或資源被删除 |
500 | 伺服器内部錯誤 |
302 | 重定向 |
2.2 【響應頭】
方法 | 說明 |
setHeader(String name,String value) | 設定響應頭資訊 |
【常見響應頭】
響應頭Key | 響應頭value |
refresh | 頁面重新整理,例如:3;url=www.itcast.cn //三秒重新整理頁面到www.itcast.cn |
content-type | 設定響應資料的類型(MIME類型) 和編碼格式 例如:text/html;charset=UTF-8 |
location | 指定響應的路徑,需要與狀态碼302配合使用,完成重定向。 |
content-disposition | 通過浏覽器以附件形式解析正文,例如:attachment;filename=xx.zip。 |
2.2.1.常見響應頭
【練習】響應頭---定時重新整理
需求:1. 通路到Servlet類3秒後跳轉到百度;
scala複制代碼@WebServlet("/refreshServlet")
public class RefreshServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//實作refresh關鍵字跳轉功能 響應頭API
//方法具有2個參數 關鍵字 跳轉位址
response.setHeader("refresh","3;url=http://www.baidu.com");
}
}
浏覽器輸入位址:http://localhost:8080/refreshServlet
注意:3秒以後自動跳轉到百度首頁,前提你要聯網啊。
【練習】content-type 設定響應資料的類型。告訴浏覽器不要解析html格式資料。
scala複制代碼@WebServlet("/contentServlet")
public class ContentServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//告訴浏覽器不要解析html格式資料
//每次寫這些方法,代碼太多,而且API還經常使用 setContentType(text/plain)
// response.setHeader("content-type","text/plain");
response.setContentType("text/plain");
response.getWriter().print("<html><body><h1>itcast</h1></body></html>");
}
}
說明:text/plain的意思是将檔案設定為純文字的形式,浏覽器在擷取到這種檔案時并不會對其進行處理。
抓包檢視浏覽器資訊:
效果圖:
2.2.2.處理響應亂碼
2.2.2.1亂碼産生的原因
伺服器如果需要響應給浏覽器中文資料,tomcat使用getWriter()輸出字元時,對于中文需要進行編碼處理,而tomcat8 預設編碼是ISO-8859-1,該碼表是不支援中文編碼的。是以響應給浏覽器,出現亂碼。
代碼如下:
css複制代碼 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().print("<html><body><h1>程式員</h1></body></html>");
}
2.2.2.2響應亂碼解決方案
因為HttpServletResponse實作類是由tomcat伺服器提供的。是以伺服器在向浏覽器輸出資料之前,對于中文要采用支援中文的編碼進行編碼,通過response.setContentType("text/html;charset=utf-8"); :
- 設定響應的資料類型(text/html);
- 設定響應的資料編碼(utf-8);
2.2.2.3處理響應亂碼的API
方法 | 說明 |
response.setHeader("content-type","text/html;charset=utf-8"); | 設定響應頭 |
response.setContentType("text/html;charset=utf-8"); | 簡寫方式 |
【注意事項】
- 開發中通常使用response.setContentType("text/html;charset=utf-8");來處理響應亂碼;
- 處理響應亂碼必須書寫在響應資料之前才起作用;
【練習】content-type 設定響應資料的類型和編碼
scala複制代碼@WebServlet("/encodeServlet")
public class EncodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//設定響應頭:content-type
//亂碼産生的原因:編解碼不一緻
//tomcat的編碼是:ISO-8859-1
//通過設定響應頭
//1.設定響應的資料格式;
//2.設定響應資料的編碼格式;
// response.setHeader("content-type","text/html;charset=utf-8");
//簡化API
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("程式員");
}
}
效果圖:如果沒有進行響應亂碼的處理,則浏覽器顯示的是亂碼.處理之後的效果如下所示:
2.2.3.重定向(掌握)
【重定向原理分析】
【重定向API】: 重定向可以去一個servlet,也可以去一個html靜态資源.
方法 | 說明 |
response.setStatus(302); response.setHeader("location", "/otherServlet"); | 通過設定響應狀态碼和響應頭實作重定向 |
response.sendRedirect("/otherServlet"); | 重定向的簡寫方式 |
【注意事項】
- 開發中通常使用response.sendRedirect("/otherServlet");來實作重定向。
【練習】通過設定響應頭location和響應行的狀态碼302完成重定向。
方法:
arduino複制代碼 //方式一:
//location+302 共同完成重定向
response.setHeader("location", "url");
//響應行
response.setStatus(302);
//方式二:
//簡化的API
response.sendRedirect("url");
班長的servlet,【MonitorServlet.java】:
scala複制代碼@WebServlet("/monitorServlet")
public class MonitorServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//使用重定向
// response.setHeader("location","/suogeServlet");
// response.setStatus(302);
response.sendRedirect("/suogeServlet");
}
}
【SuogeServlet.java】
scala複制代碼@WebServlet("/suogeServlet")
public class SuogeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//處理響應亂碼
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("一起學習Java");
}
}
浏覽器位址欄輸入通路網站效果:
http://localhost:8080/monitorServlet
回車之後,浏覽器位址欄變為:
2.3、轉發和重定向的差別
完成重定向操作之後,同學們心裡有一個疑問:之前學習的轉發和現在的重定向都可以完成跳轉,都可以跳轉到一個servlet,也可以跳轉到一個html靜态資源,功能相同。那麼他們之間有什麼差別呢?
【轉發和重定向差別】
轉發和重定向的另一種解釋:
2.3.1、轉發和重定向的差別
差別點 | 轉發 | 重定向 |
實作原理 | 伺服器内部 | 浏覽器執行 |
請求次數 | 一次 | 兩次 |
浏覽器位址欄位址 | 不變化 | 變為第二次請求的位址 |
能否共享request域 | 能夠共享 | 不能共享 |
作用 | 共享request域對象 | 完成跳轉 |
2.3.2、轉發和重定向怎麼選擇
- 如果需要共享request域,必須使用轉發;
- 如果需要将浏覽器位址欄位址變為第二次請求的位址,必須使用重定向;
作者:also_lucky
連結:https://juejin.cn/post/7240088790424256569