Servlet HTTP 状态码
常见状态码的含义、setStatus 与 sendError 的差别、自定义错误页。
Key PointssetStatus 只改状态行,sendError 还会清空缓冲并跳到容器的错误页——要带错误说明就用 sendError。
五类状态码
| Range | Meaning | Typical |
|---|---|---|
| 1xx | 请求已收到,继续 | 100 Continue |
| 2xx | 请求被正确处理 | 200 OK、201 Created、204 No Content |
| 3xx | 需要进一步动作 | 301 永久、302 临时、304 未修改 |
| 4xx | 请求本身有问题 | 400、401、403、404、405、409 |
| 5xx | 服务端处理失败 | 500、502、503、504 |
最常打交道的几个
- 400 Bad Request —— 参数缺失或格式不对,客户端要改请求
- 401 Unauthorized —— 没登录或凭证无效,应带
WWW-Authenticate - 403 Forbidden —— 已认证但无权限,重试无用
- 404 Not Found —— 资源不存在;也可用于隐藏资源存在性
- 405 Method Not Allowed —— 路径对,方法不对
- 500 Internal Server Error —— 未捕获异常,看服务端日志
- 503 Service Unavailable —— 过载或维护,可带
Retry-After
代码里的用法
Java
// 只改状态行,页面内容仍由你写
resp.setStatus(HttpServletResponse.SC_CREATED);
resp.setHeader("Location", "/users/42");
// 清空缓冲、跳到容器错误页,并可带一句说明
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "用户不存在");
// 未认证
resp.setHeader("WWW-Authenticate", "Basic realm=\"app\"");
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
// 限流
resp.setHeader("Retry-After", "30");
resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);自定义错误页
XML
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/errors/404.html</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/WEB-INF/errors/500.jsp</location>
</error-page>Error pages under WEB-INF can only be reached by internal forward, not by typing the URL. exception-type matches along the inheritance chain, so Throwable catches everything.
Never return 200 for a failure. Clients and monitoring branch on the status code; a 200 wrapping an error message breaks retries, alerting and caching alike.
五类状态码
| 范围 | 含义 | 典型 |
|---|---|---|
| 信息 | 请求已收到,继续 | 100 Continue |
| 成功 | 请求被正确处理 | 200 OK、201 Created、204 No Content |
| 重定向 | 需要进一步动作 | 301 永久、302 临时、304 未修改 |
| 客户端错误 | 请求本身有问题 | 400、401、403、404、405、409 |
| 服务端错误 | 服务端处理失败 | 500、502、503、504 |
最常打交道的几个
- 400 Bad Request —— 参数缺失或格式不对,客户端要改请求
- 401 Unauthorized —— 没登录或凭证无效,应带
WWW-Authenticate - 403 Forbidden —— 已认证但无权限,重试无用
- 404 Not Found —— 资源不存在;也可用于隐藏资源存在性
- 405 Method Not Allowed —— 路径对,方法不对
- 500 Internal Server Error —— 未捕获异常,看服务端日志
- 503 Service Unavailable —— 过载或维护,可带
Retry-After
代码里的用法
Java
// 只改状态行,页面内容仍由你写
resp.setStatus(HttpServletResponse.SC_CREATED);
resp.setHeader("Location", "/users/42");
// 清空缓冲、跳到容器错误页,并可带一句说明
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "用户不存在");
// 未认证
resp.setHeader("WWW-Authenticate", "Basic realm=\"app\"");
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
// 限流
resp.setHeader("Retry-After", "30");
resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);自定义错误页
XML
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/errors/404.html</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/WEB-INF/errors/500.jsp</location>
</error-page>错误页放在 WEB-INF 下,只能由容器内部转发访问,用户直接敲 URL 进不去。exception-type 的匹配走继承链,配 Throwable 就是兜底所有异常。
不要给所有异常都返回 200。前端和监控都靠状态码判断成败,200 包着错误信息会让重试、告警、缓存全部失效。