Servlet 服务器 HTTP 响应
HttpServletResponse 设置状态码、响应头、内容类型与输出流。
Key Points先 setContentType 和 setHeader,再取 Writer 写内容;一旦提交(flush)就不能再改状态码和头。
响应头的方法
| Method | Purpose |
|---|---|
| setContentType() | text/html;charset=UTF-8 |
| setCharacterEncoding() | 只设编码,不改 MIME |
| setHeader() | 覆盖同名头 |
| addHeader() | 保留已有值再加一个 |
| setStatus() | 只改状态行 |
| sendError() | 状态码 + 容器错误页 |
| sendRedirect() | 302 + Location |
设置响应头
Java
@WebServlet("/resp")
public class RespServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.setHeader("X-App-Version", "1.4.2");
resp.addHeader("Cache-Control", "no-store");
resp.setDateHeader("Expires", 0); // 立刻过期
try (PrintWriter out = resp.getWriter()) {
out.println("<h1>响应头已设置</h1>");
}
}
}Output
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
X-App-Version: 1.4.2
Cache-Control: no-store
Expires: Thu, 01 Jan 1970 00:00:00 GMT文件下载
Java
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition",
"attachment; filename=\"report.csv\"");
try (InputStream in = getServletContext().getResourceAsStream("/WEB-INF/report.csv");
OutputStream os = resp.getOutputStream()) {
in.transferTo(os);
}Downloads need Content-Disposition: attachment, otherwise the browser renders the file inline. Chinese filenames must be RFC 5987 encoded as filename*=UTF-8''... to avoid mojibake in older browsers.
Writer 与 OutputStream 只能选一个
getWriter() writes characters, getOutputStream() writes bytes. Calling both on one response throws IllegalStateException. Use the stream for files, the writer for HTML.
Once a response is flushed it is already on the wire; later
setStatus or setHeader calls are silently ignored — the classic cause of "I set 404 but got 200". Change the status before writing any content.响应头的方法
| 方法 | 用途 |
|---|---|
| 内容类型 | text/html;charset=UTF-8 |
| 字符集 | 只设编码,不改 MIME |
| 设置头 | 覆盖同名头 |
| 追加头 | 保留已有值再加一个 |
| 状态码 | 只改状态行 |
| 错误响应 | 状态码 + 容器错误页 |
| 重定向 | 302 + Location |
设置响应头
Java
@WebServlet("/resp")
public class RespServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.setHeader("X-App-Version", "1.4.2");
resp.addHeader("Cache-Control", "no-store");
resp.setDateHeader("Expires", 0); // 立刻过期
try (PrintWriter out = resp.getWriter()) {
out.println("<h1>响应头已设置</h1>");
}
}
}Output
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
X-App-Version: 1.4.2
Cache-Control: no-store
Expires: Thu, 01 Jan 1970 00:00:00 GMT文件下载
Java
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition",
"attachment; filename=\"report.csv\"");
try (InputStream in = getServletContext().getResourceAsStream("/WEB-INF/report.csv");
OutputStream os = resp.getOutputStream()) {
in.transferTo(os);
}下载必须用 Content-Disposition: attachment,否则浏览器会尝试直接渲染。文件名含中文时要按 RFC 5987 编码成 filename*=UTF-8''...,否则老浏览器乱码。
Writer 与 OutputStream 只能选一个
getWriter() 输出字符,getOutputStream() 输出字节。同一个响应里调用两个会抛 IllegalStateException。下文件用流,写 HTML 用 Writer。
响应一旦
flush() 就已经发给客户端,之后再 setStatus 或 setHeader 全部无效且不报错——这是「明明设了 404 却返回 200」的典型原因。要改状态码必须在写任何内容之前。