HTTP協議:響應消息
- 請求消息:客戶端發送給服務器端的數據
- 響應消息:服務器端發送給客戶端的數據
響應消息數據格式:
- 響應消息格式由響應行丶響應頭丶響應空行丶響應體組成。
1. 響應行
由下面幾部分組成:
- 協議/版本
- 響應狀態碼
- 狀態碼描述
2. 響應頭:
- 格式:頭名稱: 值
常見的響應頭:
- Content-Type:服務器告訴客戶端本次響應體數據格式以及編碼格式
- Content-disposition:服務器告訴客戶端以什麼格式打開響應體數據值 in-line:默認值,在當前頁面內打開丶attachment;filename=xxx:以附件形式打開響應體。文件下載使用這個值
3. 響應空行就是一個空行
4. 響應體:傳輸的真實數據
常用的響應狀態碼如下所示
1xx:指示信息–表示請求已接收,繼續處理。
- 100 http1.1協議中的首部接收成功,可以繼續發送body了。
2xx:成功–表示請求已被成功接收、理解、接受。
- 200(成功)用瀏覽器打開一個網頁,正常情況下都會返回200HTTP狀態碼。
3xx:重定向(URL跳轉)–要完成請求必須進行更進一步的操作。
- 300(多種選擇)下載一部片,服務器有 avi、mp4 等格式。
- 301(永久移動)請求的網頁已永久移動到新位置,自動將請求者轉到新位置。
- 304 (頁面未修改) :按F5刷新(第二次訪問)。
4xx:客戶端錯誤–請求有語法錯誤或請求無法實現。
- 400(錯誤請求)服務器不理解請求的語法。
- 401(未授權)沒有攜帶認證信息或攜帶了錯誤的認證信息,而沒有通過認證。(未登錄時)
- 403(禁止)攜帶了正確的認證信息,服務器認爲該用戶對該資源無權訪問。(https輸成了http)
- 404(未找到)請求的內容不存在。
-
405:請求方式沒有對應的doXxx方法
5xx:服務器端錯誤–服務器未能實現合法的請求。
- 500(服務器內部錯誤)服務器自己出現錯誤。
- 502(網關錯誤)服務器作爲網關或代理,從上游服務器收到無效響應。
- 503(服務器不可用)服務器超載或停機維護不可用。
Response對象
功能:設置響應消息
1. 設置響應行
- 設置狀態碼:使用方法setStatus(int sc)
2. 設置響應頭:
- 使用方法setHeader(String name, String value)
3. 設置響應體:
步驟如下:
- 獲取輸出流。獲取字符輸出流:PrintWriter getWriter() 或者 字節輸出流:ServletOutputStream getOutputStream()
- 使用輸出流,將數據輸出到客戶端瀏覽器
重定向
- 重定向是一種資源跳轉的方式
代碼演示
package com.wrg.sendRedirect;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/ServletDemo01")
public class ServletDemo01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("1111111111");
/*
重定向方式一:
//1. 設置狀態碼爲302
response.setStatus(302);
//2.設置響應頭location
response.setHeader("location","/ServletDemo02");
*/
//方式二
//簡單的重定向方法,參數是虛擬目錄+要定向的目的地
response.sendRedirect("ServletDemo02");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
重定向的特點:redirect
- 地址欄發生變化
- 重定向可以訪問其他站點(服務器)的資源
- 重定向是兩次請求。不能使用request對象來共享數據
轉發的特點:forward
- 轉發地址欄路徑不變
- 轉發只能訪問當前服務器下的資源
- 轉發是一次請求,可以使用request對象來共享數據
web路徑寫法:
路徑分類
相對路徑:通過相對路徑不可以確定唯一資源 如:./index.html。不以/開頭,以.開頭路徑
- 規則:找到當前資源和目標資源之間的相對位置關係
- * ./:當前目錄
- ../:後退一級目錄
絕對路徑:通過絕對路徑可以確定唯一資源 如:http://localhost/day15/responseDemo2 可以簡化爲 /day15/responseDemo2 以/開頭的路徑
- 規則:判斷定義的路徑是給誰用的?判斷請求將來從哪兒發出
- 給客戶端瀏覽器使用:需要加虛擬目錄(項目的訪問路徑)。建議虛擬目錄動態獲取:request.getContextPath()。判斷請求從哪發出,例如:<a> , <form> 重定向...
- 給服務器使用:不需要加虛擬目錄,例如:轉發路徑
服務器輸出字符數據到瀏覽器
步驟:
- 獲取字符輸出流
- 輸出數據
注意:
亂碼問題:編碼和解碼不一致
解決方式:
- PrintWriter pw = response.getWriter();獲取的流的默認編碼是ISO-8859-1
- 設置該流的默認編碼
- 告訴瀏覽器響應體使用的編碼
簡單的形式,設置編碼,是在獲取流之前設置
- response.setContentType("text/html;charset=utf-8");
代碼演示
@WebServlet("/ServletDemo01")
public class ServletDemo01 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("1111111111");
/*
獲取流對象之前,設置流的默認編碼:ISO-8859-1 設置爲:GBK
response.setCharacterEncoding("utf-8");
告訴瀏覽器,服務器發送的消息體數據的編碼。建議瀏覽器使用該編碼解碼
response.setHeader("content-type","text/html;charset=utf-8");
*/
//方式二:簡單的形式,設置編碼
response.setContentType("text/html;charset=utf-8");
//1.獲取字符輸出流
PrintWriter pw = response.getWriter();
//2.輸出數據
//pw.write("<h1>hello response</h1>");
pw.write("你好啊啊啊 response");
}
服務器輸出字節數據到瀏覽器和輸出字符數據一模一樣。唯一的區別就是獲取的輸出的流不同。
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//告訴瀏覽器,服務端使用什麼字符集編碼
response.setContentType("text/html;charset=utf-8");
//1.獲取字節輸出流
ServletOutputStream sos = response.getOutputStream();
//2.輸出數據
sos.write("你好".getBytes("utf-8"));
}
驗證碼案例
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
int width = 100;
int height = 50;
//1.創建一對象,在內存中圖片(驗證碼圖片對象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化圖片
//2.1 填充背景色
Graphics g = image.getGraphics();//畫筆對象
g.setColor(Color.PINK);//設置畫筆顏色
g.fillRect(0,0,width,height);
//2.2畫邊框
g.setColor(Color.BLUE);
g.drawRect(0,0,width - 1,height - 1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
//生成隨機角標
Random ran = new Random();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());
//獲取字符
char ch = str.charAt(index);//隨機字符
//2.3寫驗證碼
g.drawString(ch+"",width/5*i,height/2);
}
//2.4畫干擾線
g.setColor(Color.GREEN);
//隨機生成座標點
for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//3.將圖片輸出到頁面展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
點擊換一張圖片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
/*
分析:
點擊超鏈接或者圖片,需要換一張
1.給超鏈接和圖片綁定單擊事件
2.重新設置圖片的src屬性值
*/
window.onload = function(){
//1.獲取圖片對象
var img = document.getElementById("checkCode");
//2.綁定單擊事件
img.onclick = function(){
//加時間戳
var date = new Date().getTime();
img.src = "/day15/checkCodeServlet?"+date;
}
}
</script>
</head>
<body>
<img id="checkCode" src="/day15/checkCodeServlet" />
<a id="change" href="">看不清換一張?</a>
</body>
</html>
ServletContext對象:
- 概念:代表整個web應用,可以和程序的容器(服務器)來通信。
獲取ServletContext對象:
- 通過request對象獲取 方法 request.getServletContext();
- 通過HttpServlet獲取 方法this.getServletContext();
ServletContext對象功能
1:獲取MIME類型:
- MIME類型:在互聯網通信過程中定義的一種文件數據類型
- MIME的組成結構非常簡單;由類型與子類型兩個字符串中間用
'/'
分隔而組成。不允許空格存在。type 表示可以被分多個子類獨立類別。subtype 表示細分後的每個類型。
2. ServletContext是個域對象:共享數據
- 由於一個web應用中的所有Servlet共享同一個ServletContext對象:因此Servlet對象之間可以通過ServletContext來是實現通訊。ServletContext對象通常也被稱爲context域對象。
3. 獲取文件的真實(服務器)路徑
可以搜索當前工程目錄下面的資源文件
- getServletContext().getRealPath(path),根據相對路徑獲取服務器上資源的絕對路徑
- getServletContext().getResourceAsStream(path),根據相對路徑獲取服務器上資源的輸入字節流