SpringBoot统一返回结果封装 + 全局异常处理 学习笔记
SpringBoot统一返回结果封装 + 全局异常处理 学习笔记
一、前言
在前后端分离项目开发中,存在两个高频痛点:
- 返回格式不统一:不同接口返回数据结构杂乱,前端需要写多套解析逻辑,维护成本极高;
- 异常分散难管理:代码中到处写
try-catch,重复代码多,异常返回格式不规范。
本节课通过统一Result返回封装类 + 全局异常处理器@RestControllerAdvice 一次性解决以上问题,是企业级后端项目标准基础配置。
二、核心知识点梳理
1. 统一返回格式规范
约定全局返回JSON结构,包含3个固定字段,前端可统一解析:
{
"code": 200, // 状态码:200成功,500服务异常
"message": "提示信息", // 接口说明/异常文案
"data": null // 业务数据,成功时携带,异常时为null
}
2. 核心注解说明
| 注解 | 作用 |
|---|---|
@RestControllerAdvice |
全局REST接口增强,统一拦截所有Controller抛出的异常 |
@ExceptionHandler |
绑定指定异常类型,捕获后自定义返回信息 |
@Data(Lombok) |
自动生成get/set、toString,简化实体类代码 |
三、完整代码实现步骤
步骤1:创建通用返回类 Result<T>
存放路径:com.weitoutiao.common.Result
泛型<T>支持任意类型业务数据返回,内置静态方法快速构建成功/失败响应。
package com.weitoutiao.common;
import lombok.Data;
@Data
public class Result<T> {
// 状态码
private Integer code;
// 提示信息
private String message;
// 业务数据
private T data;
// 私有构造,禁止外部new,统一使用静态方法创建对象
private Result(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
// 成功:携带数据
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}
// 成功:仅返回提示文案,无数据
public static <T> Result<T> success(String message) {
return new Result<>(200, message, null);
}
// 失败:统一服务异常,code固定500
public static <T> Result<T> error(String message) {
return new Result<>(500, message, null);
}
}
步骤2:创建全局异常处理器 GlobalExceptionHandler
存放路径:com.weitoutiao.common.GlobalExceptionHandler
拦截所有Controller抛出的运行时异常,打印堆栈日志并封装成统一Result返回。
package com.weitoutiao.common;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 捕获所有运行时异常
@ExceptionHandler(RuntimeException.class)
public Result<?> handleRuntimeException(RuntimeException e) {
// 打印异常堆栈,方便后端定位bug
e.printStackTrace();
// 异常信息封装统一返回格式
return Result.error(e.getMessage());
}
}
步骤3:改造Controller,使用统一返回体
存放路径:com.weitoutiao.controller.HelloController
所有接口返回值统一改为Result<T>,调用Result.success()快速构建响应。
package com.weitoutiao.controller;
import com.weitoutiao.common.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public Result<String> hello() {
// 调用静态方法,统一封装返回
return Result.success("微头条后端启动成功!");
}
}
步骤4:项目完整目录结构
src/main/java/com/weitoutiao
├── common // 通用工具类包
│ ├── GlobalExceptionHandler // 全局异常处理器
│ └── Result // 统一返回封装类
├── config // 配置类
├── controller // 控制器
│ └── HelloController
├── entity // 实体类
├── mapper // Mybatis Mapper
├── service // 业务层
└── WeiTouTiaoSpringBootApplication // 启动类
四、Postman接口测试验证
操作流程
- 运行主启动类
WeiTouTiaoSpringBootApplication,启动SpringBoot项目; - 打开Postman,新建集合
微头条测试; - 在集合内新增GET请求,命名
hello; - 请求地址填写:
http://localhost:8080/hello; - 点击
Send发送请求,查看返回JSON:
{
"code": 200,
"message": "微头条后端启动成功!",
"data": null
}
异常场景测试拓展(可选)
在接口内手动抛出运行时异常,验证全局异常捕获效果:
@GetMapping("/hello")
public Result<String> hello() {
throw new RuntimeException("服务器内部业务异常");
}
请求后会自动返回统一错误格式:
{
"code": 500,
"message": "服务器内部业务异常",
"data": null
}
五、学习总结
1. 统一返回Result类优势
- 接口输出标准化,前端仅需一套通用解析逻辑;
- 静态工厂方法简化代码,不用每次new对象;
- 泛型兼容字符串、实体、集合等全部业务数据类型。
2. 全局异常处理器优势
- 消除项目中大量冗余
try-catch代码,业务代码更纯粹; - 异常统一拦截、统一返回格式,前后端协作更规范;
- 集中打印异常堆栈,便于线上/线下排查问题。
3. 企业拓展优化方向(后续可完善)
- 自定义业务异常类,区分参数错误、权限不足、数据不存在等不同code;
- 新增参数校验异常
MethodArgumentNotValidException捕获; - 引入日志框架(SLF4J)替换
e.printStackTrace(),持久化异常日志; - 封装分页专用返回对象,拓展
Result分页字段。
六、踩坑记录
- 忘记引入Lombok依赖,
@Data注解失效,实体无get/set方法,接口返回空对象; - 异常处理器未加
@RestControllerAdvice,无法拦截Controller异常; - 启动类未扫描到
common包:正常启动类默认扫描自身及子包,无需额外配置;若分包过深可通过@SpringBootApplication(scanBasePackages = "com.weitoutiao")指定扫描路径。
浙公网安备 33010602011771号