Springboot3 | ResponseEntity 完全使用教程

Spring Boot 3 ResponseEntity 完全使用教程

Springboot3 | 统一返回类设计:从问题到实现一文中,我们通过自定义设计实现了标准化响应封装类,该方案有效确保了RESTful接口响应数据结构的统一性。值得关注的是,Spring Boot框架本身也提供了类似的标准化响应机制实现方案。

ResponseEntity 是 Spring Boot 中控制 HTTP 响应的核心工具------它能让你精准定义响应状态码、响应头、响应体,相比直接返回实体类或字符串,灵活性和规范性提升一个量级。接下来我会用最易懂的方式,结合宠物(Pet)管理的实际场景,带你掌握 ResponseEntity 的所有核心用法。

前置准备

1. 项目基础依赖(Maven)

首先确保你的 Spring Boot 3 项目引入了核心依赖(以 3.2.x 版本为例):

xml 复制代码
<dependencies>
    <!-- Spring Boot Web 核心 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Lombok 简化实体类代码 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- 参数校验(用于后续异常场景) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
</dependencies>

2. 核心实体类 Pet

补全 Pet 类(添加 Lombok 注解简化 getter/setter,参数校验注解用于后续案例):

java 复制代码
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;

@Data // 自动生成getter、setter、toString等方法
public class Pet {
    private Long id;         // 宠物ID(唯一标识)
    
    @NotBlank(message = "宠物名称不能为空")
    private String name;     // 宠物名称
    
    @NotBlank(message = "宠物品种不能为空")
    private String breed;    // 宠物品种(如"金毛"、"布偶猫")
    
    @Min(value = 0, message = "宠物年龄不能为负数")
    private Integer age;     // 宠物年龄(单位:岁)
}

3. 模拟数据层(简化案例,无需数据库)

创建一个简单的 PetService 模拟内存数据操作,避免引入数据库复杂度:

java 复制代码
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;

@Service
public class PetService {
    // 模拟数据库存储宠物数据
    private static final Map<Long, Pet> PET_MAP = new HashMap<>();
    
    // 初始化测试数据
    static {
        PET_MAP.put(1L, new Pet(1L, "旺财", "金毛", 3));
        PET_MAP.put(2L, new Pet(2L, "咪宝", "布偶猫", 2));
    }

    // 根据ID查询宠物
    public Pet getPetById(Long id) {
        return PET_MAP.get(id);
    }

    // 新增宠物
    public Pet addPet(Pet pet) {
        long newId = PET_MAP.size() + 1;
        pet.setId(newId);
        PET_MAP.put(newId, pet);
        return pet;
    }

    // 删除宠物
    public boolean deletePet(Long id) {
        return PET_MAP.remove(id) != null;
    }
}

核心场景案例(结合ApiPost测试)

接下来的所有案例,都基于 PetController 实现,每个场景对应一个真实的 HTTP 业务场景,同时给出 ApiPost 测试步骤。

场景1:查询单个宠物(成功返回200)

业务需求 :根据宠物ID查询详情,存在则返回 200 OK + 宠物数据。
Controller 代码

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/pets")
public class PetController {
    @Autowired
    private PetService petService;

    // 场景1:查询单个宠物(成功返回200)
    @GetMapping("/{id}")
    public ResponseEntity<Pet> getPet(@PathVariable Long id) {
        Pet pet = petService.getPetById(id);
        // ResponseEntity.ok() 等价于 ResponseEntity.status(200).body(pet)
        return ResponseEntity.ok(pet);
    }
}

ApiPost 测试步骤

  1. 新建请求,请求方式选择 GET,URL 填写 http://localhost:8080/pets/1
  2. 点击「发送」,查看响应:
    • 状态码:200 OK;

    • 响应体:

      json 复制代码
      {
          "id": 1,
          "name": "旺财",
          "breed": "金毛",
          "age": 3
      }

场景2:新增宠物(成功返回201 + 自定义响应头)

业务需求 :新增宠物成功后,返回 201 Created(符合 REST 规范),并在响应头中添加 Location(指向新增宠物的查询地址)。
Controller 新增代码

java 复制代码
// 场景2:新增宠物(返回201 + 自定义响应头)
@PostMapping
public ResponseEntity<Pet> addPet(@Valid @RequestBody Pet pet) {
    Pet newPet = petService.addPet(pet);
    // 构建响应:状态码201 + Location响应头 + 新增宠物数据
    return ResponseEntity
            .status(201) // 等价于 ResponseEntity.created(URI.create("/pets/" + newPet.getId()))
            .header("Location", "/pets/" + newPet.getId())
            .body(newPet);
}

ApiPost 测试步骤

  1. 新建请求,请求方式选择 POST,URL 填写 http://localhost:8080/pets

  2. 切换到「Body」标签,选择「JSON」格式,输入请求体:

    json 复制代码
    {
        "name": "小白",
        "breed": "萨摩耶",
        "age": 1
    }
  3. 点击「发送」,查看响应:

    • 状态码:201 Created;

    • 响应头:包含 Location: /pets/3

    • 响应体:

      json 复制代码
      {
          "id": 3,
          "name": "小白",
          "breed": "萨摩耶",
          "age": 1
      }

场景3:删除宠物(成功返回204 无响应体)

业务需求 :删除宠物成功后,返回 204 No Content(无响应体,符合 REST 规范);删除失败则返回 404。
Controller 新增代码

java 复制代码
// 场景3:删除宠物(成功204,失败404)
@DeleteMapping("/{id}")
public ResponseEntity<Void> deletePet(@PathVariable Long id) {
    boolean isDeleted = petService.deletePet(id);
    if (isDeleted) {
        // 204 无响应体,使用 ResponseEntity.noContent().build()
        return ResponseEntity.noContent().build();
    } else {
        // 404 未找到
        return ResponseEntity.notFound().build();
    }
}

ApiPost 测试步骤

  1. 新建请求,请求方式选择 DELETE,URL 填写 http://localhost:8080/pets/3
  2. 点击「发送」,查看响应:
    • 状态码:204 No Content;
    • 响应体:为空(符合规范);
  3. 测试删除不存在的宠物(URL 改为 http://localhost:8080/pets/99):
    • 状态码:404 Not Found。

场景4:查询宠物不存在(返回404 + 错误信息)

业务需求 :查询不存在的宠物时,返回 404 Not Found + 自定义错误提示(而非空响应)。
改造场景1的查询接口

java 复制代码
// 场景4:改造查询接口,不存在则返回404 + 错误信息
@GetMapping("/{id}")
public ResponseEntity<Object> getPet(@PathVariable Long id) {
    Pet pet = petService.getPetById(id);
    if (pet != null) {
        return ResponseEntity.ok(pet);
    } else {
        // 构建自定义错误响应体,状态码404
        Map<String, String> error = new HashMap<>();
        error.put("code", "PET_NOT_FOUND");
        error.put("message", "宠物ID:" + id + " 不存在");
        return ResponseEntity.status(404).body(error);
    }
}

ApiPost 测试步骤

  1. GET 请求 URL 填写 http://localhost:8080/pets/99
  2. 点击「发送」,查看响应:
    • 状态码:404 Not Found;

    • 响应体:

      json 复制代码
      {
          "code": "PET_NOT_FOUND",
          "message": "宠物ID:99 不存在"
      }

场景5:参数校验失败(返回400 + 错误信息)

业务需求 :新增/修改宠物时,参数不符合规则(如年龄负数、名称为空),返回 400 Bad Request + 详细错误提示。
新增全局异常处理器(统一处理参数校验异常)

java 复制代码
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice // 全局异常处理
public class GlobalExceptionHandler {
    // 处理参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        // 遍历所有校验失败的字段,收集错误信息
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        // 返回400 + 错误信息
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors);
    }
}

ApiPost 测试步骤

  1. POST 请求新增宠物,请求体传入非法参数:

    json 复制代码
    {
        "name": "",
        "breed": "哈士奇",
        "age": -1
    }
  2. 点击「发送」,查看响应:

    • 状态码:400 Bad Request;

    • 响应体:

      json 复制代码
      {
          "name": "宠物名称不能为空",
          "age": "宠物年龄不能为负数"
      }

前端测试

以下是极简版的 Axios 请求案例,仅聚焦「前端处理 ResponseEntity 返回内容」的核心逻辑,所有结果直接输出到浏览器控制台:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Axios 处理 ResponseEntity 示例</title>
    <!-- 引入 Axios -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
    <button onclick="sendPetRequest()">发送新增宠物请求</button>

    <script>
        // 核心:发送POST请求并处理ResponseEntity返回内容
        async function sendPetRequest() {
            try {
                // 1. 构造请求参数(与后端Pet实体匹配)
                const petData = {
                    name: "小白",
                    breed: "萨摩耶",
                    age: 1
                };

                // 2. 发送POST请求,调用后端返回ResponseEntity的接口
                const response = await axios.post(
                    'http://localhost:8080/pets', // 后端接口地址
                    petData // 请求体
                );

                // 3. 控制台打印ResponseEntity的核心返回内容(重点!)
                console.log("===== ResponseEntity 返回内容解析 =====");
                console.log("1. HTTP状态码(ResponseEntity.status):", response.status); // 201
                console.log("2. 响应头(ResponseEntity.header设置的内容):", response.headers); // 含Location等
                console.log("3. Location响应头具体值:", response.headers.location); // /pets/3
                console.log("4. 响应体(ResponseEntity.body):", response.data); // 新增的Pet对象
                console.log("========================================");

            } catch (error) {
                // 4. 异常场景:解析错误的ResponseEntity内容
                console.log("===== 错误的ResponseEntity返回内容 =====");
                if (error.response) {
                    // 后端返回了错误的ResponseEntity(如400/404)
                    console.log("错误状态码:", error.response.status); // 400/404等
                    console.log("错误响应体:", error.response.data); // 后端返回的错误信息
                } else {
                    console.log("请求异常:", error.message); // 网络/配置错误
                }
            }
        }
    </script>
</body>
</html>

核心说明(聚焦 ResponseEntity 处理)

  1. response.status :对应后端 ResponseEntity.status(201) 设置的 HTTP 状态码;
  2. response.headers :对应后端 ResponseEntity.header("Location", ...) 设置的响应头;
  3. response.data :对应后端 ResponseEntity.body(...) 设置的响应体(Pet 对象/错误信息);
  4. 错误场景下,error.response.status/error.response.data 可获取后端返回的错误 ResponseEntity 内容(如 400 时的参数错误信息)。

测试步骤

  1. 启动后端 Spring Boot 项目;
  2. 用浏览器打开该 HTML 文件,点击按钮;
  3. 按 F12 打开控制台(Console 标签),即可看到 ResponseEntity 各部分内容的解析结果。

控制台输出示例(成功场景)

复制代码
===== ResponseEntity 返回内容解析 =====
1. HTTP状态码(ResponseEntity.status): 201
2. 响应头(ResponseEntity.header设置的内容): {location: '/pets/3', ...}
3. Location响应头具体值: /pets/3
4. 响应体(ResponseEntity.body): {id: 3, name: '小白', breed: '萨摩耶', age: 1}
========================================

控制台输出示例(错误场景,如参数为空)

复制代码
===== 错误的ResponseEntity返回内容 =====
错误状态码: 400
错误响应体: {name: '宠物名称不能为空', age: '宠物年龄不能为负数'}

核心总结

ResponseEntity 的核心价值是「完全掌控 HTTP 响应」,记住这几个关键用法:

  1. 快捷方法ok()(200)、created()(201)、noContent()(204)、notFound()(404)------ 日常开发优先用,代码更简洁;
  2. 自定义响应status(状态码) + header(键, 值) + body(响应体) ------ 满足特殊业务需求;
  3. 响应体灵活:可以是实体类、Map、字符串,甚至 Void(204 场景);
  4. 结合异常处理:统一返回规范的错误响应,提升接口友好性。

所有案例都能直接复制到项目中运行,用 ApiPost 测试时只需注意端口和请求参数,就能快速验证效果。掌握这些用法后,你的 Spring Boot 接口会更符合 REST 规范,也能应对各种复杂的响应需求。


ResponseEntity 的诞生与演进

ResponseEntity 并非 Spring Boot 专属特性,而是Spring Framework 中用于标准化 HTTP 响应的核心类,其诞生和发展完全围绕 Spring 对 RESTful API 支持的演进展开。

1. 首次诞生:Spring Framework 3.0(2009年)

ResponseEntity 最早出现在 Spring Framework 3.0 版本(正式发布时间:2009年12月17日),是 Spring 为强化 RESTful API 开发能力而新增的核心类。

诞生背景

  • 2000年 Roy Fielding 提出 REST 架构风格后,2000年代后期 RESTful API 逐渐成为主流;
  • Spring 2.x 及更早版本对 HTTP 响应的控制极为繁琐(需手动操作 HttpServletResponse 设置状态码、响应头,或通过 ModelAndView 封装结果),无法优雅适配 REST 规范;
  • Spring 3.0 核心目标之一是「原生支持 RESTful 开发」,因此引入 ResponseEntity,将 HTTP 响应的状态码、响应头、响应体 封装为统一对象,让开发者无需直接操作底层 Servlet API。

2. 关键演进节点(与 Spring Boot 关联)

Spring Boot 是基于 Spring Framework 的封装,其对 ResponseEntity 的支持完全依赖底层 Spring 版本:

框架版本 关键变化
Spring Framework 3.0 首次引入 ResponseEntity,核心能力:封装状态码、响应头、响应体
Spring Framework 4.1 新增大量静态工厂方法(如 ok()notFound()noContent()),简化使用
Spring Framework 5.x 适配响应式编程(WebFlux),新增 ResponseEntity<T> 对响应式类型的支持
Spring Framework 6.x 适配 Jakarta EE 9+(替代 Java EE),包路径从 javax 迁移到 jakarta,但 ResponseEntity 核心逻辑不变
Spring Boot 3.x 基于 Spring Framework 6.x 构建,沿用 ResponseEntity 所有特性,无额外修改

3. 核心定位未变

从 2009 年诞生至今,ResponseEntity 的核心设计目标从未改变:

  • 脱离底层 Servlet API 依赖,以面向对象的方式控制 HTTP 响应;
  • 严格遵循 HTTP 规范,支持所有标准状态码(2xx/4xx/5xx)和自定义响应头;
  • 保持灵活性,响应体可适配任意类型(实体类、Map、字符串等)。

总结

  • 「诞生时间」:2009年(Spring Framework 3.0);
  • 「归属」:Spring Framework 的 spring-web 模块(非 Spring Boot 独创);
  • 「Spring Boot 角色」:仅做集成和简化(如自动配置、无需手动注册 Bean),未改变 ResponseEntity 的核心实现。

你在 Spring Boot 3 中使用的 ResponseEntity,本质是 Spring Framework 6.x 版本的实现,相比 2009 年的初代版本,只是增加了更便捷的静态方法和对 Jakarta EE 的适配,核心能力和设计初衷完全一致。

相关推荐
毕设源码-郭学长1 小时前
【开题答辩全过程】以 高校兼职系统为例,包含答辩的问题和答案
java·spring boot
黄嚯嚯1 小时前
Jackson 多态反序列化详解:基于字段自动选择子类的优雅方案
java
h***38181 小时前
SpringBoot - Cookie & Session 用户登录及登录状态保持功能实现
java·spring boot·后端
一只乔哇噻1 小时前
java后端工程师+AI大模型进修ing(研一版‖day57)
java·开发语言·人工智能·算法·语言模型
十五喵1 小时前
智慧物业|物业管理|基于SprinBoot+vue的智慧物业管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·智慧物业管理系统
Williams101 小时前
Java POI/Excel工具:终结OOM、精度丢失和i18n三大难题
java·开发语言·excel
MaxHua1 小时前
彻底搞懂Spring AOP:概念与实战
java·后端·架构
用户84913717547161 小时前
实战复盘:10W+ QPS 秒杀架构演进(Redis Lua + 分片 + RabbitMQ)
java·架构·设计
b***9101 小时前
idea创建springBoot的五种方式
java·spring boot·intellij-idea