day16-Servlet05
Servlet05
14.HttpServletRequest
- HttpServletRequest對象代表客戶端的請求
- 當 客戶端/瀏覽器 通過HTTP協議訪問伺服器時,HTTP請求頭中的所有資訊都封裝在這個對象中
- 通過這個對象的方法,可以獲取客戶端的資訊
- HttpServletRequest類圖
14.1HttpServletRequest常用方法
-
getRequestURI():獲取請求的資源路徑
//localhost:8080
/servlet/loginServlet
-
getRequestURL():獲取請求的統一資源定位符(絕對路徑)
//localhost:8080/servlet/loginServlet
-
getRemoteHost():獲取客戶端的主機
-
getRemoteAddr():獲取客戶端的ip
-
getHeader():獲取請求頭
-
getParameter():獲取請求的參數
-
getParameterValues():獲取請求的參數(多個值的時候使用)
-
getMethod():獲取請求的方式get或post
-
setAttribute(key,value):設置域數據
-
getAttribute(key):獲取域數據
-
getRequestDispatcher():獲取請求轉發對象(請求轉發的核心對象)
14.2HttpServletRequest應用實例
需求:在一個表單提交數據給Servlet,在該Servlet中通過HttpServletRequest對象獲取相關數據
package com.li.servlet.request;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "HttpServletRequestMethods", value = "/requestMethods")
public class HttpServletRequestMethods extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//這裡我們使用request對象,獲取表單提交的各種數據
//System.out.println("HttpServletRequestMethods doPost()被調用...");
//1.獲取和http請求頭相關的資訊
System.out.println("請求的資源URI= " + request.getRequestURI());
System.out.println("請求的統一資源定位符(絕對路徑)URL= " + request.getRequestURL());
System.out.println("請求的客戶端ip地址= " + request.getRemoteAddr());
/*
getRemoteAddr()應用:發現某個ip在10s內訪問的次數超過100次,就封ip
實現思路:1用一個集合concurrentHashMap[k=ip v=訪問次數] 2啟動執行緒定時掃描 3做出相應處理
*/
//如果我們希望得到請求的頭的相關資訊,可以直接使用request.getHeader("請求頭欄位名")
System.out.println("http請求頭HOST= " + request.getHeader("Host"));
System.out.println("該請求發起的地址是= " + request.getHeader("Referer"));
//請獲取訪問網站的瀏覽器是什麼?
String userAgent = request.getHeader("User-Agent");
//User-Agent= Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
String[] s = userAgent.split(" ");//使用空格分割
//取最後一個字元,再用 /分割,取第一個字元
System.out.println("瀏覽器的種類= " + s[s.length - 1].split("\\/")[0]);
System.out.println("http請求方式= " + request.getMethod());
//2.獲取和請求參數相關的資訊,要去在返回數據前獲取參數
//username=&pwd=&hobby=lb&hobby=cc
//2.1獲取表單的數據[單個數據]
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
//2.2獲取表單一組數據[多個數據]
String[] hobbies = request.getParameterValues("hobby");
System.out.println("username= " + username);
System.out.println("pwd= " + pwd);
//增強for循環的快捷鍵 iter->回車即可
for (String hobby : hobbies) {
System.out.println("hobby= " + hobby);
}
//推而廣之,如果是單選,下拉框等,獲取數據的方法大同小異
}
}
html頁面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>註冊</title>
</head>
<body>
<h1>註冊用戶</h1>
<!--注意:這裡的requestMethods不是你的類名,是你在web.xml裡面(或者註解裡面)配置的<url-pattern>-->
<form action="//localhost:8080/servlet_demo/requestMethods" method="post">
u:<input type="text" name="username"/><br/><br/>
p:<input type="password" name="pwd"/><br/><br/>
選擇你最喜歡的三國人物:
<input type="checkbox" name="hobby" value="lb">劉備
<input type="checkbox" name="hobby" value="cc">曹操
<input type="checkbox" name="hobby" value="sq">孫權<br/><br/>
<input type="submit" value="註冊用戶">
</form>
</body>
</html>
瀏覽器中訪問html頁面,輸入數據,點擊註冊:
後台輸出如下:
14.3HttpServletRequest注意事項和細節
-
獲取doPost參數中文亂碼解決方法,設置編碼類型
request.setCharacterEncoding("UTF-8");
注意要寫在獲取參數之前:
-
注意:如果通過PrintWriter writer,有返回數據給瀏覽器,建議將獲取參數的程式碼寫在writer.print()之前,否則可能獲取不到參數值(post)
-
處理http響應數中文亂碼問題
-
再次理解HTTP協議響應Content-Type的含義,比如text/html,text/plain,application/x-tar
Content-Type表示返回的數據類型,瀏覽器會根據這個類型來解析數據,詳見HTTP協議MIME類型
14.4請求轉發
14.4.1為什麼需要請求轉發
-
目前我們學習的都是一次請求,對應一個Servlet
-
在實際的開發中,往往業務比較複雜,需要在一次請求中,使用到多個Servlet完成一個任務(Servlet鏈,流水作業)
14.4.2請求轉發說明
-
實現請求轉發:請求轉髮指一個web資源收到客戶端請求後,通知伺服器去調用另外一個web資源進行處理
-
HttpServletRequest對象(也叫request對象)提供了一個getRequestDispatcher方法,該方法返回一個RequestDispatcher對象,調用這個對象的forward方法可以實現請求轉發
-
request對象同時也是一個域對象,開發人員通過request對象在實現轉發時,把數據通過request對象帶給其他web資源處理
- setAttribute方法
- getAttribute方法
- removeAttribute方法
- getAttributeNames方法
14.4.3請求轉發應用實例
例子
需求:瀏覽器在某html頁面輸入數據,checkServlet根據該數據對進行操作,如果輸入的數據為「tom」,就將其設置為「管理員」,如果不是,就設置為「普通用戶」,由managerServlet向伺服器返回數據
CheckServlet:
package com.li.servlet.request;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(urlPatterns = {"/checkServlet"})
public class CheckServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CheckServlet doPost()被調用...");
//根據用戶名來確定該用戶是什麼身份
String username = request.getParameter("username");
//注意:如果是同一個request對象(請求轉發),那麼可以在不同的Servlet中使用getParameter取出該參數
if ("tom".equals(username)) {
//分配許可權
//request對象是一個域對象,通過request對象,在實現轉發時,
// 把數據通過request對象帶給其他web資源處理
request.setAttribute("role", "管理員");//k-v
} else {
request.setAttribute("role", "普通用戶");//k-v
}
//獲取分發器
/**
* 1. /managerServlet寫的是想轉發的Servlet的url-pattern
* 2. / 會被解析成 /servlet_demo
* 因此請求轉發是不可能轉發到外網去的
* 3.forward(request,response)表示把當前的request和response對象傳遞給下一個Servlet使用,
* 保證了下一個Servlet和當前的Servlet使用的是同一個request和response對象
*/
RequestDispatcher requestDispatcher =
request.getRequestDispatcher("/managerServlet");
requestDispatcher.forward(request, response);
}
}
ManagerServlet:
package com.li.servlet.request;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = {"/managerServlet"})
public class ManagerServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ManagerServlet doPost()被調用...");
//因為是同一個request對象,因此可以用request.getParameter("username")獲取username
String username = request.getParameter("username");
String role = (String) request.getAttribute("role");//k-v
//輸出資訊
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("用戶名:" + username + "<br/>");
writer.print("role:" + role);
writer.flush();
writer.close();
}
}
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄</title>
</head>
<body>
<form action="//localhost:8080/servlet_demo/checkServlet" method="post">
u:<input type="text" name="username"><br/>
<input type="submit" value="登錄">
</form>
</body>
</html>
redeployTomcat,在瀏覽器中訪問//localhost:8080/servlet_demo/login.html
,輸入數據,點擊登錄,可以看到地址欄變為//localhost:8080/servlet_demo/checkServlet
,但沒有變為managerServlet(地址會保留在第一個Servlet的URL)
14.4.4請求轉發注意細節
-
瀏覽器地址不會變化(地址會保留在第一個Servlet的URL)
-
在同一次HTTP請求中,進行多次轉發,仍然是一次HTTP請求
-
在同一次HTTP請求中,進行多次轉發,多個Servlet可以共享request域/對象的數據,即request域/對象的數據(參數,屬性)的作用域,是在一次HTTP請求有效
因為是同一個request對象(數據上來講)
-
可以轉發到WEB-INF目錄下
-
不能訪問當前WEB工程外的資源
-
因為瀏覽器地址欄會停留在第一個Servlet,如果你刷新頁面,會再次發出請求(並且會帶數據)。
所以在支付頁面情況下,不要使用請求轉發,否則會造成重複支付 [解決方案可以使用重定向]
14.5習題
14.5.1習題一
通過HttpServletRequest對象獲取到訪問服務的的瀏覽器名稱
通過字元串分割,14.2已完成
14.5.2習題二
請想辦法獲取到 JSESSIONID的值
//獲取 JSESSIONID的值
String cookie = request.getHeader("Cookie");
String[] s1 = cookie.split(";");
String[] strings = s1[0].split("=");
System.out.println("JSESSIONID的值= "+strings[1]);
14.5.3習題三
下面是一個表單,完成如下功能
(1)編寫一個RegisterServlet,能夠接收到提交的各種數據,並獲取瀏覽器所在電腦的作業系統和位數
(2)並把接收到的數據返回給瀏覽器顯示
(3)注意處理中文亂碼問題
(4)暫不處理文件提交
RegisterServlet:
package com.li.servlet.request.homework;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = {"/registerServlet"})
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.獲取表單提交的數據
//先設置編碼類型
request.setCharacterEncoding("utf-8");
//單個數據使用 getParameter
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
String pwd2 = request.getParameter("pwd2");
//多個數據使用getParameterValues
String[] sports = request.getParameterValues("sport");
String gender = request.getParameter("gender");
String city = request.getParameter("city");
String introduce = request.getParameter("introduce");
//2.獲取用戶瀏覽器所在電腦的作業系統和位數
//Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
String User_Agent = request.getHeader("User-Agent");
String[] s = User_Agent.split(" ");//使用空格分割
//s[1]="(Windows" 取出索引為1及之後的字元串
String OS = s[1].substring(1);
//s[5]=x64;
String OSNum = s[5].substring(1, 3);
//3.返回輸出
//設置編碼類型
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("你的用戶名稱:" + username + "<br/>");
writer.print("你的用戶密碼:" + pwd + "<br/>");
writer.print("你的確認密碼:" + pwd2 + "<br/>");
writer.print("喜歡的運動:");
for (String sport : sports) {
writer.print(sport + " ");
}
writer.print("<br/>你的性別:" + gender + "<br/>");
writer.print("喜歡的城市:" + city + "<br/>");
writer.print("自我介紹:" + introduce + "<br/>");
writer.print("電腦作業系統:" + OS + "<br/>");
writer.print("位數:" + OSNum + "<br/>");
writer.flush();
writer.close();
}
}
register_form.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用戶註冊</title>
</head>
<body>
<form action="//localhost:8080/servlet_demo/registerServlet" method="post">
用戶註冊資訊<br/>
用戶名稱:<input type="text" name="username"/><br/>
用戶密碼:<input type="password" name="pwd"/><br/>
確認密碼:<input type="password" name="pwd2"/><br/>
請選中你喜歡的運動項目<br/>
<input type="checkbox" name="sport" value="lq">籃球<br/>
<input type="checkbox" name="sport" value="zq">足球<br/>
<input type="checkbox" name="sport" value="sq">手球<br/>
請選中你的性別<br/>
<input type="radio" name="gender" value="men">男<br/>
<input type="radio" name="gender" value="women">女<br/>
請選中你喜歡的城市
<select name="city">
<option>--請選中--</option>
<option value="gz">廣州</option>
<option value="bj">北京</option>
<option value="sh">上海</option>
</select><br/>
自我介紹<textarea name="introduce"></textarea><br/>
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
</body>
</html>