HttpServletResponse 是 Servlet 規範中封裝 HTTP 響應的核心接口。本文系統梳理狀態碼設置、Header 操作、輸出流選擇、重定向、Cookie 管理、內容協商等核心用法,並給出生產級最佳實踐。
// 常用狀態碼常量 (HttpServletResponse)
response.setStatus(HttpServletResponse.SC_OK); // 200
response.setStatus(HttpServletResponse.SC_CREATED); // 201
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); // 400
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
response.setStatus(HttpServletResponse.SC_NOT_FOUND); // 404
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500
// 發送錯誤頁面 (會提交響應)
response.sendError(HttpServletResponse.SC_NOT_FOUND, "資源不存在");
注意:調用 sendError 或 sendRedirect 後響應已提交,不可再寫入 Body。
// 設置單值 Header
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("X-Request-ID", UUID.randomUUID().toString());
response.setDateHeader("Expires", 0); // 日期類 Header 專用
response.setIntHeader("Retry-After", 60); // 整數類 Header 專用
// 多值 Header (如多個 Set-Cookie)
response.addHeader("Set-Cookie", "session=abc; Path=/; HttpOnly");
response.addHeader("Set-Cookie", "token=xyz; Path=/api; Secure");
// 獲取已設置 Header (Servlet 3.0+)
String cacheControl = response.getHeader("Cache-Control");
Collection cookies = response.getHeaders("Set-Cookie");
| 方法 | 返回類型 | 適用場景 | 編碼處理 |
|---|---|---|---|
getWriter() | PrintWriter | 文本輸出 (HTML, JSON, XML, CSV) | 默認 ISO-8859-1,需 setCharacterEncoding("UTF-8") 或 setContentType("text/html;charset=UTF-8") |
getOutputStream() | ServletOutputStream | 二進制輸出 (圖片, 文件下載, PDF, Excel) | 直接寫字節,無編碼轉換 |
鐵律:同一請求中只能調用其中一個,否則拋 IllegalStateException。
public void downloadFile(HttpServletResponse response, File file, String downloadName) throws IOException {
response.setContentType("application/octet-stream");
// 解決中文文件名跨瀏覽器兼容 (RFC 5987)
String encodedName = URLEncoder.encode(downloadName, StandardCharsets.UTF_8).replace("+", "%20");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedName);
response.setContentLengthLong(file.length());
try (FileInputStream fis = new FileInputStream(file);
ServletOutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) > 0) {
os.write(buffer, 0, len);
}
os.flush();
}
}
// 重定向 (客戶端跳轉,地址欄變化,302)
response.sendRedirect(request.getContextPath() + "/login.jsp");
// 轉發 (服務端內部跳轉,地址欄不變) - 需 RequestDispatcher
request.getRequestDispatcher("/error.jsp").forward(request, response);
// 寫入 Cookie
Cookie cookie = new Cookie("userId", "12345");
cookie.setPath("/"); // 生效路徑
cookie.setMaxAge(3600); // 存活秒數,-1=會話級,0=刪除
cookie.setHttpOnly(true); // 防 XSS,JS 不可讀
cookie.setSecure(true); // 僅 HTTPS 傳輸 (需 HTTPS 站點)
cookie.setDomain(".example.com"); // 跨子域共享 (可選)
response.addCookie(cookie);
// 讀取 Cookie
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
if ("userId".equals(c.getName())) { /* ... */ }
}
}
// 手寫 JSON 輸出 (無框架時)
response.setContentType("application/json;charset=UTF-8");
try (PrintWriter writer = response.getWriter()) {
writer.write("{\"code\":200,\"msg\":\"success\",\"data\":{\"id\":1}}");
writer.flush();
}
// 推薦:Jackson 一行搞定
ObjectMapper mapper = new ObjectMapper();
response.setContentType("application/json;charset=UTF-8");
mapper.writeValue(response.getOutputStream(), resultObject); // 直接寫字節流,效率更高
request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8");。Cache-Control: no-store。X-Frame-Options: DENY、X-Content-Type-Options: nosniff、Content-Security-Policy。try-with-resources 自動關閉,避免流洩漏導致連接無法復用。@ControllerAdvice 或 web.xml error-page 統一返回友好錯誤頁/JSON。