Java Web(5)-Servlet詳解(下)
阿新 • • 發佈:2020-07-29
## 一、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 ,然後在類中
```java
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
```xml
RequestAPIServlet
com.md.servlet.RequestAPIServlet
RequestAPIServlet
/requestAPIServlet
```
### 3. 獲取請求引數
首先在web下面建立html檔案,如下
```html
Title
使用者名稱:
密碼:
愛好:C++ Java Python ``` 然後是對應的java程式碼,以及配置的web.xml(和上面的類似) ```java /** * @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請求的時候,如果使用者名稱輸入的是中文,則會出現中文亂碼的情況,所以需要這樣設定 ```java 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目錄下 - 不可以訪問工程以外的資源 ![](https://img2020.cnblogs.com/blog/1212924/202007/1212924-20200728220347158-702935334.png) 例子如下:通過訪問Servlet1然後轉發到Servlet2去 ```java 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就不展示了,都類似 ```java /** * @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標籤 ![](https://img2020.cnblogs.com/blog/1212924/202007/1212924-20200728220357857-770722003.png) 所以在html檔案中,跳轉的時候若使用相對路徑,指定相對的那個路徑 ```htmlTitle
這是a目錄下的b目錄下的c.html頁面
跳到首頁
```
開發中儘量使用絕對路徑,實在不行就使用base+相對路徑
### 7. web中 / 斜槓的不同意義
在web中 / 是一種絕對路徑
1. / 斜槓被瀏覽器解析,得到的地址就是 http://ip:port
`斜槓 `
2. / 斜槓 如果被伺服器解析,得到的地址是:http://ip:port/工程路徑
- `/servlet1 `
- servletContext.getRealPath(“/”);
- request.getRequestDispatcher(“/”);
3. 特殊情況: response.sendRediect(“/”); 把斜槓傳送給瀏覽器解析。得到 http://ip:port/
## 二、HttpServletResponse 類
### 1. HttpServletResponse 類的作用
HttpServletResponse 類和 HttpServletRequest 類一樣。
每次請求進來,Tomcat 伺服器都會建立一個 Response 物件傳 遞給 Servlet 程式去使用。HttpServletRequest 表示請求過來的資訊,HttpServletResponse 表示所有響應的資訊,
我們如果需要設定返回給客戶端的資訊,都可以通過 HttpServletResponse 物件來進行設定
### 2. 兩個輸出流
| 字元流 | getWriter() | 用於傳字串(常用) |
| ------ | ----------------- | ------------------------ |
| 位元組流 | getOutputStream() | 用於下載(傳遞二進位制資料) |
### 3. 如何往客戶端回傳資料
首先還是先建立一個servlet,配置對應的web.xml
注意中文的亂碼情況
```java
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下的資源
- 可以訪問工程外的資源
![](https://img2020.cnblogs.com/blog/1212924/202007/1212924-20200728220433607-871841761.png)
例子如下:訪問Response1重定向到Response2
```java
/**
* @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
```xml
Response1
com.md.servlet.Response1
Response1
/response1
Response2
com.md.servlet.Response2
Response2
/response2
密碼:
愛好:C++ Java Python ``` 然後是對應的java程式碼,以及配置的web.xml(和上面的類似) ```java /** * @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請求的時候,如果使用者名稱輸入的是中文,則會出現中文亂碼的情況,所以需要這樣設定 ```java 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目錄下 - 不可以訪問工程以外的資源 ![](https://img2020.cnblogs.com/blog/1212924/202007/1212924-20200728220347158-702935334.png) 例子如下:通過訪問Servlet1然後轉發到Servlet2去 ```java 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就不展示了,都類似 ```java /** * @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標籤 ![](https://img2020.cnblogs.com/blog/1212924/202007/1212924-20200728220357857-770722003.png) 所以在html檔案中,跳轉的時候若使用相對路徑,指定相對的那個路徑 ```html