1. 简介
在 Spring MVC 中,有多种方式可以设置 HTTP 响应的状态码。
本文将介绍其中最简单直接的一种:使用 @ResponseStatus
注解。✅
这个注解虽然小,但在控制 REST 接口返回状态时非常实用,尤其适合那些希望代码简洁、语义清晰的开发者。踩坑多了你会发现,状态码管理混乱是线上问题的常见诱因之一。
2. 用于 Controller 方法
默认情况下,当一个接口成功执行后,Spring 会返回 HTTP 200(OK)状态码。
但我们可以通过 @ResponseStatus
注解来显式指定某个 Controller 方法的响应状态码。该注解提供两个等价参数用于指定状态:
code
value
⚠️ 二者作用完全相同,可互换使用,推荐统一用
code
提高可读性。
举个“经典”的例子(RFC 2324 开玩笑用的):
@ResponseStatus(HttpStatus.I_AM_A_TEAPOT)
void teaPot() {}
调用这个接口时,客户端会收到 418 I'm a teapot
状态码。虽然不实用,但说明了用法足够灵活。
自定义错误信息
你还可以通过 reason
参数附加一条错误描述:
@ResponseStatus(HttpStatus.BAD_REQUEST, reason = "Some parameters are invalid")
void onIllegalArgumentException(IllegalArgumentException exception) {}
⚠️ 但注意:只要设置了 reason
,Spring 就会调用 HttpServletResponse.sendError()
,这会导致:
- 返回的是 HTML 错误页面
- 不适合用于 RESTful API(我们通常期望返回 JSON)
所以,在构建前后端分离或对外提供的 REST 接口时,不要设置 reason
字段 ❌
执行前提
✅ @ResponseStatus
只有在被标记的方法正常完成(未抛出异常) 时才会生效。
换句话说:方法没出错,才走这个注解定义的状态码逻辑。
3. 与异常处理器结合使用
除了用于正常流程,@ResponseStatus
更常见的用途是配合异常处理机制,将 Java 异常映射为对应的 HTTP 状态码。
Spring 支持以下三种方式实现这一功能:
- 使用
@ExceptionHandler
在控制器内处理异常 - 使用
@ControllerAdvice
全局统一处理 - 直接在自定义异常类上标注
@ResponseStatus
前两种需要编写异常处理方法,细节可参考 Baeldung 的 Spring REST 异常处理文章。这里重点讲第三种——最简单粗暴且高内聚的方式。
方式一:@ExceptionHandler
@ExceptionHandler(CustomException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void handleCustomException() {
// 日志记录、监控上报等
}
这种方式适用于需要对不同异常做差异化处理的场景。
方式二:@ControllerAdvice
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ValidationException.class)
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
public void handleValidation(ValidationException e) {
// 统一处理校验异常
}
}
适合全局异常拦截,是现代 Spring Boot 项目中最常见的做法。
方式三:直接标记异常类(推荐)
如果你的异常和状态码之间有一一对应关系,且不需要动态响应体,那最干净的做法是——**直接在异常类上加 @ResponseStatus
**:
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
class CustomException extends RuntimeException {}
这样,只要这个异常被 Spring 捕获(无论是否在 @ControllerAdvice
中处理),框架就会自动将其转换为指定的 HTTP 状态码。
注意事项 ⚠️
- 一旦异常类被
@ResponseStatus
标记,Spring **总会调用sendError()
**,即使没有设置reason
- 这意味着:返回的是容器默认的错误页(HTML),不适合 REST 接口
- 如果你希望返回 JSON 格式的错误响应,应避免使用此方式,转而使用
@ExceptionHandler
手动构造响应体 ✅
继承行为
- 子类会继承父类的
@ResponseStatus
配置 - 除非子类自己也标注了
@ResponseStatus
,此时以子类为准
例如:
@ResponseStatus(HttpStatus.BAD_REQUEST)
class BusinessException extends RuntimeException {}
class InvalidOrderException extends BusinessException {}
// 自动获得 400 状态码
4. 总结
@ResponseStatus
是一个轻量级但强大的工具,适用于多种场景下的 HTTP 状态码设置:
使用场景 | 是否推荐 | 说明 |
---|---|---|
正常接口返回非 200 状态 | ✅ 推荐 | 如创建资源返回 201 |
异常类直接标注状态码 | ⚠️ 谨慎 | 会触发 sendError() ,返回 HTML |
REST API 错误响应 | ❌ 不推荐直接用 | 应结合 @ExceptionHandler 返回 JSON |
✅ 最佳实践建议:
- 对于 REST 接口,优先使用
@ControllerAdvice + @ExceptionHandler
,手动控制响应格式 - 若只是想改变成功状态码(如 POST 返回 201),直接在方法上加
@ResponseStatus
简单高效 - 自定义异常类上加
@ResponseStatus
仅适用于非 REST 场景或已有错误页体系的项目
示例代码已托管至 GitHub:https://github.com/baeldung/spring-web-modules/tree/master/spring-mvc-basics-5