SpringBoot3实现统一结果封装的示例代码

 更新时间:2024年03月14日 11:00:34   作者:蒾酒  
Spring Boot进行统一结果封装的主要目的是提高开发效率、降低代码重复率,并且提供一致的API响应格式,从而简化前后端交互和错误处理,所以本文给大家介绍了SpringBoot3实现统一结果封装的方法,需要的朋友可以参考下

前置条件

已经初始化好一个spring boot项目且版本为3X,项目可正常启动。

作者版本为3.2.2

初始化教程:

新版idea(2023)创建spring boot3项目

封装目的

Spring Boot进行统一结果封装的主要目的是提高开发效率、降低代码重复率,并且提供一致的API响应格式,从而简化前后端交互和错误处理

具体好处如下:

  • 方便前端处理:前端可以统一根据返回格式进行处理,而不用关注具体的返回类型和内容。
  • 提高 API 的可读性和可维护性:统一结果封装可以使 API 的返回更加规范化,统一了 API 返回结果的格式,使得代码更加易于阅读和维护。
  • 增加系统的健壮性:通过统一结果封装,能够更好地处理错误和异常情况,从而增加系统的健壮性和稳定性。
  • 统一日志输出:通过统一结果封装,可以方便地记录请求参数、请求结果、异常信息等,方便后续的日志分析和排查问题。

常用格式

最常用的格式为状态码、提示信息、携带数据如图

具体格式还要看团队,这里我就使用这种通用的格式。

定义返回结果枚举类

通过使用这样的枚举类有助于避免硬编码的状态码和消息,提高了代码的可维护性。

import lombok.Getter;
 
/**
 * @author mijiupro
 */
@Getter
public enum ResultEnum {
 
    /* 成功状态码 */
    SUCCESS(1, "操作成功!"),
 
    /* 错误状态码 */
    FAIL(0, "操作失败!"),
 
    /* 参数错误:10001-19999 */
    PARAM_IS_INVALID(10001, "参数无效"),
    PARAM_IS_BLANK(10002, "参数为空"),
    PARAM_TYPE_BIND_ERROR(10003, "参数格式错误"),
    PARAM_NOT_COMPLETE(10004, "参数缺失"),
 
    /* 用户错误:20001-29999*/
    USER_NOT_LOGGED_IN(20001, "用户未登录,请先登录"),
    USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),
    USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
    USER_NOT_EXIST(20004, "用户不存在"),
    USER_HAS_EXISTED(20005, "用户已存在"),
 
    /* 系统错误:40001-49999 */
    FILE_MAX_SIZE_OVERFLOW(40003, "上传尺寸过大"),
    FILE_ACCEPT_NOT_SUPPORT(40004, "上传文件格式不支持"),
 
    /* 数据错误:50001-599999 */
    RESULT_DATA_NONE(50001, "数据未找到"),
    DATA_IS_WRONG(50002, "数据有误"),
    DATA_ALREADY_EXISTED(50003, "数据已存在"),
    AUTH_CODE_ERROR(50004, "验证码错误"),
 
 
    /* 权限错误:70001-79999 */
    PERMISSION_UNAUTHENTICATED(70001, "此操作需要登陆系统!"),
 
    PERMISSION_UNAUTHORIZED(70002, "权限不足,无权操作!"),
 
    PERMISSION_EXPIRE(70003, "登录状态过期!"),
 
    PERMISSION_TOKEN_EXPIRED(70004, "token已过期"),
 
    PERMISSION_LIMIT(70005, "访问次数受限制"),
 
    PERMISSION_TOKEN_INVALID(70006, "无效token"),
 
    PERMISSION_SIGNATURE_ERROR(70007, "签名失败");
 
    // 状态码
    int code;
    // 提示信息
    String message;
 
    ResultEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }
 
    public int code() {
        return code;
    }
 
    public String message() {
        return message;
    }
 
    public void setCode(int code) {
        this.code = code;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
}

定义返回结果封装类

import com.mijiu.commom.enumerate.ResultEnum;
import lombok.Data;
 
 
/**
 * @author mijiupro
 */
 
@Data
public class Result<T> {
 
    // 操作代码
    Integer code;
 
    // 提示信息
    String message;
 
    // 结果数据
    T data;
 
    public Result(ResultEnum resultCode) {
        this.code = resultCode.code();
        this.message = resultCode.message();
    }
 
    public Result(ResultEnum resultCode, T data) {
        this.code = resultCode.code();
        this.message = resultCode.message();
        this.data = data;
    }
    public Result(String message) {
        this.message = message;
    }
    //成功返回封装-无数据
    public static Result<String> success() {
        return new Result<String>(ResultEnum.SUCCESS);
    }
    //成功返回封装-带数据
    public static <T> Result<T> success(T data) {
        return new Result<T>(ResultEnum.SUCCESS, data);
    }
    //失败返回封装-使用默认提示信息
    public static Result<String> error() {
        return new Result<String>(ResultEnum.FAIL);
    }
    //失败返回封装-使用返回结果枚举提示信息
    public static Result<String> error(ResultEnum resultCode) {
        return new Result<String>(resultCode);
    }
    //失败返回封装-使用自定义提示信息
    public static Result<String> error(String message) {
        return new Result<String>(message);
 
    }
}

对返回结果封装

此时我们就可以使用封装类封装统一格式的响应了

import com.mijiu.common.result.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @author mijiupro
 */
@RestController
@RequestMapping("/test1")
public class Test1Controller {
    @GetMapping("/hello")
    public Result<String> hello() {
        return Result.success("hello world");
    }
}

我们的接口通常有很多,如果对每个接口都封装属于重复劳动,可以利用AOP技术拦截控制类的返回结果进行封装。

代码如下

import cn.hutool.json.JSONUtil;
import com.mijiu.commom.result.Result;
import io.micrometer.common.lang.NonNullApi;
import io.micrometer.common.lang.Nullable;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 
/**
 * 统一结果封装增强器
 * @author mijiupro
 */
@RestControllerAdvice(basePackages = "com.mijiu.controller")//指定要增强的包
@NonNullApi
public class ResultAdvice implements ResponseBodyAdvice<Object> {
 
    /**
     * 判断是否支持对返回类型的处理
     *
     * @param returnType    方法参数的类型
     * @param converterType 转换器的类型
     * @return 是否支持处理
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
 
    /**
     * 在写入响应体之前对返回结果进行处理和封装
     *
     * @param body                  返回结果对象
     * @param returnType            方法参数的类型
     * @param selectedContentType   响应内容的类型
     * @param selectedConverterType 转换器的类型
     * @param request               HTTP 请求对象
     * @param response              HTTP 响应对象
     * @return 处理后的返回结果
     */
    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType,
                                  MediaType selectedContentType, Class selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        //当返回结果为字符串类型需要单独处理
        if (body instanceof String) {
            // 如果返回结果是字符串类型,将其封装为成功的结果对象,并转换为 JSON 字符串
            return JSONUtil.toJsonStr(Result.success(body));
        }
 
        // 将返回结果封装为成功的结果对象
        return Result.success(body);
    }
}

此代码可以兼容任何类型的返回结果对其进行统一封装。

为何遇到方法的返回结果是String类型需要手动转成json返回呢?

测试封装

现在com.mijiu.controller下的所有控制类的所有方法都会被拦截将返回结果进行统一格式封装。

到这里返回结果统一封装结束。

以上就是SpringBoot3实现统一结果封装的示例代码的详细内容,更多关于SpringBoot3统一结果封装的资料请关注脚本之家其它相关文章!

相关文章

  • JAVA实现经典游戏坦克大战的示例代码

    JAVA实现经典游戏坦克大战的示例代码

    小时候大家都玩过坦克大战吧,熟悉的旋律和丰富的关卡陪伴了我们一整个寒暑假。本文将通过Java+Swing实现这一经典游戏,感兴趣的可以学习一下
    2022-01-01
  • Java ThreadLocal的使用详解

    Java ThreadLocal的使用详解

    ThreadLocal是线程私有的局部变量存储容器,可以理解成每个线程都有自己专属的存储容器,用来存储线程私有变量。ThreadLocal 在日常开发框架中应用广泛,但用不好也会出现各种问题,本文就此讲解一下。
    2021-05-05
  • 基于Jenkins自动打包并部署docker环境的操作过程

    基于Jenkins自动打包并部署docker环境的操作过程

    这篇文章主要介绍了基于Jenkins自动打包并部署docker环境,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • java面试常见问题---ConcurrentHashMap

    java面试常见问题---ConcurrentHashMap

    ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment的结构和HashMap类似,是一种数组和链表结构,今天给大家普及java面试常见问题---ConcurrentHashMap知识,一起看看吧
    2021-06-06
  • java获取时间的方法总结

    java获取时间的方法总结

    以下是对java中获取时间的几种方法进行了详细的分析介绍,需要的朋友可以参考下
    2013-07-07
  • springboot项目实现断点续传功能

    springboot项目实现断点续传功能

    这篇文章主要介绍了springboot项目实现断点续传,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • Java如何将ResultSet结果集遍历到List中

    Java如何将ResultSet结果集遍历到List中

    这篇文章主要介绍了Java如何将ResultSet结果集遍历到List中问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Java并发 线程间的等待与通知

    Java并发 线程间的等待与通知

    这篇文章主要介绍了Java并发 线程间的等待与通知,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • 超详细讲解Java线程池

    超详细讲解Java线程池

    本文主要介绍了Java线程池,本文运用大量代码和图片讲解相关知识,感兴趣的小伙伴一起来看看吧
    2021-09-09
  • Java中BigDecimal的舍入模式解析(RoundingMode)

    Java中BigDecimal的舍入模式解析(RoundingMode)

    这篇文章主要介绍了Java中BigDecimal的舍入模式解析(RoundingMode),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06

最新评论