一、HttpServletRequest 類
1. HttpServletRequest 類作用?
每次只要有請求進入 Tomcat 伺服器,Tomcat 伺服器就會把請求過來的 HTTP 協議資訊解析好封裝到 Request 物件中。 然後傳遞到 service 方法(doGet 和 doPost)中給我們使用,可以通過 HttpServletRequest 物件,獲取到所有請求的 資訊
2. HttpServletRequest 類的常用方法
- getRequestURI() 獲取請求的資源路徑
- getRequestURL() 獲取請求的統一資源定位符(絕對路徑)
- getRemoteHost() 獲取客戶端的 ip 地址
- getHeader() 獲取請求頭
- getParameter() 獲取請求的引數
- getParameterValues() 獲取請求的引數(多個值的時候使用)
- getMethod() 獲取請求的方式 GET 或 POST
- setAttribute(key, value); 設定域資料
- getAttribute(key); 獲取域資料
- getRequestDispatcher() 獲取請求轉發物件
具體如下:
首先把環境建好,配置好web.xml ,然後在類中
package com.md.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author MD
* @create 2020-07-25 8:18
*/
public class RequestAPIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(req.getRequestURI());// /04_Servlet/requestAPIServlet
System.out.println(req.getRequestURL());
//http://localhost:8080/04_Servlet/requestAPIServlet
System.out.println(req.getRemoteHost());//127.0.0.1
System.out.println(req.getHeader("User-Agent"));//Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
System.out.println(req.getMethod());//GET
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
對應的web.xml
<servlet>
<servlet-name>RequestAPIServlet</servlet-name>
<servlet-class>com.md.servlet.RequestAPIServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestAPIServlet</servlet-name>
<url-pattern>/requestAPIServlet</url-pattern>
</servlet-mapping>
3. 獲取請求引數
首先在web下面建立html檔案,如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/parameterServlet" method="post">
使用者名稱:<input type="text" name="username"><br>
密碼:<input type="password" name="password"><br>
愛好:<input type="checkbox" name="hobby" value="cpp">C++
<input type="checkbox" name="hobby" value="java">Java
<input type="checkbox" name="hobby" value="python">Python
<input type="submit">
</form>
</body>
</html>
然後是對應的java程式碼,以及配置的web.xml(和上面的類似)
/**
* @author MD
* @create 2020-07-25 8:31
*/
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("------------doGet--------------");
// 獲取請求的引數
String username = req.getParameter("username");
String password = req.getParameter("password");
// String hobby = req.getParameter("hobby");
// 當有多個值的時候
String [] hobby = req.getParameterValues("hobby");
System.out.println("使用者名稱:"+username);
System.out.println("密碼:"+password);
System.out.println("愛好:"+ Arrays.asList(hobby));
}
}
4. 中文亂碼
使用post請求的時候,如果使用者名稱輸入的是中文,則會出現中文亂碼的情況,所以需要這樣設定
public class ParameterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 在post的時候注意設定字符集,要不中文亂碼
// 只有在獲取請求引數呼叫之前使用才有效
req.setCharacterEncoding("UTF-8");
System.out.println("------------doPost--------------");
// 獲取請求的引數
String username = req.getParameter("username");
String password = req.getParameter("password");
// String hobby = req.getParameter("hobby");
// 當有多個值的時候
String [] hobby = req.getParameterValues("hobby");
System.out.println("使用者名稱:"+username);
System.out.println("密碼:"+password);
System.out.println("愛好:"+ Arrays.asList(hobby));
}
}
5. 請求轉發
什麼是請求的轉發?
請求轉發是指伺服器收到請求後,從一次資源跳轉到另一個資源的操作叫請求轉發
請求轉發的特點:
- 瀏覽器位址列沒有改變
- 一次請求
- 共享Request域中的資料
- 可以轉發到WEB-INF目錄下
- 不可以訪問工程以外的資源
例子如下:通過訪問Servlet1然後轉發到Servlet2去
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// http://localhost:8080/04_Servlet/servlet1?username=abc
// 1. 獲取請求的引數
String username = req.getParameter("username");
System.out.println("在Servlet1中獲取到的請求引數:"+username);
// 在Servlet1中獲取到的請求引數:abc
// 2. 把獲取到的資料傳遞,也可以自定義引數傳遞
// req.setAttribute("username" , username);
req.setAttribute("key","我來自Servlet1");
// 3. 轉發
// 地址必須以 /開頭 ,這個地址也是在web.xml中配置對應的你要去的
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
requestDispatcher.forward(req,resp);
// 或者可以直接這樣
req.getRequestDispatcher("/servlet2").forward(req,resp);
}
}
對應的web.xml就不展示了,都類似
/**
* @author MD
* @create 2020-07-25 8:57
*/
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 獲取請求的引數
String username = req.getParameter("username");
System.out.println("在Servlet2中獲取到的請求引數:"+username);//在Servlet2中獲取到的請求引數:abc
// 2. 檢視從Servlet1中傳遞的引數
Object key = req.getAttribute("key");
System.out.println("Servlet1中傳來的引數:"+key);//Servlet1中傳來的引數:我來自Servlet1
// 3. 處理自己的業務
System.out.println("正在處理Servlet2的業務");//正在處理Servlet2的業務
}
}
6. base標籤
所以在html檔案中,跳轉的時候若使用相對路徑,指定相對的那個路徑
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--
base標籤設定頁面相對路徑工作時參照的地址
href 屬性就是引數的地址值
-->
<!--<base href="http://localhost:8080/04_Servlet/a/b/c.html">-->
<!--
也可以這樣,但最後的斜槓不能省略
-->
<base href="http://localhost:8080/04_Servlet/a/b/">
</head>
<body>
這是a目錄下的b目錄下的c.html頁面
<a href="../../index.html">跳到首頁</a>
<!--通過定義了base,這個就相當於那個地址的上上層
http://localhost:8080/04_Servlet/index.html
-->
</body>
</html>
開發中儘量使用絕對路徑,實在不行就使用base+相對路徑
7. web中 / 斜槓的不同意義
在web中 / 是一種絕對路徑
-
/ 斜槓被瀏覽器解析,得到的地址就是 http://ip:port
<a href="/">斜槓</a>
-
/ 斜槓 如果被伺服器解析,得到的地址是:http://ip:port/工程路徑
<url-pattern>/servlet1</url-pattern>
- servletContext.getRealPath(“/”);
- request.getRequestDispatcher(“/”);
-
特殊情況: response.sendRediect(“/”); 把斜槓傳送給瀏覽器解析。得到 http://ip:port/
二、HttpServletResponse 類
1. HttpServletResponse 類的作用
HttpServletResponse 類和 HttpServletRequest 類一樣。
每次請求進來,Tomcat 伺服器都會建立一個 Response 物件傳 遞給 Servlet 程式去使用。HttpServletRequest 表示請求過來的資訊,HttpServletResponse 表示所有響應的資訊,
我們如果需要設定返回給客戶端的資訊,都可以通過 HttpServletResponse 物件來進行設定
2. 兩個輸出流
字元流 | getWriter() | 用於傳字串(常用) |
---|---|---|
位元組流 | getOutputStream() | 用於下載(傳遞二進位制資料) |
3. 如何往客戶端回傳資料
首先還是先建立一個servlet,配置對應的web.xml
注意中文的亂碼情況
package com.md.servlet;
/**
* @author MD
* @create 2020-07-25 9:57
*/
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println(resp.getCharacterEncoding());//ISO-8859-1
//
// // 設定伺服器字符集為
// resp.setCharacterEncoding("UTF-8");
// // 此時若瀏覽器沒有使用UTF-8中文還是亂碼,這個時候需要
// // 通過設定響應頭,使得瀏覽器也使用UTF-8字符集
// resp.setHeader("Content-Type","text/html; charset=UTF-8");
// 或者直接可以這樣寫,自動設定伺服器字符集和瀏覽器響應頭
// 方法一定要流獲取之前先呼叫,通常放在最上面就行
resp.setContentType("text/html; charset=UTF-8");
// 需求:往客戶端回傳字串資料
PrintWriter writer = resp.getWriter();
writer.write("response");
writer.write("越過山丘,");
}
}
4. 請求重定向
請求重定向,是指客戶端給伺服器發請求,然後伺服器告訴客戶端說。我給你一些地址。你去新地址訪問。叫請求 重定向(因為之前的地址可能已經被廢棄)
請求重定向的特點:
- 瀏覽器的地址會發生改變
- 兩次請求
- 不能共享Request域中的資料
- 不能訪問WEB-INF下的資源
- 可以訪問工程外的資源
例子如下:訪問Response1重定向到Response2
/**
* @author MD
* @create 2020-07-25 10:15
*/
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Response 1 ");
// // 設定響應狀態碼,表示重定向
// resp.setStatus(302);
//
// // 設定響應頭,說明新的地址,和web.xml裡的要對應
// resp.setHeader("Location","http://localhost:8080/04_Servlet/response2");
// 推薦使用
resp.sendRedirect("http://localhost:8080/04_Servlet/response2");
}
}
//-----------------------------------
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Response 2 ");
resp.getWriter().write("Response2 result !");
}
}
對應的web.xml
<servlet>
<servlet-name>Response1</servlet-name>
<servlet-class>com.md.servlet.Response1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Response1</servlet-name>
<url-pattern>/response1</url-pattern>
</servlet-mapping>
<!---->
<servlet>
<servlet-name>Response2</servlet-name>
<servlet-class>com.md.servlet.Response2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Response2</servlet-name>
<url-pattern>/response2</url-pattern>
</servlet-mapping>