找回密码
立即注册
搜索
发回帖 发新帖

4912

积分

0

好友

626

主题
发表于 1 小时前 | 查看: 4| 回复: 0

简介

Graceful Response 是一个面向 Spring Boot 技术栈的优雅响应处理器。它提供一站式统一返回值封装、全局异常处理、自定义异常错误码等功能。借助它进行 Web 接口开发,既能显著提升效率,也能让代码逻辑更清晰、可读性更好。

本项目案例工程代码:https://github.com/feiniaojin/graceful-response-example.git ,注意选择最新版本分支。

Spring Boot 版本 Graceful Response 版本 graceful-response-example 分支
2.x 3.2.1-boot2 3.2.0-boot2
3.x 3.2.1-boot3 3.2.0-boot3

注意,3.2.1-boot2 版本的 Graceful Response 源码由单独仓库维护,地址为 https://github.com/feiniaojin/graceful-response-boot2 。3.2.1-boot2 和 3.2.1-boot3 除了支持的 Spring Boot 版本不同,其他实现完全一致。Maven 引用时只需根据对应的 Spring Boot 版本选择 Graceful Response 的 version,两者的 groupId、artifactId 一致。

快速入门

Spring Boot 接口开发现状

目前,业界使用 Spring Boot 进行 接口开发 时,往往存在效率低下、重复劳动、可读性差等问题。下面这段伪代码大家应该很熟悉,很多项目里的 Controller 接口都长这样:

@Controller
public class Controller {

    @GetMapping("/query")
    @ResponseBody
    public Response query(Map<String, Object> paramMap) {
        Response res = new Response();
        try {
            // 1.校验 params 参数合法性,包括非空校验、长度校验等
            if (illegal(paramMap)) {
                res.setCode(1);
                res.setMsg("error");
                return res;
            }
            // 2.调用 Service 的一系列操作,得到查询结果
            Object data = service.query(params);
            // 3.将操作结果设置到 res 对象中
            res.setData(data);
            res.setCode(0);
            res.setMsg("ok");
            return res;
        } catch (Exception e) {
            // 4.异常处理:手写 try...catch,有错误码时还需要手工填充
            res.setCode(1);
            res.setMsg("error");
            return res;
        }
    }
}

这段代码存在哪些问题?

第一个问题,效率低下。Controller 层的代码本来应该尽量简洁,上面的伪代码其实只是为了把查询结果封装成统一格式返回。例如以下响应体:

{
  "code": 0,
  "msg": "ok",
  "data": {
    "id": 1,
    "name": "username"
  }
}

查询过程中如果发生异常,就需要在 Controller 手工捕获,再人工设置错误码,用同样的格式封装后返回。也就是说,除了调用 service 层的 query 方法那一行,其余大量代码都在做结果封装,冗余且低价值。

第二个问题,重复劳动。捕获异常、封装执行结果这些操作每个接口都会重复一遍。

第三个问题,可读性低。核心业务代码被淹没在大量冗余代码里,阅读起来就像大海捞针。

借助 Graceful Response 组件,可以解决这些问题。

快速入门

引入 Graceful Response 组件

Graceful Response 已发布到 Maven 中央仓库,可以直接引入。

<dependency>
  <groupId>com.feiniaojin</groupId>
  <artifactId>graceful-response</artifactId>
  <version>{latest.version}</version>
</dependency>
Spring Boot 版本 Graceful Response 最新版本
2.x 3.2.1-boot2
3.x 3.2.1-boot3

启用 Graceful Response

在启动类中引入 @EnableGracefulResponse 注解,即可启用组件。

@EnableGracefulResponse
@SpringBootApplication
public class ExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

Controller 层

引入 Graceful Response 后,不需要手工封装查询结果,直接返回实际结果即可,组件会自动完成封装。

Controller 层示例如下:

@Controller
public class Controller {

    @RequestMapping("/get")
    @ResponseBody
    public UserInfoView get(Long id) {
        log.info("id={}", id);
        return UserInfoView.builder().id(id).name("name" + id).build();
    }
}

示例中 Controller 方法直接返回 UserInfoView 对象,没有做封装操作,但经过 Graceful Response 处理后,仍能得到以下响应:

{
  "status": {
    "code": "0",
    "msg": "ok"
  },
  "payload": {
    "id": 1,
    "name": "name1"
  }
}

对于命令操作,默认不需要返回数据,因此命令操作的方法返回值应为 void。Graceful Response 对返回值类型 void 的方法同样会自动封装。

public class Controller {

    @RequestMapping("/command")
    @ResponseBody
    public void command() {
        // 业务操作
    }
}

成功调用该接口后返回:

{
  "status": {
    "code": "200",
    "msg": "success"
  },
  "payload": {}
}

Service 层

引入 Graceful Response 之前,有些开发者在 Service 层方法中直接返回 Response,淹没了方法正常的返回值。

Response 的定义如下:

// lombok 注解
@Data
public class Response {
    private String code;
    private String msg;
    private Object data;
}

直接返回 Response 的 Service 层方法:

/**
 * 直接返回 Response 的 Service
 * 不规范
 */
public interface Service {
    public Response commandMethod(Command command);
}

Graceful Response 引入 @ExceptionMapper 注解,通过它把异常和错误码关联起来。这样 Service 方法就不需要再维护响应码,直接抛出业务异常,由组件完成异常与响应码的映射。

@ExceptionMapper 用法如下:

/**
 * NotFoundException 的定义,使用 @ExceptionMapper 注解修饰
 * code:代表接口的异常码
 * msg:代表接口的异常提示
 */
@ExceptionMapper(code = "1404", msg = "找不到对象")
public class NotFoundException extends RuntimeException {
}

Service 接口定义:

public interface QueryService {
    UserInfoView queryOne(Query query);
}

Service 接口实现:

public class QueryServiceImpl implements QueryService {

    @Resource
    private UserInfoMapper mapper;

    @Override
    public UserInfoView queryOne(Query query) {
        UserInfo userInfo = mapper.findOne(query.getId());
        if (Objects.isNull(userInfo)) {
            // 这里直接抛自定义异常
            throw new NotFoundException();
        }
        // ……后续业务操作
    }
}

当 queryOne 方法抛出 NotFoundException 时,Graceful Response 会捕获异常,将异常对应的异常码和异常信息封装到统一响应对象中,最终返回:

{
  "status": {
    "code": "1404",
    "msg": "找不到对象"
  },
  "payload": {}
}

参数校验

Graceful Response 对 JSR-303 数据校验规范和 Hibernate Validator 做了增强。它自身不提供参数校验功能,但配合 Hibernate Validator 使用后,可以通过 @ValidationStatusCode 注解为参数校验结果指定业务码,并统一封装返回。

例如 UserInfoQuery:

@Data
public class UserInfoQuery {

    @NotNull(message = "userName is null !")
    @Length(min = 6, max = 12)
    @ValidationStatusCode(code = "520")
    private String userName;
}

上例中 userName 定义了两个校验规则。未引入 Graceful Response 时,校验失败会直接抛异常;如果引入组件但没有加 @ValidationStatusCode,则以默认错误码返回。这里因为指定了 code=520,userName 字段任意校验不通过时,都会统一返回错误码 520:

{
  "status": {
    "code": "520",
    "msg": "userName is null !"
  },
  "payload": {}
}

对于 Controller 层直接校验方法入参的场景,Graceful Response 也做了增强:

public class Controller {

    @RequestMapping("/validateMethodParam")
    @ResponseBody
    @ValidationStatusCode(code = "1314")
    public void validateMethodParam(
            @NotNull(message = "userId不能为空") Long userId,
            @NotNull(message = "userName不能为空") Long userName) {
        // 省略业务逻辑
    }
}

如果该方法入参校验触发 userId 和 userName 的校验异常,返回错误码 1314:

{
  "status": {
    "code": "1314",
    "msg": "userId不能为空"
  },
  "payload": {}
}

自定义 Response 格式

Graceful Response 内置两种响应风格,通过 graceful-response.response-style 配置。

配置 graceful-response.response-style=0(或不配置,默认),返回:

{
  "status": {
    "code": 1007,
    "msg": "有内鬼,终止交易"
  },
  "payload": {
  }
}

配置 graceful-response.response-style=1,返回:

{
  "code": "1404",
  "msg": "not found",
  "data": {
  }
}

如果这两种格式都不满足业务需要,Graceful Response 也支持 自定义 Response 格式。具体技术实现可查阅组件文档。

本项目还提供以下进阶功能:

  • 第三方组件集成(Swagger、Actuator 等)
  • 自定义响应
  • 异常请求放行
  • 异常别名
  • 常用配置项

目前该组件在 GitHub 上已经有两百多 Star,很多朋友已经开始使用,可以通过下方链接了解:

https://github.com/feiniaojin/graceful-response

如果你在落地统一响应封装时遇到问题,也欢迎到云栈社区一起交流。




上一篇:MediaCrawler 基于 Playwright 一键抓取小红书、抖音、B 站等 7 平台公开数据
下一篇:WebSocket 入门到实践:Java 与 Spring Boot 实时通信全指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-8 03:55 , Processed in 0.091033 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表