1. 程式人生 > >Request&Response詳解

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);
訪問網站訪問量