news 2026/6/10 3:54:30

【Spring Boot + MyBatis|第3篇】统一返回结果 Result 类设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Spring Boot + MyBatis|第3篇】统一返回结果 Result 类设计

前言

上一篇我们学习了 Controller 中常见的三种参数接收方式:@RequestParam、@PathVariable、@RequestBody。

这一篇继续学习一个项目中非常常见的设计:统一返回结果类 Result

在 Spring Boot 项目中,如果每个接口返回的数据格式都不一样,前端处理起来就会很麻烦。比如有的接口返回字符串,有的接口返回对象,有的接口返回列表,有的接口失败时又返回另一种格式。

所以在实际开发中,我们一般会设计一个统一的返回结构,让所有接口都按照同一种格式返回数据。

一、为什么需要统一返回结果?

假设我们不使用统一返回结果,接口可能会这样写。

@GetMapping("/{id}") public Emp getById(@PathVariable Integer id) { return empService.getById(id); }

这个接口直接返回了一个 Emp 对象。

再看另一个接口:

@PostMapping public String save(@RequestBody Emp emp) { empService.save(emp); return "新增成功"; }

这个接口返回的是字符串。

如果删除失败,又可能这样写:

@DeleteMapping("/{id}") public String delete(@PathVariable Integer id) { return "删除失败"; }

这样写虽然能运行,但是问题很明显:接口返回格式不统一。

前端拿到数据后,很难用同一套逻辑判断接口是否成功。

所以我们更希望所有接口都返回类似下面这种格式:

{ "code": 1, "msg": "success", "data": {} }

这样前端只需要判断 code,就能知道接口是否执行成功。

二、Result 类的基本设计

一个基础版的 Result 类通常包含三个字段:

字段含义
code状态码,用来表示成功或失败
msg提示信息
data返回给前端的数据

比如:

public class Result { private Integer code; private String msg; private Object data; }

在学习阶段,我们可以先约定:

code = 1 表示成功 code = 0 表示失败

三、编写 Result 工具类

1. Result 类代码

public class Result { private Integer code; private String msg; private Object data; public Result() { } public Result(Integer code, String msg, Object data) { this.code = code; this.msg = msg; this.data = data; } public static Result success() { return new Result(1, "success", null); } public static Result success(Object data) { return new Result(1, "success", data); } public static Result error(String msg) { return new Result(0, msg, null); } public Integer getCode() { return code; } public String getMsg() { return msg; } public Object getData() { return data; } public void setCode(Integer code) { this.code = code; } public void setMsg(String msg) { this.msg = msg; } public void setData(Object data) { this.data = data; } }

2. 文字说明

这个 Result 类中最核心的是三个静态方法:

Result.success() Result.success(data) Result.error(msg)

如果接口执行成功,但是不需要返回数据,就使用:

return Result.success();

如果接口执行成功,并且需要返回数据,就使用:

return Result.success(data);

如果接口执行失败,就使用:

return Result.error("失败原因");

这样 Controller 层写起来会非常统一。

四、Controller 中如何使用 Result?

1. 查询接口

@GetMapping("/{id}") public Result getById(@PathVariable Integer id) { Emp emp = empService.getById(id); return Result.success(emp); }

2. 新增接口

@PostMapping public Result save(@RequestBody Emp emp) { empService.save(emp); return Result.success(); }

3. 删除接口

@DeleteMapping("/{id}") public Result delete(@PathVariable Integer id) { empService.delete(id); return Result.success(); }

4. 条件分页查询接口

@GetMapping public Result page(Integer page, Integer pageSize, String name) { PageBean pageBean = empService.page(page, pageSize, name); return Result.success(pageBean); }

5. 文字说明

可以看到,Controller 的返回值都统一变成了:

Result

无论是查询、新增、删除,还是分页查询,返回结构都一样。

只不过有的接口有 data,有的接口没有 data。

例如新增成功后返回:

{ "code": 1, "msg": "success", "data": null }

查询成功后返回:

{ "code": 1, "msg": "success", "data": { "id": 1, "name": "张三" } }

这样前端处理起来就会更方便。

五、Service 层要不要返回 Result?

这一点很容易写混。

一般来说,不建议 Service 层直接返回 Result

比如不推荐这样写:

public Result getById(Integer id) { Emp emp = empMapper.getById(id); return Result.success(emp); }

更推荐这样写:

public Emp getById(Integer id) { return empMapper.getById(id); }

然后在 Controller 层统一包装:

@GetMapping("/{id}") public Result getById(@PathVariable Integer id) { Emp emp = empService.getById(id); return Result.success(emp); }

原因很简单:

Result 是返回给前端的响应格式,更适合放在 Controller 层处理。
Service 层更应该关注业务逻辑,而不是关心前端响应格式。

这样分层会更清楚。

六、如果使用 Lombok 可以简化代码

如果项目中引入了 Lombok,可以把 Result 类简化成这样:

@Data @NoArgsConstructor @AllArgsConstructor public class Result { private Integer code; private String msg; private Object data; public static Result success() { return new Result(1, "success", null); } public static Result success(Object data) { return new Result(1, "success", data); } public static Result error(String msg) { return new Result(0, msg, null); } }

这里的:

@Data

会自动生成 get、set、toString 等方法。

@NoArgsConstructor @AllArgsConstructor

会自动生成无参构造和全参构造。

不过如果刚开始学习 Java,不使用 Lombok 也完全可以,手动写 getter、setter 反而更容易理解。

七、Result 类可以进一步优化成泛型

上面的 data 使用的是:

private Object data;

这样写比较简单,但是类型不够明确。

后面项目复杂之后,可以改成泛型:

public class Result<T> { private Integer code; private String msg; private T data; public Result() { } public Result(Integer code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public static <T> Result<T> success(T data) { return new Result<>(1, "success", data); } public static <T> Result<T> success() { return new Result<>(1, "success", null); } public static <T> Result<T> error(String msg) { return new Result<>(0, msg, null); } }

这样写以后,返回类型可以更加清楚。

比如:

public Result<Emp> getById(@PathVariable Integer id) { Emp emp = empService.getById(id); return Result.success(emp); }

表示这个接口返回的 data 类型是 Emp。

不过在初学阶段,使用 Object data 的版本已经够用了。

八、常见问题总结

1. Result 类是不是必须写?

不是语法要求必须写,但是实际项目中非常推荐写。

因为统一返回格式可以让接口更规范,也方便前端统一处理成功和失败。

2. code 一定要用 1 和 0 吗?

不一定。

有的项目会用:

200 表示成功 500 表示服务器错误 401 表示未登录 403 表示无权限

学习阶段用 1 和 0 比较简单,后期可以根据项目规范调整。

3. Result 和 HTTP 状态码有什么关系?

HTTP 状态码是协议层面的状态,比如 200、404、500。

Result 中的 code 是业务层面的状态,用来告诉前端业务是否成功。

在普通后台管理系统中,经常会同时使用:

HTTP 状态码:200 Result.code:1 或 0

也就是说,请求能正常到达后端,HTTP 可以是 200,但是业务可能成功,也可能失败。

4. Mapper 层需要关心 Result 吗?

不需要。

Mapper 层只负责操作数据库,返回实体类、集合、数字等结果即可。

比如:

Emp getById(Integer id); List<Emp> list(); int deleteById(Integer id);

不要在 Mapper 层返回 Result。

九、实际开发中的建议

在项目中使用 Result 类时,可以记住下面几点:

  1. Controller 层统一返回 Result
  2. Service 层返回业务数据,不直接返回 Result
  3. Mapper 层只操作数据库,不关心响应格式
  4. 成功时使用 Result.success()
  5. 失败时使用 Result.error("错误信息")
  6. 返回列表、分页对象、详情对象时放到 data 中

这样代码结构会更加清楚。

十、总结

这一篇主要学习了 Spring Boot 项目中统一返回结果类 Result 的设计。

Result 类的作用就是让所有接口返回同一种格式,常见字段包括 code、msg、data。

它最大的好处是让前后端交互更统一,前端可以通过 code 判断接口是否成功,通过 msg 获取提示信息,通过 data 获取真正的数据。

在分层上,Controller 层负责把业务数据包装成 Result 返回,Service 层负责业务逻辑,Mapper 层负责数据库操作。这样三层职责会更清楚,也更适合后期维护。

下一篇可以继续学习 MyBatis 中非常重要的动态 SQL,也就是 <if>、<where>、<foreach> 的使用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 3:52:10

基于UCIe与3DIC Compiler的高效多芯片设计与IP集成

基于UCIe与3DIC Compiler的高效多芯片设计与IP集成 随着高性能计算、人工智能、汽车电子和移动终端等应用对计算能力与功耗效率要求的不断提升,芯片设计正加速从传统的单片式SoC向多芯片(multi-die)架构演进。通过2.5D/3D先进封装技术,设计者可以将多个异构或同质芯片(又…

作者头像 李华
网站建设 2026/6/10 3:50:01

2026西安代理记账新选择:金税四期下,如何挑选靠谱财税服务商

面对市场上数量众多的财税服务机构&#xff0c;如何结合新政要求、行业特性、本地化服务能力&#xff0c;筛选出稳定、专业、高风控水平的代账合作伙伴&#xff0c;成为西安广大企业主重点关注的问题。本文结合2026年本地财税行业现状&#xff0c;确立全新的服务商评估体系&…

作者头像 李华
网站建设 2026/6/10 3:49:59

小白都能看懂的setState原理,一次吃透!!

react中执行setState更新状态时都做了什么&#xff1f;结论&#xff1a;setState是react中修改组件状态、触发视图更新的一个api。他是一个异步更新的过程&#xff0c;但是不同于setTimeout、promise等异步Api实现&#xff0c;而是react自身的批量更新机制导致的异步&#xff0…

作者头像 李华
网站建设 2026/6/10 3:47:15

ICRA 2026 灵巧手五强争霸:直驱、绳驱、混驱,谁在定义下一代机器人的手

ICRA 2026 灵巧手五强争霸:直驱、绳驱、混驱,谁在定义下一代机器人的手? 一、为什么灵巧手突然卷起来了 2026 年 ICRA 的展区有个肉眼可见的变化:灵巧手展台的数量比上一届翻了至少一倍。舞肌科技、曦诺未来、临界点 AGILINK、灵心巧手、灵巧智能、源升智能——六家中国企…

作者头像 李华
网站建设 2026/6/10 3:44:40

技术文章大纲:Codex安装适配国产信创环境

技术文章大纲&#xff1a;Codex安装适配国产信创环境国产信创环境概述信创产业背景与核心目标&#xff08;自主可控、安全可靠&#xff09;主流国产化平台介绍&#xff08;如麒麟OS、统信UOS、龙芯、飞腾等&#xff09;适配国产环境的常见技术挑战&#xff08;硬件兼容性、软件…

作者头像 李华
网站建设 2026/6/10 3:43:42

SPDX+Syft+Policy引擎打造合规流水线

发散创新&#xff1a;用 SPDXSyftCustom Policy Engine 构建可审计、可落地的开源合规流水线 在企业级软件交付中&#xff0c;开源合规已不再是法务部门的“事后检查单”&#xff0c;而是研发流程中必须前置嵌入的硬性质量门禁。据 Linux Foundation 2023 年《Open Source Com…

作者头像 李华