Spring Boot 中修改 HTTP 响应状态码(即 `response.status`)可以通过以下几种方式实现

news2025/5/25 11:23:04

以下是不同场景下的具体方法:


方法 1:直接使用 @ResponseStatus 注解

在 Controller 方法或异常类上使用 @ResponseStatus 注解,直接指定返回的状态码。

场景示例:固定返回指定状态码
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
    // 成功创建资源时返回 201
    @PostMapping("/create")
    @ResponseStatus(HttpStatus.CREATED) // 状态码 201
    public String createResource() {
        return "Resource created";
    }
}

方法 2:动态返回 ResponseEntity 对象

通过 ResponseEntity 对象在代码中动态控制状态码,适用于需要根据业务逻辑返回不同状态码的场景。

场景示例:根据条件返回不同状态码
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
    @GetMapping("/user/{id}")
    public ResponseEntity<String> getUser(@PathVariable Long id) {
        if (id == 1) {
            return ResponseEntity.ok("User found"); // 默认 200
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found"); // 404
        }
    }
}

方法 3:通过全局异常处理统一修改状态码

使用 @ControllerAdvice@ExceptionHandler 拦截异常并统一设置状态码。

场景示例:资源不存在时返回 404
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import javax.persistence.EntityNotFoundException;

@ControllerAdvice
public class GlobalExceptionHandler {
    // 捕获 EntityNotFoundException 并返回 404
    @ExceptionHandler(EntityNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleEntityNotFound() {
        return "Resource not found";
    }
}

方法 4:直接操作 HttpServletResponse

在 Controller 方法中注入 HttpServletResponse 对象,直接设置状态码。

场景示例:手动设置状态码
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
    @GetMapping("/manual")
    public String manualStatus(HttpServletResponse response) {
        response.setStatus(HttpStatus.ACCEPTED.value()); // 状态码 202
        return "Status manually set";
    }
}

常见场景与状态码对照表

场景推荐状态码说明
成功200 OK默认成功状态码
创建资源成功201 Created配合 @PostMapping 使用
请求参数错误400 Bad Request客户端请求错误
未授权访问401 Unauthorized需要身份验证
禁止访问403 Forbidden无权限访问资源
资源不存在404 Not Found请求的资源不存在
服务器内部错误500 Internal Error未捕获的异常导致服务器错误

注意事项

  1. 优先级问题
    ResponseEntity 的优先级高于 @ResponseStatus,如果二者同时存在,以 ResponseEntity 为准。

  2. 直接操作 HttpServletResponse 的限制
    如果在设置状态码后修改响应体,可能导致 IllegalStateException,建议优先使用 Spring 提供的抽象(如 ResponseEntity)。

  3. 全局异常处理的覆盖范围
    通过 @ControllerAdvice 可以统一处理所有 Controller 抛出的异常,适合集中管理错误状态码。


通过上述方法,你可以根据具体场景灵活控制 HTTP 响应的状态码。推荐优先使用 ResponseEntity@ResponseStatus 保持代码简洁。
以下是结合自定义返回工具类与 Spring Boot 状态码控制的详细方案,提供代码示例和分步说明:


1. 定义统一返回结果工具类

public class ApiResponse<T> {
    private int code;       // 业务状态码(非 HTTP 状态码)
    private String message; // 提示信息
    private T data;         // 返回数据

    // 快速创建成功响应(静态工厂方法)
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "Success", data);
    }

    // 快速创建失败响应(链式调用支持)
    public static ApiResponse<Void> failure(int code, String message) {
        return new ApiResponse<>(code, message, null);
    }

    public ApiResponse<T> code(int code) {
        this.code = code;
        return this;
    }

    public ApiResponse<T> message(String message) {
        this.message = message;
        return this;
    }

    // 构造方法、Getter 省略...
}

2. 与状态码控制方法结合使用

场景 1:固定状态码 + 统一数据结构(@ResponseStatus)
@PostMapping("/users")
@ResponseStatus(HttpStatus.CREATED) // 强制 HTTP 201
public ApiResponse<User> createUser(@RequestBody User user) {
    User savedUser = userService.save(user);
    return ApiResponse.success(savedUser)
                     .message("User created successfully");
}
场景 2:动态状态码 + 统一数据结构(ResponseEntity)
@GetMapping("/products/{id}")
public ResponseEntity<ApiResponse<Product>> getProduct(@PathVariable Long id) {
    return productService.findById(id)
        .map(product -> 
            ResponseEntity.ok(ApiResponse.success(product)) // HTTP 200
        )
        .orElseGet(() -> 
            ResponseEntity.status(HttpStatus.NOT_FOUND)
                          .body(ApiResponse.failure(404, "Product not found"))
        );
}

3. 全局异常处理统一包装结果

@ControllerAdvice
public class GlobalExceptionHandler {

    // 处理业务异常(HTTP 400 + 自定义错误码)
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ApiResponse<Void>> handleBusinessException(BusinessException ex) {
        return ResponseEntity.badRequest() // HTTP 400
            .body(ApiResponse.failure(ex.getCode(), ex.getMessage()));
    }

    // 处理资源不存在(HTTP 404)
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ApiResponse<Void>> handleResourceNotFound(ResourceNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body(ApiResponse.failure(404, ex.getMessage()));
    }

    // 兜底异常处理(HTTP 500)
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<Void>> handleGlobalException(Exception ex) {
        return ResponseEntity.internalServerError()
            .body(ApiResponse.failure(500, "Internal server error"));
    }
}

4. 进阶工具类(支持链式设置 HTTP 状态码)

public class ApiResponseBuilder<T> {
    private HttpStatus httpStatus = HttpStatus.OK; // 默认 200
    private ApiResponse<T> apiResponse;

    private ApiResponseBuilder(ApiResponse<T> apiResponse) {
        this.apiResponse = apiResponse;
    }

    public static <T> ApiResponseBuilder<T> success(T data) {
        return new ApiResponseBuilder<>(ApiResponse.success(data));
    }

    public ApiResponseBuilder<T> httpStatus(HttpStatus status) {
        this.httpStatus = status;
        return this;
    }

    public ResponseEntity<ApiResponse<T>> build() {
        return ResponseEntity.status(httpStatus).body(apiResponse);
    }
}

// 使用示例
@PostMapping("/orders")
public ResponseEntity<ApiResponse<Order>> createOrder() {
    Order newOrder = orderService.create();
    return ApiResponseBuilder.success(newOrder)
                           .httpStatus(HttpStatus.CREATED) // 设置 HTTP 201
                           .build();
}

5. 关键注意事项

  1. 明确区分两类状态码

    • HTTP 状态码:描述网络请求结果(200/404/500)
    • 业务状态码:描述业务逻辑结果(如 1001=库存不足)
  2. 推荐优先级

    • 优先使用 ResponseEntity 控制 HTTP 状态码
    • 使用工具类封装业务状态码
  3. 保持响应结构一致性

    // 成功示例
    {
      "code": 200,
      "message": "Success",
      "data": { "id": 1, "name": "test" }
    }
    
    // 错误示例(HTTP 404)
    {
      "code": 40401,
      "message": "Product not found",
      "data": null
    }
    

通过这种方式,您既可以精准控制 HTTP 协议层的状态码,又能通过工具类统一业务响应格式,同时保持代码的高度可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2385311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux目录介绍+Redis部署(小白篇)

目录 &#x1f451;Linux基础✨【目录】 &#x1f451;Redis 安装1.下载压缩包2.解压3.安装编译环境4.安装到本地5.设置开机自启 &#x1f451;Linux 自启服务 &#x1f451;Linux基础 虽然在大二的时候学过Linux&#xff0c;但是很多基础知识都忘了&#xff0c;想再次从基础捡…

Python 基础语法速查手册:从入门到精通

Python 作为最受欢迎的编程语言之一&#xff0c;以其简洁易读的语法和强大的功能吸引了大量开发者。本文全面汇总 Python 基础语法知识&#xff0c;帮助初学者快速掌握核心概念&#xff0c;并为后续深入学习打下坚实基础。 1. Python 基础语法结构 1.1 代码结构与缩进规则 Py…

论文阅读笔记——Emerging Properties in Unified Multimodal Pretraining

BAGEL 论文 商业闭源系统与学术/开源模型的差距很大&#xff0c;BAGEL 旨在通过开源统一架构大规模交错数据主要解决&#xff1a; 架构割裂&#xff1a;理解/生成分属两条网络&#xff0c;信息被压缩在少量条件 token 中&#xff0c;长上下文推理受限。数据贫乏&#xff1a;主…

JAVA批量发送邮件(含excel内容)

EmailSenderHtmlV1 是读取配置文件《批量发送邮件.xlsx》&#xff0c;配置sheet获取 发件人邮箱 邮箱账号 口令&#xff0c;发送excel数据sheet获取收件人邮箱 抄送人邮箱 邮件标题 第N行开始(N>1,N0默认表头) 第M行结束(M>1,M0默认表头) 附件文件夹…

Linux(Ubuntu)新建文件权限继承问题

当你在一个工作目权限为777的文件下&#xff0c;新建一个文件的时候&#xff0c;就有可能发生&#xff0c;新建的这个文件&#xff0c;权限和其他文件&#xff0c;或者工作目录不一致的问题&#xff0c;我们不可能每次新建一个文件&#xff0c;就要 sudo chmod -R 777 /PATH 所…

Java中的String的常用方法用法总结

1.1 String &#xff08;1&#xff09;声明 &#xff08;2&#xff09;字符串常量 存储字符串数据的容器&#xff1a;private final char value[] 字符串常量都存储在字符串常量池&#xff08;StringTable&#xff09;中 字符串常量池不允许存放两个相同的字符串常量 &#xff…

QGIS如何打开 ARCGIS的mxd工程文件

“SLYR”是一款由著名开源组织“北路开源”开发的一套QGIS兼容和转换ARCGIS样式、工程、设置信息的插件&#xff01;其主要功能为&#xff1a; 最近项目需要&#xff0c;我使用了一些功能&#xff0c;发现其对中文环境及中文信息支持不太好&#xff0c;还有一些其它BUG&#xf…

基于微信小程序的智能问卷调查系统设计与实现(源码+定制+解答)基于微信生态的问卷管理与数据分析系统设计

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

React 如何封装一个可复用的 Ant Design 组件

文章目录 前言一、为什么需要封装组件&#xff1f;二、 仿antd组件的Button按钮三、封装一个可复用的表格组件 (实战)1. 明确需求2. 设计组件 API3. 实现组件代码4. 使用组件 三、封装组件的最佳实践四、进阶优化 总结 前言 作为一名前端开发工程师&#xff0c;在日常项目中&a…

Canvas SVG BpmnJS编辑器中Canvas与SVG职能详解

Canvas详解与常见API 一、Canvas基础 核心特性 • 像素级绘图&#xff1a;Canvas是基于位图的绘图技术&#xff0c;通过JavaScript操作像素实现图形渲染&#xff0c;适合动态、高性能场景&#xff08;如游戏、数据可视化&#xff09;。 • 即时模式&#xff1a;每次绘制需手动…

dify多实例部署,一台机器部署多个dify实例

dify多实例部署 目的 实现在一台机器上&#xff0c;部署多个dify的实例。比如一个部署1.2版本&#xff0c;一个部署1.3版本。废话没有&#xff0c;直接上干货。 前提 你的电脑已经部署了一个dify实例&#xff0c;并成功运行。比如已经部署成功0.15.3版本。 步骤如下&#…

ML 48.机器学习之临床生存树(rpartSurv)

简介机器学习中生存树&#xff08;Survival Tree&#xff09;的原理详解 生存树是结合决策树与生存分析的机器学习模型&#xff0c;主要用于处理带有时间-事件数据&#xff08;包含删失数据&#xff09;的预测问题。其核心目标是&#xff1a;通过树状结构对数据进行递归分割&am…

HarmonyOS 应用开发,如何引入 Golang 编译的第三方 SO 库

本指南基于笔者临时修复的 ohos_golang_go 项目fork&#xff0c;解决HO 应用导入 cgo编译产物时的 crash 问题。 1. 下载 ohos_golang_go git clone https://gitcode.com/deslord/ohos_golang_go.git&#x1f4cc; 该仓库为笔者临时修复版本&#xff0c;修复了 CGO 编译模式下…

一体化雷达波明渠流量计简介

一、技术定义与核心原理 一体化雷达波明渠流量计是基于微波技术的全自动流量监测设备&#xff0c;采用 24G K 波段平面雷达技术&#xff0c;通过非接触式测量方式实现对明渠、河道、排水管网等场景的水位、流速及流量监测。其核心原理是利用雷达发射高频电磁波&#xff0c;经水…

Pr -- 耳机没有Pr输出的声音

问题 很久没更新视频号了&#xff0c;想用pr剪辑一下&#xff0c;结果使用Pr打开后发现耳机没有Pr输出的声音 解决方法 在编辑--首选项-音频硬件中设置音频硬件的输出为当前耳机设备

白皮精读:2024年国家数据基础设施建设指引【附全文阅读】

《国家数据基础设施建设指引》提出建设覆盖数据采集至安全全链条的新型基础设施,目标到 2029 年形成横向联通、纵向贯通的格局,聚焦数据可信流通、算力协同、高速传输、安全保障四大功能,明确技术架构与重点方向,强调政府与市场协同,分阶段推进试点及规模化部署,为数字中…

穿屏技巧:Mac-Windows一套鼠标键盘控制多台设备 (sharemouse6.0-Keygen)| KM-401A

文章目录 引言I sharemouse6.0介绍功能介绍关闭自动更新安装包II 安装系统对应的sharemouse软件Windowsmac版本III 知识扩展:SCP、FTP、SSH文件传输SCP配置SSH密钥免密登录FTP(File Transfer Protocal,文件传输协议)引言 基于USB进行同步键盘和鼠标事件,更流畅。 基于局域…

【写在创作纪念日】基于SpringBoot和PostGIS的各省东西南北四至极点区县可视化

目录 前言 一、空间检索简介 1、空间表结构 2、四至空间检索 二、前后端实现 1、后端实现 2、前端集成 三、成果展示 1、东部省份 2、西部省份 3、南部省份 4、北部省份 5、中部省份 四、总结 前言 在当今数字化时代&#xff0c;地理信息数据的分析与可视化对于众…

如何制作可以本地联网搜索的MCP,并让本地Qwen3大模型调用搜索回答用户问题?

环境: SearXNG Qwen3-32B-FP8 vllm 0.8.5 问题描述: 如何制作可以本地联网搜索的MCP,并让本地Qwen3大模型调用搜索回答用户问题? 解决方案: 一、安装searxng 1.按需新建模型相关文件夹 mkdir MCP chmod 777 /mnt/program/MCP2.配置conda源 nano ~/.condarc nano…

服务器硬盘虚拟卷的处理

目前的情况是需要删除逻辑卷&#xff0c;然后再重新来弄一遍。 数据已经备份好了&#xff0c;所以不用担心数据会丢失。 查看服务器的具体情况 使用 vgdisplay 操作查看服务器的卷组情况&#xff1a; --- Volume group ---VG Name vg01System IDFormat …