Request&Response詳解

01_響應對象的概述&向客戶端發送數據

WEB服務器會針對每一個客戶端發出的HTTP請求,分別的創建一個請求對象和一個響應對象
如果需要獲取客戶端提交的數據,需要使用請求對象
如果需要向客戶端發送一些數據,需要使用響應對象
響應 : 響應行 響應頭 響應正文 
  1XX:瀏覽器發送的請求信息不完善,需要瀏覽器進一步補充資料
  2XX:響應正常完成
  3XX:本次請求已經完成,但是需要瀏覽器進行進一步操作  302
  4XX:請求的資源錯誤
  5XX:服務器端錯誤
注意:
這兩個流互相排斥,在一個Servlet中只能使用其中的一個,如果有字符輸出流則不能有字節輸出流,否則會出現

02_字節流向客戶端發送中文的亂碼處理

編碼:
二進制   A 65  a 97   漢字
ASCII 美國標準信息碼(128字符)
ISO-8859-1 -16 一共有15編碼 13
//GB2312 2個字節表示一個字符 6700+
GBK   2個字節表示一個字符  18000+ 國家強制標準 
Unicode 萬國碼   2個字節表示一個字符
UTF-8 用1-6個字節來表示一個字符
ANSI 本地平臺默認
     中文版window GBK
英文版的window UTF-8
原因:
亂碼的出現是因爲前後編碼不一致,發送數據的編碼,接收數據的編碼
服務器發送數據:ISO-8859-1
瀏覽器接收數據:GBK
解決方法一:
將服務器發送數據格式改爲GBK
OutputStream os = response.getOutputStream();
os.write("黑馬程序員".getBytes());//默認GBK
解決方法二
//設置響應頭,告訴瀏覽器你應該使用什麼編碼
response.setHeader("Content-type", "text/html;charset=UTF-8");
os.write("黑馬程序員".getBytes("UTF-8"))

03_字符流向客戶端發送中文的亂碼處理

原因
服務器發送數據:ISO-8859-1 -> GBK
瀏覽器接收數據:GBK
解決方法一:
response.setCharacterEncoding("GBK");//設置編碼的格式,也就是設置服務器發送數據的格式
如果服務器發送的是UTF-8
response.setCharacterEncoding("UTF-8");//服務器
response.setContentType("text/html;charset=UTF-8");//告訴瀏覽器採用什麼方式進行解碼
推薦方案
response.setContentType("text/html;charset=UTF-8");//告訴瀏覽器採用什麼方式進行解碼

04_響應頭Refresh

定時自動刷新
response.setHeader("Refresh", "3");
定時自動跳轉
response.setHeader("Refresh", "3;URL=http://www.itcast.cn");    //跳轉外部資源
response.setHeader("Refresh", "3;URL=/myResponse/ResponseDemo");//跳轉內部資源
轉發和跳轉的區別
轉發:共享請求和響應對象,跳轉:不共享
轉發:只能是內部地址,跳轉:內部地址和外部地址都可以
轉發:地址欄不會發生變化,跳轉:地址欄會發生變化

05_請求重定向

概念:一個WEB資源接收到客戶端的請求之後,通知這個客戶端去訪問(請求)另外的一個WEB資源
重定向和轉發的區別
請求次數
重定向發出兩次請求
轉發只發出一次請求,共享請求對象和響應對象
訪問的路徑
重定向可以訪問內部的路徑,也可以訪問外部的路徑
轉發只能訪問內部的路徑
地址欄
重定向的地址欄發生變化
轉發地址欄不會變化
原理:設置location響應頭,同時還需要設置一個響應碼(狀態碼),302/307
  response.setHeader("Location", "http://www.itcast.cn");
  response.setStatus(307);  //立即重定向

06_文件下載案例

步驟
//設置響應頭
response.setHeader("Content-disposition", "attachment;filename=pic01.jpg");
//獲取字節輸出流對象
OutputStream os = response.getOutputStream();
//創建字節輸入流對象
String path = getServletContext().getRealPath("/WEB-INF/pic01.jpg");
FileInputStream fis = new FileInputStream(path);
//循環讀取並向客戶端發送數據
int len = 0;
byte[] bys = new byte[1024];

while((len = fis.read(bys)) != -1) {
//向客戶端發送數據
os.write(bys,0,len);
}

//釋放資源
fis.close();

07_文件下載的細節

注意:
響應頭裏不能有中文,中文被認爲是不安全的字符
更改如下:
String s = URLEncoder.encode("傳智專修學院.jpg", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + s);

08_請求對象的概述&獲取請求行

HttpServletRequest
請求對象封裝了HTTP協議的請求行,請求頭,請求體,我們可以通過請求對象的方法來獲取這些信息
獲取請求行
StringBuffer getRequestURL() //完整的URL 
String getRequestURI()  //請求行中的資源路徑
String getMethod()  //請求方式
String getContextPath() //當前項目的路徑
String getQueryString() //請求行中資源路徑後面的參數
注意:
getRequestURL()返回的是一個可變字符串,不能直接使用String來接收
getQueryString()獲取的是資源路徑後面的參數,請求體裏的數據無法獲取

09_獲取請求頭

String getHeader(String name) //通過name來獲取請求頭value
Enumeration getHeaderNames()  //獲取所有的請求頭name
Enumeration迭代遍歷
Enumeration<String> e = request.getHeaderNames();
while(e.hasMoreElements()) {
String name = e.nextElement();
System.out.println(name);
}

10_獲取表單提交的數據

String getParameter(String name) :根據表單項的name來獲取表單項的value
注意:
有表單項提交過來,但是沒有值, 打印的是空字符串
表單項根本沒有提交過來,打印的就是null,就不能調用字符串的方法,否則會報空指針異常

11_獲取表單提交的數據2

String[] getParameterValues(String name) 根據表單項的name獲取表單項value的數組
應用場景: name是重複的,比如密碼確認密碼 複選框

12_獲取表單提交的數據3

Map getParameterMap(): 獲取表單提交來的所有數據,並封裝成一個map返回,一些框架(工具類)會使用這個方法 
Enumeration getParameterNames()  獲取提交過來表單項所有的name
返回值使用泛型時應該是Map<String,String[]>形式,
因爲有時像checkbox這樣的組件會有一個name對應對個value的時候,
所以該Map中鍵值對是<String-->String[]>的實現。
注意:
註冊按鈕提交過來沒有意義,所以註冊按鈕千萬不要寫個name屬性  

14_獲取表單提交的數據亂碼的處理

原因:
編碼前後不一致
表單提交數據用的是UTF-8
請求對象接收數據轉換成字符串 用的是默認的ISO-8859-1
對於post請求
request.setCharacterEncoding("UTF-8");//只能處理請求體,這裏設置請求對象創建字符串所使用的編碼是UTF-
對於get請求
瀏覽器
按照表單頁面的編碼(UTF-8)進行轉碼,轉成字節數組,拼接在請求資源的後面
接下來把字節數組做一個轉義(url編碼)在發送
服務器
服務器首先拿到這個數據做一個url解碼,(正確的)
然後把解碼之後的數據按照ISO-8859-1拼成字符串(錯誤)
做法:
//把字符串打回原形
byte[] bys = request.getParameter("username").getBytes("ISO-8859-1");
//把字節數組按照正確的編碼轉換字符串
String username = new String(bys,"UTF-8");

15_轉發和包含

用ServletContext實現轉發和包含,路徑必須以正斜槓開頭
RequestDispatcher rd = getServletContext().getRequestDispatcher("/register.html");
rd.forward(request, response);
rd.include(request, response);
用request對象實現轉發和包含,路徑可以不用正斜槓開頭
RequestDispatcher rd = request.getRequestDispatcher("register.html");
rd.forward(request, response);
rd.include(request, response);

16_使用請求對象實現數據共享

ServletContext 上下文對象 範圍是當前的web應用   
時間範圍  tomcat 一加載項目 tomcat關閉
空間範圍  整個web應用
request 請求對象 範圍是當前的請求 需要同一個請求才能實現數據的共享
時間範圍 一個請求開始,請求結束
空間範圍  當前這個請求裏面
//設置數據
request.setAttribute("username", "zhangsan");
//獲取數據
Object obj = request.getAttribute("username");
System.out.println(obj);
//刪除數據
request.removeAttribute("username");
//轉發
RequestDispatcher rd = request.getRequestDispatcher("/RequestDemo9");
rd.forward(request, response);
訪問網站訪問量



發佈了43 篇原創文章 · 獲贊 31 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章