Java Web 响应处理:HttpServletResponse 详解
在 Java Web 开发中,服务器对客户端请求的响应由 HttpServletResponse 对象封装。它负责构建 HTTP 响应消息(状态行、响应头、响应正文),并将结果返回给客户端。本文将详细解析 HttpServletResponse 的核心功能,包括状态码设置、响应头管理、响应正文输出及常见应用场景。
HttpServletResponse 概述
HttpServletResponse 是 ServletResponse 接口的子接口,专门用于处理 HTTP 协议的响应。它由 Servlet 容器创建,通过 service() 方法传递给 Servlet,开发者通过其提供的方法构建响应内容。
1 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { |
状态行处理
HTTP 响应状态行由协议版本、状态码和状态描述组成(如 HTTP/1.1 200 OK)。状态码用于告知客户端请求处理结果,HttpServletResponse 提供以下方法设置状态码:
核心方法
setStatus(int sc):设置状态码(如200表示成功,404表示资源不存在)。sendError(int sc):发送错误状态码,并触发容器的错误页面机制(如404会显示自定义错误页)。sendError(int sc, String msg):发送错误状态码及自定义描述信息。
常见状态码
| 状态码 | 含义 | 常量(HttpServletResponse) | 应用场景 |
|---|---|---|---|
| 200 | 请求成功 | SC_OK |
正常返回响应正文 |
| 302 | 临时重定向 | SC_FOUND |
页面跳转(如登录后跳首页) |
| 400 | 客户端请求错误 | SC_BAD_REQUEST |
参数格式错误 |
| 401 | 未认证 | SC_UNAUTHORIZED |
未登录访问受保护资源 |
| 403 | 权限不足 | SC_FORBIDDEN |
登录后无操作权限 |
| 404 | 资源不存在 | SC_NOT_FOUND |
请求 URL 错误 |
| 500 | 服务器内部错误 | SC_INTERNAL_SERVER_ERROR |
代码抛出异常 |
示例:
1 | // 设置成功状态码(默认即为 200,可省略) |
响应头管理
响应头用于向客户端传递附加信息(如内容类型、缓存策略、重定向地址等)。HttpServletResponse 提供以下方法操作响应头:
核心方法
setHeader(String name, String value):设置响应头,若已存在则覆盖原值。addHeader(String name, String value):添加响应头,若已存在则保留多个值。setIntHeader(String name, int value):设置整数类型响应头(如Content-Length)。setDateHeader(String name, long date):设置日期类型响应头(如Expires,值为毫秒时间戳)。
常用响应头及应用
| 响应头 | 作用描述 | 示例代码 |
|---|---|---|
Content-Type |
指定响应正文的 MIME 类型和编码 | resp.setHeader("Content-Type", "text/html;charset=UTF-8") |
Location |
重定向目标 URL(配合 302 状态码) | resp.setHeader("Location", "/home") |
Cache-Control |
控制客户端缓存策略 | resp.setHeader("Cache-Control", "no-cache") |
Content-Disposition |
指示客户端下载文件 | resp.setHeader("Content-Disposition", "attachment;filename=file.txt") |
Set-Cookie |
向客户端设置 Cookie | 通常通过 addCookie(Cookie cookie) 间接设置 |
示例:设置 JSON 响应及编码
1 | // 设置响应为 JSON 类型,编码 UTF-8 |
示例:控制页面不缓存
1 | resp.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); |
响应正文输出
响应正文是服务器返回给客户端的实际内容(如 HTML、JSON、图片等),通过输出流写入。HttpServletResponse 提供两种输出流:
字符输出流(PrintWriter)
- 用于输出字符数据(如 HTML、JSON 文本),需指定字符编码。
- 方法:
getWriter(),默认编码为ISO-8859-1,需通过setCharacterEncoding("UTF-8")或setContentType(...)设置编码。
示例:输出 HTML 内容
1 | // 设置编码(需在 getWriter() 前调用) |
字节输出流(ServletOutputStream)
- 用于输出二进制数据(如图片、文件下载)。
- 方法:
getOutputStream(),直接操作字节,无需编码设置。
示例:输出图片
1 | // 设置响应类型为 JPEG 图片 |
注意事项
- 流的互斥性:
getWriter()和getOutputStream()不能同时调用,否则会抛出IllegalStateException。 - 编码设置时机:字符编码需在获取
PrintWriter前设置,否则无效。 - 缓冲区刷新:输出流默认带缓冲区,可通过
flush()手动刷新,或在流关闭时自动刷新。
文件下载实现
利用 HttpServletResponse 可实现文件下载功能,核心步骤为:
- 设置
Content-Type为application/octet-stream(二进制流); - 设置
Content-Disposition指示客户端下载并指定文件名; - 通过
ServletOutputStream写入文件字节。
示例:
1 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { |
重定向与请求转发的区别
| 特性 | 重定向(sendRedirect) |
请求转发(RequestDispatcher.forward) |
|---|---|---|
| 客户端感知 | 地址栏 URL 会变化(显示重定向目标) | 地址栏 URL 不变(显示原请求 URL) |
| 跳转范围 | 可跨域、跨应用 | 仅能在当前 Web 应用内 |
| 请求对象 | 新请求(request 对象不同) |
同一请求(request 对象可共享) |
| 响应头设置 | 可设置响应头(如 Location) |
无法设置响应头(已提交) |
| 适用场景 | 登录后跳转、跨应用跳转 | 内部页面跳转(如 MVC 视图渲染) |
示例:重定向到登录页
1 | resp.sendRedirect("/login?error=1"); // 客户端地址栏变为 /login?error=1 |