JavaWeb - Respnse響應訊息、ServletContext物件
阿新 • • 發佈:2020-07-17
1.響應訊息資料格式
1. 響應行
1. 組成:協議 / 版本 響應狀態碼 狀態碼描述 如:HTTP/1.1 200 OK
2. 響應狀態碼:伺服器告訴客戶端瀏覽器本次請求和響應的一個狀態
1. 狀態碼都是3位數字
2. 分類:
1. 1xx:伺服器接收客戶端訊息,但沒有接收完成,等待一段時間後,傳送1xx多狀態碼
2. 2xx:成功。代表:200
3. 3xx:重定向。代表:302(重定向) 304(訪問快取)
4. 4xx:客戶端錯誤。代表:404(請求路徑沒有對應的資源)405(請求方式沒有對應的doXxx方法)
5. 5xx:伺服器端錯誤。代表:500(伺服器內部出現異常)
2. 響應頭
1. 格式:頭名稱:值
2. 常見的響應頭:
1. Content - Type:伺服器告訴客戶端本次響應訊息體資料格式以及編碼格式
2. Content - disposition:伺服器告訴客戶端以什麼格式開啟響應體資料
* 值:
* in - line:預設值,在當前頁面內開啟
* attachment(filename=xxx):以附件形式開啟響應體。檔案下載時使用
3. 響應空行
4. 響應體
* 字串格式:
2.Response
* 功能:設定相應訊息
1. 設定響應行
1. 格式: HTTP/1.1 200 ok
2. 設定狀態碼:setStatus(int sc)
2. 設定響應頭
1. setHeader(String name,String value)
3. 設定響應體
* 使用步驟:
1. 獲取輸出流
* 字元輸出流:PrintWriter getWriter()
* 位元組輸出流:ServletOutputStream getOutputStream()
2. 使用輸出流,將資料輸出到客戶端瀏覽器
response.setStatus(302);
response.setHeader("location","/web_servlet/respnseDemo01")
### 簡單的重定向方法:sendRedirect()
* 重定向的特點:
1. 位址列發生變化
2. 重定向可以訪問其他站點(伺服器)的資源
3. 重定向是兩次請求。不能使用request域來共享資料了
* 轉發的特點:
1. 轉發位址列路徑不變
2. 轉發只能訪問當前伺服器下的資源
3. 轉發是一次請求,可以使用request物件來共享資料
* 面試題:forward和redirect的區別,既轉發和重定向的區別
* 路徑寫法:
1. 路徑分類
1. 相對路徑:通過相對路徑不可以確定唯一資源
* 如: . / index.html 或 ../ index.html
* 不以 / 開頭,以 . 開頭
* 規則:找到訪問當前資源和目標資源的相對位置關係 . / 代表當前目錄 . . / 代表後退一級的目錄
2. 絕對路徑:通過絕對路徑可以確定唯一資源
* 如: http://localhost/web_servlet/ResponseDemo01 或 /web_servlet/ResponseDemo01
* 以 / 開頭的路徑
* 規則:判斷定義的路徑是給誰用的?判斷請求將來從哪發出
* 給客戶端瀏覽器使用:需要加虛擬目錄(專案的訪問路徑),重定向就是客戶端發出的,需要加虛擬目錄
* 建議:之後動態獲取虛擬目錄 request.getContextPath() 來獲取
* 如:<a> <href> 重定向
* 給伺服器使用:不需要加虛擬目錄 如:轉發路徑
3. 伺服器輸出字元資料到瀏覽器
* 步驟:
1. 獲取字元輸出流
2. 輸出資料
* 注意:
* 亂碼問題:
1. PrintWriter pw = response.getWriter(); 獲取的流的預設編碼是ISO-8859-1的拉丁編碼
2. 設定該流的預設編碼和響應體資料使用的編碼:response.setContentType("text/html;charset=utf-8"); 在獲取流之前設定
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //告訴瀏覽器,伺服器傳送的訊息體資料的編碼 response.setHeader("Content-type","text/html;charset=utf-8"); //簡單形式設定編碼 response.setContentType("text/html;charset=utf-8"); //1.獲取字元輸出流 PrintWriter pw = response.getWriter(); //2.輸出資料 pw.write("hello response"); }
4. 案例:驗證碼
1. 本質:圖片
2. 目的:防止惡意表單註冊
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script> window.onload = function () { // 1.獲取圖片物件 var img = document.getElementById("checkcode"); // 2.繫結單擊事件 img.onclick = function () { //加時間戳 var date = new Date().getTime(); //因為瀏覽器會從快取裡拿圖片,而不是重新請求,所以我們修改路徑,通過傳參,達到修改了路徑 img.src= "/servlet3/checkCode?" + date; }; document.getElementById("change").onclick = function () { // 1.獲取圖片物件 var img = document.getElementById("checkcode"); //加時間戳 var date = new Date().getTime(); //因為瀏覽器會從快取裡拿圖片,而不是重新請求,所以我們修改路徑,通過傳參,達到修改了路徑 img.src= "/servlet3/checkCode?" + date; } } </script> </head> <body> <img id="checkcode" src="/servlet3/checkCode"> <a id="change" href="">看不清,換一張</a> </body> </html>註冊頁面
package web.servlet; import javax.imageio.ImageIO; 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.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; @WebServlet("/checkCode") public class CheckCode 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 graphics = image.getGraphics(); //畫筆物件 // 設定畫筆填充顏色 graphics.setColor(Color.PINK); graphics.fillRect(0,0,width,height); // 2.2 畫邊框 graphics.setColor(Color.BLUE); graphics.drawRect(0,0,width-1,height-1); String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; // 生產隨機角標 Random random = new Random(); for (int i = 1; i <= 4; i++) { int index = random.nextInt(str.length()); // 獲取字元 char random_char = str.charAt(index); // 2.3 寫驗證碼 graphics.drawString(random_char+"",width/5*i,height/2); } // 2.4畫干擾線 graphics.setColor(Color.GREEN); for (int i = 0; i < 10; i++) { // 隨機生成座標點 int x1 = random.nextInt(width); int x2 = random.nextInt(width); int y1 = random.nextInt(height); int y2 = random.nextInt(height); graphics.drawLine(x1,y1,x2,y2); } // 3.將圖片輸出到頁面展示 ImageIO.write(image,"jpg",response.getOutputStream()); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }驗證碼生產的Servlet
5. ServletContext物件
1. 概念:代表整個web應用,可以和程式的容器(伺服器)來通訊
2. 獲取:
1. 通過request物件來獲取
request.getServletContext();
2. 通過HttpServlet獲取
this.getServletContext();
3. 功能:
1. 獲取MIME型別:
* MIME型別:在網際網路通訊過程中定義的一種檔案資料型別
* 格式:大型別 / 小型別 text / html image / jpeg
* 獲取:String getMimeType(String file)
2. 域物件:共享資料
1. setAttribute(String name,Object value)
2. getAttribute(String name)
3. removeAttribute(String name)
* ServletContext物件範圍:可共享所有使用者所有請求的資料
3. 獲取檔案的真實(伺服器)路徑(檢視檔案的工作空間路徑)Using CATALINA_BASE 對應的路徑去找 conf / Catalina / localhost 下的xml文件中
1. 方法:String getRealPath(String path)
* web目錄下的資源路徑寫法:/ a.txt
* WEB - INF目錄下的資源路徑寫法:/ WEB - INF / a.txt
* src目錄下的資源路徑寫法:WEB - INF / classes / a.txt
6. 案例:圖片及任何檔案下載
* 使用響應頭設定資源的開啟方式:
* content - dispostion:attachment;filename=xxx
* 步驟:
1. 定義頁面,編輯超連結的href屬性,指向servlet,傳遞資源名稱filename
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>圖片下載</title> </head> <body> <a href="img/九尾.jpg">九尾圖片</a> <hr/> <a href="/case_download/downloadServlet?filename=九尾.jpg">九尾圖片</a> </body> </html>下載頁面
2. 定義servlet
1. 獲取檔名稱
2. 使用位元組輸入流載入檔案進記憶體
3. 指定response的響應頭:content - dispostion:attachment;filename=xxx
4. 將資料寫出到response的輸出流
package download; import utils.DownLoadUtils; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.FileInputStream; import java.io.IOException; @WebServlet("/downloadServlet") public class DownloadServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1.獲取請求引數,檔名稱 String filename = request.getParameter("filename"); // 2. 使用位元組輸入流載入檔案進記憶體 // 2.1 找到檔案的伺服器路徑 ServletContext servletContext = this.getServletContext(); String realPath = servletContext.getRealPath("/img/" + filename); // 2.2 用位元組流關聯 FileInputStream fis = new FileInputStream(realPath); //3. 設定response的響應頭 //3.1 設定響應頭型別:content-type String mimeType = servletContext.getMimeType(filename);//獲取檔案的mime型別 response.setHeader("content-type",mimeType); //3.2 設定響應頭開啟方式 content-disposition //解決中文檔名問題 //1. 獲取user-agent請求頭 //2. 使用工具類方法編碼檔名 String agent = request.getHeader("user-agent"); filename = DownLoadUtils.getFileName(agent, filename); response.setHeader("content-disposition","attachment;filename="+filename); //4. 將輸入流的資料寫入到輸出流中 ServletOutputStream sos = response.getOutputStream(); byte[] buff = new byte[1024*8]; int len = 0; while ((len = fis.read(buff))!=-1){ sos.write(buff,0,len); } fis.close(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }下載的Servlet
* 問題:
* 中文檔名問題:
* 解決思路:
1. 獲取客戶端使用的瀏覽器版本資訊
2. 根據不同的版本資訊,響應不同的資料,設定filename的編碼格式不同
package utils; import sun.misc.BASE64Encoder; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Base64; public class DownLoadUtils { public static String getFileName(String agent, String filename) throws UnsupportedEncodingException { if (agent.contains("MSIE")) { // IE瀏覽器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐瀏覽器 BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它瀏覽器 filename = URLEncoder.encode(filename, "utf-8"); } return filename; } }中文亂碼utils包,jdk8用,jdk9要轉換