1. 概述

这篇文章会介绍几种在 Spring MVC 控制器中返回自定义 HTTP 状态码的方法。

为什么要自定义状态码?因为 HTTP 协议本身提供了丰富的语义,通过返回合适的状态码,可以让客户端更清楚地知道请求的结果,从而做出更合理的处理。比如,当请求出错时,不同的错误类型返回不同的错误码,客户端就可以展示对应的错误提示给用户。

⚠️ 本文不会介绍如何搭建 Spring MVC 项目,如果你还不熟悉基础环境,可以先参考 Spring MVC 教程

2. 返回自定义状态码的方式

Spring 提供了三种主要方式返回自定义状态码:

  • 使用 ResponseEntity
  • 在异常类上使用 @ResponseStatus 注解
  • 使用 @ControllerAdvice + @ExceptionHandler 全局异常处理(本文不重点介绍,详见 这里

✅ 这些方式不是互斥的,反而可以配合使用,提升代码的灵活性和可维护性。

2.1. 使用 ResponseEntity 返回状态码

这是最常见、最灵活的一种方式。在控制器中返回 ResponseEntity 对象,可以自由控制响应的状态码、头部信息和响应体。

示例代码如下:

@RequestMapping(value = "/controller", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity sendViaResponseEntity() {
    return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE);
}

当客户端发起 GET 请求访问 /controller 时,Spring 会返回一个 406 Not Acceptable 的状态码。

💡 这里我们随便选了一个状态码作为示例,实际开发中你可以返回任何合法的 HTTP 状态码(完整列表见 HTTP 状态码维基百科)。

2.2. 通过抛出异常返回状态码

另一种常见的做法是通过抛出异常,配合 @ResponseStatus 注解来返回特定状态码。

先看控制器方法:

@RequestMapping(value = "/exception", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity sendViaException() {
    throw new ForbiddenException();
}

当访问 /exception 接口时,控制器会抛出一个自定义异常 ForbiddenException

@ResponseStatus(HttpStatus.FORBIDDEN)
public class ForbiddenException extends RuntimeException {}

这个异常类本身没有逻辑代码,所有“返回 403 状态码”的行为都由 @ResponseStatus 注解完成。

✅ 如果你希望返回时带上错误信息,可以这样写:

@ResponseStatus(value = HttpStatus.FORBIDDEN, reason="To show an example of a custom message")
public class ForbiddenException extends RuntimeException {}

⚠️ 虽然技术上你可以让异常返回任意状态码,但从语义上讲,异常更适合用于返回错误类状态码(4xx 和 5xx),不要滥用。

3. 总结

这篇文章介绍了在 Spring MVC 控制器中返回自定义 HTTP 状态码的两种主要方式:

  • ✅ 使用 ResponseEntity 灵活控制响应
  • ✅ 使用 @ResponseStatus 注解搭配异常类返回特定状态码

示例代码可以在 GitHub 示例项目 中找到。


原始标题:Custom Status Codes from Spring Controllers