一. HttpServletRequest
1. 什麼是HttpServletRequest對象?
HttpServletRequest對象代表客戶端的請求,當客戶端通過HTTP協議訪問服務器時,HTTP請求頭中的所有信息
都封裝在這個對象中,開發人員通過這個對象的方法,可以獲得客戶這些信息。也就是說所有的請求信息都封裝
在這裏,由服務器負責封裝。
2. HttpServletRequest對象的作用是用於獲取請求數據。
3. Request常用方法
(1) 獲取請求行信息:
① request.getMethod(); 獲取請求的方式
② request.getRequestURI(); / request.getRequestURL(); 獲取請求的資源
③ request.getProtocol(); 獲取請求的http協議版本
public class ExampleDemo1 extends HttpServlet {
/**
* (1)tomcat服務器接收到瀏覽器發送的請求數據,然後封裝到HttpServletRequest對象
* (2)tomcat服務器調用doGet方法,然後把request對象傳入到Servlet中。
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* (3)從request對象取出請求數據。
*/
t1(request);
}
private void t1(HttpServletRequest request) {
System.out.println("請求的方式:" + request.getMethod());// 請求方式
System.out.println("URI:" + request.getRequestURI());// 請求資源
System.out.println("URL:" + request.getRequestURL());// 也是獲取請求資源,只是兩種不同的表現形式
System.out.println("http協議版本:" + request.getProtocol());// http協議
}
}
運行結果如下圖所示:
(2) 獲取請求頭信息:
① request.getHeader("名稱"); 根據請求頭獲取請求值
② request.getHeaderNames(); 獲取所有的請求頭名稱
public class ExampleDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
t2(request);
}
private void t2(HttpServletRequest request) {
/*
* 獲取請求頭 request.getHeader("頭名稱");根據頭名稱拿到請求頭的內容。
*/
String host = request.getHeader("Host");
System.out.println(host);
// 遍歷所有請求頭
Enumeration<String> enums = request.getHeaderNames();// 得到所有的請求頭名稱列表
while (enums.hasMoreElements()) { // 判斷是否有下一個元素
String headerName = enums.nextElement();// 取出下一個元素,結果仍然是一個頭名稱,我們可以用頭名稱拿到它對應的值。
String headerValue = request.getHeader(headerName);
System.out.println(headerName + ":" + headerValue);
}
}
}
運行結果如下圖所示:
(3) 獲得實體內容
request.getInputStream(); 獲取實體內容數據
public class ExampleDemo3 extends HttpServlet {
// 爲了接受post方式提交的請求。如果是post方式提交的請求一定要用doPost方法
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 獲取請求的實體內容
*/
InputStream in = request.getInputStream(); // 得到實體內容
byte[] buf = new byte[1024];
int len = 0;
while ((len = in.read(buf)) != -1) {
String str = new String(buf, 0, len);
System.out.println(str);
}
}
}
運行結果如下圖所示:
4. 表單傳遞的請求參數如何獲取?
(1) 請求參數存在的位置:
① 如果是GET請求方式,參數放在URI的後面。
② 如果是POST請求方式,參數放在實體內容中。
(2) 獲取參數的方式:
① 獲取GET請求的參數的方式:request.getQueryString();
② 獲取POST請求的參數的方式:request.getInputStream();
(3) 存在的問題:以上兩種方式不通用,而且獲取到的參數還需要進一步的解析,所以可以採用統一方便的獲取參
數的方式。
(4) 統一獲取參數的方式:
① request.getParameter("參數名"); 根據參數名獲取參數值(注意,只能獲取一個參數的參數值)
② request.getParameterValue("參數名“); 根據參數名獲取參數值(可以獲取多個參數的參數值)
③ request.getParameterNames(); 獲取所有參數名稱列表
/*
* 獲取GET方式和POST方式提交的參數
*/
public class RequestDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 統一方便的獲取請求參數的方法
*/
// getparameter根據參數名得到參數值(但是隻能獲取一個值的參數,不能獲取多選框的值)
String name = request.getParameter("name");
String password = request.getParameter("password");
System.out.println("用戶名:" + name + " 密碼:" + password);
System.out.println("=================================");
// 返回的是一個迭代器,可以遍歷所有的參數
Enumeration<String> enums = request.getParameterNames();
while (enums.hasMoreElements()) {
String paraName = enums.nextElement();
/*
* getParameterValues(name):根據參數名獲取參數值(可以獲取同名參數名的多個參數值)
*/
// 如果參數名是hobit,則調用getParameterValues
if ("hobit".equals(paraName)) {
System.out.println(paraName + ":");
String[] hobits = request.getParameterValues("hobit");
for (String h : hobits) {
System.out.println(h + ",");
}
} else {
String paraValue = request.getParameter(paraName);
System.out.println(paraName + ":" + paraValue);
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 調用doGet方式
this.doGet(request, response);
}
}
運行結果如下圖所示:
5. request常見應用:
(1) 獲取瀏覽器類型;
(2) 防盜鏈;
(3) 各種表單輸入項數據的獲取,比如:text、password、radio、checkbox、file、select、textarea、
hidden、imge、button;
(4) 請求參數的中文亂碼問題。
二. HttpServletResponse
1. 簡介
(1) Web服務器收到客戶端的http請求,會針對每一次請求,分別創建一個用於代表請求的request對象,和代表
響應的response對象。
(2) request對象和response對象既然代表請求和響應,那我們要獲取客戶端提交過來的數據,只需要找request
對象就行了;如果要向客戶端輸出數據,只需要找response對象即可。
2. HttpServletResponse對象
HttpServletResponse對象代表了服務器的響應。這個對象中封裝了向客戶端發送數據、發送響應頭、發送響應
狀態碼的方法,該對象的作用是用來設置響應數據。
3. HttpServletResponse對象修改響應信息
(1) 修改響應行信息:
response.setStatus(); 設置狀態碼
(2) 修改響應頭信息:
response.setHeader("name","value"); 設置響應頭
(3) 修改實體內容:
response.getWriter().writer(); 發送字符實體內容
response.getOutputStream().writer(); 發送字節實體內容
4.實例:
/*
* 設置響應的信息
*/
public class ResponseDemo1 extends HttpServlet {
/*
* (1)tomcat服務器把請求信息封裝到HttpServletRequest對象中,並且把響應信息封裝到HttpServletresponse中去
* (2)tomcat服務器先調用service方法,在service方法中調用doGet方法。傳入request和response對象
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* (3)通過response對象改變響應信息。
*/
// 3.1響應行
// response.setStatus(404);//修改狀態碼,會影響瀏覽器的行爲
response.sendError(404);// 發送404的狀態碼+404的錯誤頁面。但是發404是沒有意義的。
// 3.2改變響應頭
response.setHeader("server", "JBoss");
// 3.3改變實體內容:實體內容就是我們頁面看的到的部分(瀏覽器直接能夠看到的內容就是實體內容)。
// 兩種改變方式
response.getWriter().write("01.hello world");// writer裏面是字符串,所以發送的內容也是字符內容。
response.getOutputStream().write("02.hello world".getBytes());// 發送的是字節內容。
}
/*
* (4)tomcat服務器把response對象的內容轉換成響應格式內容,再發送給瀏覽器解析
*/
}
5. Response細節:
(1) getOutputStream和getWriter方法分別用於得到輸出二進制數據、輸出文本數據的ServletOuputStream、
Printwriter對象。
(2) getOutputStream和getWriter這兩個方法互相排斥,調用了其中的任何一個方法後,就不能再調用另一方
法。
(3) Servlet程序向ServletOutputStream或PrintWriter對象中寫入的數據將被Servlet引擎從response裏面獲
取,Servlet引擎將這些數據當作響應消息的正文,然後再與響應狀態行和各響應頭組合後輸出到客戶端。
(4) Serlvet的service方法結束後,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對象是否
已經調用過close方法,如果沒有,Servlet引擎將調用close方法關閉該輸出流對象。
三. response常見應用
1. 案例一 請求重定向(Location)
(1) 請求重定向是指:一個Web資源收到客戶端請求後,通知客戶端去訪問另外一個Web資源,這稱之爲請求重
定向。
(2) 應用場景:用戶註冊。
(3) 實現方式:response.sendRedirect();
(4) 實現原理:
發送一個302狀態碼和location的響應頭即可實現重定向。
(5) 原理圖及分析:
① 瀏覽器發送一個請求到服務器請求一個資源,tomcat服務器中有一個ResponseDemo2,當瀏覽器發送請
求,它就會產生一個響應,這個Servlet就會發送狀態碼和響應頭給瀏覽器;
② 瀏覽器是認識302狀態碼的,當瀏覽器得到302狀態碼之後,會再次自動向服務器發出一個請求,請求的地址
就是location的value值的地址,所以location的地址值是:/zw_http/adv.html,當瀏覽器得到302狀態碼之
後,會自動向瀏覽器發送一個請求,就請求這個資源,服務器中有這個資源就會做出響應。所以就看到請求重定
向的效果;
③ 請求重定向瀏覽器一共向服務器發出2次請求;
④ 它的地址欄是由第二次請求決定的,用第二次的地址決定瀏覽器應該顯示什麼。也就相當於瀏覽器在地址欄中
輸入adv.html的地址。
(6) 實例:
public class ResponseDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* response.setStatus(302);//發送一個302狀態碼 response.setHeader("location",
* "/zw_http/adv.html");//location的響應頭採用的是URI的寫法。
*/
response.sendRedirect("/zw_http/adv.html");// 簡寫
}
}
2. 案例二 使用Refresh實現定時跳轉(定時刷新)
(1) 實現原理:
瀏覽器認識Refresh響應頭,得到Refresh響應頭之後重新再請求當前資源。比如:註冊完一個網站用戶後,3秒
之後跳轉到首頁。
(2) 實例:
public class ResponseDemo3 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// response.setHeader("refresh", "1");//每隔1秒刷新此頁面
response.setHeader("refresh", "3;url=/zw_http/adv.html");// 隔3秒之後跳轉到adv.html
}
}
3. 案例三 使用content-Type實現向瀏覽器輸出圖片
/*
* 案例三:content-Type的作用:
* 服務器發送給瀏覽器的數據類型及內容編碼
*/
public class ResponseDemo4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 1.服務器發送給瀏覽器的數據類型
*/
/*
* //response.setHeader("content-type","text/html");
* //response.setContentType("text/html");//和上面代碼等價,推薦使用此方法。
* response.getWriter().write(
* "<html><head><title>this is title</title></head><body>this is body</body></html>"
* );
*/
response.setContentType("image/jpg");
/*
* 發送圖片
*/
FileInputStream in = new FileInputStream(new File("e:/mm.jpg"));// 先把圖片讀進來
// 邊讀邊寫
byte[] buf = new byte[1024];
int len = 0;
while ((len = in.read(buf)) != -1) {
response.getOutputStream().write(buf, 0, len);
}
}
}