首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Web 開發實戰:Servlet 核心 API 操作請求與響應完全指南

     編輯:Java 相關知識

前言:Servlet 是 Java Web 的基石

Servlet 容器(Tomcat/Jetty/Undertow)將 HTTP 請求封裝為 `HttpServletRequest`,響應封裝為 `HttpServletResponse`。掌握這兩個介面的核心 API,等於掌握了 Java Web 開發的「手腳」。本文通過實戰場景,系統梳理動態頁面生成、表單處理、Header/Cookie/Session 操作、重定向與轉發、MIME 類型與狀態碼控制。

一、動態生成 HTML 頁面


@WebServlet("/time")
public class TimeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        resp.setContentType("text/html;charset=UTF-8"); // 必須先設定,否則中文亂碼
        PrintWriter out = resp.getWriter(); // 字符流,適用文本
        
        String html = "

當前時間: " + new Date() + "

"; out.println(html); } }

關鍵點:

  • `resp.setContentType` 必須在 `getWriter()` 前調用,指定 charset 避免亂碼。
  • 二進制輸出(圖片、PDF、Excel)用 `resp.getOutputStream()` 獲取 `ServletOutputStream`。

二、處理表單提交 (POST)

2.1 前端表單


用戶名:
密碼:

2.2 Servlet 處理


@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        // 1. 設置請求編碼 (必須在 getParameter 前)
        req.setCharacterEncoding("UTF-8");
        
        // 2. 獲取參數
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        
        // 3. 業務邏輯 (省略:驗證、加密、入庫)
        
        // 4. 響應
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println("

註冊成功,歡迎 " + username + "!

"); } }

三、Request 核心 API 速查

需求API示例
獲取請求方法`getMethod()``"GET"`, `"POST"`, `"PUT"`
獲取請求 URL`getRequestURL()` / `getRequestURI()``/app/register`
獲取查詢字串`getQueryString()``username=zhang&age=20`
獲取單個參數`getParameter(name)``req.getParameter("username")`
獲取同名多值參數`getParameterValues(name)``String[] hobbies = req.getParameterValues("hobby")`
獲取所有參數 Map`getParameterMap()``Map map = req.getParameterMap()`
獲取 Header`getHeader(name)` / `getHeaders(name)``req.getHeader("User-Agent")`
獲取 Cookie`getCookies()``Cookie[] cookies = req.getCookies()`
獲取 Session`getSession()` / `getSession(false)``HttpSession session = req.getSession()`
獲取輸入流 (文件上傳/JSON)`getInputStream()` / `getReader()``InputStream is = req.getInputStream()`
獲取客戶端 IP`getRemoteAddr()``String ip = req.getRemoteAddr()`
屬性作用域 (請求轉發共享)`setAttribute(name, obj)` / `getAttribute(name)``req.setAttribute("user", userObj)`

四、Response 核心 API 速查

需求API示例
設置內容類型`setContentType(type)``resp.setContentType("application/json;charset=UTF-8")`
設置狀態碼`setStatus(code)``resp.setStatus(HttpServletResponse.SC_NOT_FOUND)`
發送重定向`sendRedirect(location)``resp.sendRedirect("/login.html")` (客戶端跳轉,地址欄變化)
設置 Header`setHeader(name, value)` / `addHeader``resp.setHeader("X-Custom", "value")`
設置 Cookie`addCookie(Cookie)``resp.addCookie(new Cookie("token", "abc123"))`
設置 Content-Length`setContentLength(len)` / `setContentLengthLong``resp.setContentLengthLong(file.length())`
獲取輸出流 (二進制)`getOutputStream()``ServletOutputStream os = resp.getOutputStream()`
獲取字符流 (文本)`getWriter()``PrintWriter out = resp.getWriter()`

五、進階場景實戰

5.1 文件下載


@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        String filename = "report.pdf";
        File file = new File("/data/reports", filename);
        
        resp.setContentType("application/pdf");
        resp.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
        resp.setContentLengthLong(file.length());
        
        try (FileInputStream fis = new FileInputStream(file);
             ServletOutputStream os = resp.getOutputStream()) {
            fis.transferTo(os); // Java 9+ 高效傳輸
        }
    }
}

5.2 JSON API 響應


@WebServlet("/api/user")
public class UserApiServlet extends HttpServlet {
    private final ObjectMapper mapper = new ObjectMapper();
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        User user = userService.findById(req.getParameter("id"));
        
        resp.setContentType("application/json;charset=UTF-8");
        mapper.writeValue(resp.getOutputStream(), user); // 直接寫流,無中間字串
    }
}

5.3 請求轉發 vs 重定向

特性請求轉發 `RequestDispatcher.forward()`重定向 `sendRedirect()`
發起方服務端內部客戶端 (瀏覽器)
地址欄不變改變
請求對象共享同一 request/response新請求,舊 request 失效
可訪問資源WEB-INF 內部資源僅公開 URL
適用場景MVC Controller → JSP、內部流程跳轉登入成功跳首頁、POST 後重定向 (PRG 模式)

// 轉發
req.getRequestDispatcher("/WEB-INF/views/success.jsp").forward(req, resp);

// 重定向 (PRG 模式防重複提交)
resp.sendRedirect(req.getContextPath() + "/order/success");

六、最佳實踐清單

  1. 編碼過濾器: 配置 `CharacterEncodingFilter` (Spring) 或 Filter 統一 `req.setCharacterEncoding("UTF-8")`,避免每個 Servlet 重複。
  2. 輸出編碼: `resp.setContentType("text/html;charset=UTF-8")` 統一放在基類 `BaseServlet` 的 `service()` 方法開頭。
  3. 資源關閉: `try-with-resources` 管理 `InputStream`/`OutputStream`/`Reader`/`Writer`。
  4. 異常處理: `web.xml` 配置 `` 或 Spring `@ControllerAdvice` 統一處理,避免 Servlet 內部 try-catch 泛濫。
  5. 線程安全: Servlet 實例單例,不要**在類成員變量存儲請求相關狀態**,使用請求屬性 `req.setAttribute()` 或局部變量。

結語

`HttpServletRequest`/`HttpServletResponse` 是 Java Web 開發的「方向盤與踏板」。熟練掌握參數獲取、流操作、Header/Cookie/Session 控制、轉發重定向、MIME 與狀態碼,配合編碼過濾器、基類封裝、異常統一處理,即可構建清晰、健壯、高效的 Web 應用。下一篇將進階《Filter 與 Listener:攔截鏈與生命週期監聽實戰》。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved