在 Java Web 開發中,Request
?和?Response
?是兩個非常重要的對象,用于在客戶端和服務器之間進行請求和響應的處理,以下是詳細介紹:
Request(請求對象)
Request繼承體系
在 Java Web 開發中,通常涉及到的?request
?對象主要是指?HttpServletRequest
繼承體系如下:
頂層接口:java.util.EventListener
雖然它不是直接與?HttpServletRequest
?功能相關的父類,但從 Java 事件監聽體系角度來說,它是很多相關類間接實現的接口。EventListener
?是所有事件監聽器接口必須實現的標記接口,不過在?HttpServletRequest
?的直接繼承體系中并不直接體現它的影響。
直接相關繼承體系
javax.servlet.ServletRequest
?接口- 這是一個核心的基礎接口,定義了所有 Servlet 請求對象必須實現的基本方法。這些方法提供了獲取請求參數、屬性、請求輸入流等通用功能,使得 Servlet 能夠處理客戶端的請求數據。例如,
getParameter(String name)
?方法用于獲取請求中的參數值。
- 這是一個核心的基礎接口,定義了所有 Servlet 請求對象必須實現的基本方法。這些方法提供了獲取請求參數、屬性、請求輸入流等通用功能,使得 Servlet 能夠處理客戶端的請求數據。例如,
javax.servlet.http.HttpServletRequest
?接口- 繼承自?
ServletRequest
?接口,專門針對 HTTP 請求進行擴展。由于 HTTP 協議是 Web 應用中最常用的協議,HttpServletRequest
?接口添加了許多與 HTTP 協議相關的方法。比如,getMethod()
?可以獲取 HTTP 請求的方法(如 GET、POST 等);getHeader(String name)
?用于獲取 HTTP 請求頭信息。
- 繼承自?
- 具體實現類
- 在不同的 Servlet 容器(如 Tomcat、Jetty 等)中,會有具體的?
HttpServletRequest
?實現類。以 Tomcat 為例,它的實現類是?org.apache.catalina.connector.RequestFacade
。這些實現類會實現?HttpServletRequest
?接口定義的所有方法,完成具體的請求處理邏輯。當客戶端發起請求時,Servlet 容器會創建該實現類的對象,并將其作為參數傳遞給 Servlet 的處理方法(如?doGet
、doPost
),讓開發者可以通過這個對象來處理請求。
- 在不同的 Servlet 容器(如 Tomcat、Jetty 等)中,會有具體的?
需要注意的是,從 Servlet 4.0 開始,包名從?javax.servlet
?變更為?jakarta.servlet
,所以對應的接口變為?jakarta.servlet.ServletRequest
?和?jakarta.servlet.http.HttpServletRequest
,但繼承體系的邏輯結構保持不變。
- 概念:
Request
?對象封裝了客戶端發送給服務器的請求信息,包括請求頭、請求參數、請求方法等。在 Servlet 開發中,常見的實現類是?HttpServletRequest
,它提供了一系列方法來獲取請求相關的數據。 - 主要方法及作用
獲取請求參數
getParameter(String name)
:根據參數名獲取單個參數值,如?String username = request.getParameter("username");
,常用于獲取表單提交的單個數據。getParameterValues(String name)
:獲取指定參數名的所有值(適用于復選框等會提交多個值的情況),返回一個字符串數組。getParameterMap()
:獲取所有請求參數,返回一個?Map<String, String[]>
,其中鍵是參數名,值是參數值數組。
- 獲取請求頭信息:
getHeader(String name)
?用于根據頭名稱獲取請求頭的值,例如?String userAgent = request.getHeader("User - Agent");
?可獲取客戶端瀏覽器信息。 - 獲取請求方法:
getMethod()
?方法返回客戶端發送請求的 HTTP 方法,如 "GET"、"POST" 等。 - 解決亂碼問題:對于 POST 請求,可通過?
setCharacterEncoding("UTF - 8");
?設置字符編碼來解決參數亂碼問題。對于 GET 請求,有時需要額外的編碼轉換操作。 - 請求轉發:
getRequestDispatcher(String path).forward(request, response);
?可實現請求轉發,將當前請求轉發到另一個資源(Servlet、JSP 等),轉發過程在服務器端完成,客戶端地址欄不變。 -
package com.itheima.web;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException;import static javax.servlet.http.HttpUtils.getRequestURL;@WebServlet("/req1") public class RequestDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//String getMethod() 獲取請求方式:GETString method = req.getMethod();System.out.println("method:" + method);//GET//String getContextPath():獲取虛擬目錄(項目訪問路徑):/webDemoString contextPath = req.getContextPath();System.out.println(contextPath);//StringBuffer getRequestURL(): 獲取URL(統一資源定位符):http://localhost:8080/webDemo/req1StringBuffer requestURL = req.getRequestURL();System.out.println(requestURL.toString());//String getReQuestURI():獲取URI(統一資源標識符):/webDemo/req1String requestURI = req.getRequestURI();System.out.println(requestURI);//String getQueryString():獲取請求參數(GET方式):username=zhangsanString queryString = req.getQueryString();System.out.println(queryString);//-----------//獲取請求頭:user-agent:瀏覽器的版本信息String agent = req.getHeader("user-agent");System.out.println(agent);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 獲取Post請求信息用的是IO流,最后打印信息BufferedReader reader = req.getReader();String line = reader.readLine();System.out.println(line);}}
Response(響應對象)
- 概念:
Response
?對象用于封裝服務器對客戶端請求的響應信息,服務器通過它向客戶端發送響應狀態碼、響應頭和響應體等內容。在 Servlet 開發中,常見的實現類是?HttpServletResponse
。 - 主要方法及作用
- 設置響應狀態碼:
setStatus(int sc)
?用于設置 HTTP 響應狀態碼,如?response.setStatus(200);
?表示請求成功,response.setStatus(404);
?表示資源未找到。 - 設置響應頭:
setHeader(String name, String value)
?用于設置響應頭字段,如?response.setHeader("Content - Type", "text/html;charset=UTF - 8");
?設置響應內容類型和字符編碼;response.setHeader("Location", "new - url");
?配合 302 狀態碼用于重定向。 - 重定向:
sendRedirect(String location)
?方法可實現重定向功能,它會設置狀態碼為 302,并設置?Location
?響應頭,讓客戶端重新請求指定的 URL,客戶端地址欄會改變。 - 獲取輸出流
getWriter()
:獲取字符輸出流?PrintWriter
,用于向客戶端輸出文本數據,如 HTML、JSON 等。getOutputStream()
:獲取字節輸出流?ServletOutputStream
,用于輸出二進制數據,如圖片、文件等。但要注意,getWriter()
?和?getOutputStream()
?不能同時使用。
- 設置響應狀態碼:
?如何使用Request和Response對象
在 Java Web 開發中,HttpServletRequest
?和?HttpServletResponse
?對象是處理客戶端請求和發送服務器響應的核心工具。以下詳細介紹它們的常見使用場景和示例代碼:
1. 獲取請求參數
使用?HttpServletRequest
?對象可以方便地獲取客戶端請求中攜帶的參數。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/paramDemo")
public class ParamDemoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 獲取單個參數String username = request.getParameter("username");// 獲取多個參數(如復選框)String[] hobbies = request.getParameterValues("hobby");response.setContentType("text/html;charset=UTF-8");response.getWriter().println("用戶名: " + username);if (hobbies != null) {response.getWriter().println("愛好: ");for (String hobby : hobbies) {response.getWriter().println(hobby);}}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 解決POST請求中文亂碼問題request.setCharacterEncoding("UTF-8");doGet(request, response);}
}
2. 獲取請求頭信息
可以使用?HttpServletRequest
?對象獲取客戶端請求頭中的各種信息。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/headerDemo")
public class HeaderDemoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 獲取指定請求頭String userAgent = request.getHeader("User-Agent");response.setContentType("text/html;charset=UTF-8");response.getWriter().println("User-Agent: " + userAgent);}
}
3. 請求轉發
請求轉發是服務器內部的一種資源跳轉方式,使用?RequestDispatcher
?實現。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/forwardDemo")
public class ForwardDemoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 設置請求屬性request.setAttribute("message", "這是轉發傳遞的消息");// 獲取RequestDispatcher對象request.getRequestDispatcher("/targetServlet").forward(request, response);}
}@WebServlet("/targetServlet")
public class TargetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 獲取請求屬性String message = (String) request.getAttribute("message");response.setContentType("text/html;charset=UTF-8");response.getWriter().println("接收到的消息: " + message);}
}
4. 重定向
重定向會讓客戶端重新向新的 URL 發送請求,使用?HttpServletResponse
?的?sendRedirect
?方法。
package com.itheima.web;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;//本類演示重定向@WebServlet("/resp1")
public class ResponseDemo1 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("resp1...");// 重定向//第一種方法//1. 設置響應狀態碼 302resp.setStatus (302);//2. 設置響應頭 Locationresp.setHeader ("Location","/webDemo/resp2");
//第二種方法// 簡化方式完成重定向resp.sendRedirect ("/webDemo/resp2");}
}
5. 設置響應頭和響應體
使用?HttpServletResponse
?對象可以設置響應頭信息和向客戶端輸出響應體內容。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/responseDemo")
public class ResponseDemoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 設置響應頭response.setContentType("text/html;charset=UTF-8");response.setHeader("Cache-Control", "no-cache");// 獲取字符輸出流,輸出響應體response.getWriter().println("<html><body>");response.getWriter().println("<h1>這是一個響應示例</h1>");response.getWriter().println("</body></html>");}
}
Response響應字節數據
發送字節數據
當需要發送二進制數據,如圖片、音頻、視頻等時,使用?ServletOutputStream
?來發送字節數據。以下是一個簡單的示例,展示如何從服務器讀取圖片文件并將其作為字節數據發送給客戶端:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;@WebServlet("/sendByteData")
public class SendByteDataServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 設置響應內容類型為圖片類型response.setContentType("image/jpeg");// 獲取要發送的圖片文件的輸入流InputStream inputStream = new FileInputStream("path/to/your/image.jpg");// 獲取響應的輸出流OutputStream outputStream = response.getOutputStream();// 定義緩沖區byte[] buffer = new byte[1024];int bytesRead;// 從輸入流讀取數據并寫入輸出流while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}// 關閉輸入流inputStream.close();}
}
代碼解釋:
- 設置響應內容類型:通過?
response.setContentType("image/jpeg")
?設置響應內容類型為 JPEG 圖片類型,讓客戶端知道接收到的是圖片數據。 - 獲取輸入流和輸出流:使用?
FileInputStream
?打開要發送的圖片文件,獲取文件的輸入流;通過?response.getOutputStream()
?獲取響應的輸出流,用于將數據發送給客戶端。 - 數據傳輸:使用一個緩沖區?
byte[] buffer
?從輸入流讀取數據,并將其寫入輸出流,直到文件讀取完畢。 - 關閉輸入流:操作完成后,關閉輸入流以釋放資源。
Response響應字符數據
發送字符數據
當需要發送文本數據,如 HTML、JSON、純文本等時,使用?PrintWriter
?來發送字符數據。以下是一個示例,展示如何向客戶端發送一段 HTML 內容:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/sendCharData")
public class SendCharDataServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 設置響應內容類型和字符編碼response.setContentType("text/html;charset=UTF-8");// 獲取響應的字符輸出流PrintWriter writer = response.getWriter();// 向輸出流寫入 HTML 內容writer.println("<html>");writer.println("<head><title>字符數據響應示例</title></head>");writer.println("<body>");writer.println("<h1>這是一段 HTML 內容</h1>");writer.println("</body>");writer.println("</html>");// 刷新輸出流writer.flush();// 關閉輸出流writer.close();}
}
代碼解釋:
- 設置響應內容類型和字符編碼:通過?
response.setContentType("text/html;charset=UTF-8")
?設置響應內容類型為 HTML 文本,并指定字符編碼為 UTF - 8,確保中文等字符能正確顯示。 - 獲取字符輸出流:使用?
response.getWriter()
?獲取響應的字符輸出流?PrintWriter
。 - 寫入數據:使用?
writer.println()
?方法向輸出流寫入 HTML 內容。 - 刷新和關閉輸出流:調用?
writer.flush()
?方法將緩沖區的數據刷新到客戶端,最后關閉輸出流以釋放資源。
需要注意的是,getOutputStream()
?和?getWriter()
?方法不能同時使用,否則會拋出?IllegalStateException
?異常。
通過以上示例,你可以了解到?HttpServletRequest
?和?HttpServletResponse
?在不同場景下的基本使用方法,它們是 Java Web 開發中處理請求和響應的基礎。