Spring Boot3统一结果封装

简介: Spring Boot3统一结果封装

前置条件

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

作者版本为3.2.2

初始化教程:新版idea(2023)创建spring boot3项目

封装目的

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

具体好处如下:

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

常用格式

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

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

定义返回结果枚举类

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

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下的所有控制类的所有方法都会被拦截将返回结果进行统一格式封装。

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

目录
相关文章
|
7月前
|
NoSQL 安全 Java
Spring Boot3整合Redis
Spring Boot3整合Redis
248 1
|
1月前
|
Java
springboot将list封装成csv文件
springboot将list封装成csv文件
43 4
|
2月前
|
Java API Spring
springBoot:注解&封装类&异常类&登录实现类 (八)
本文介绍了Spring Boot项目中的一些关键代码片段,包括使用`@PathVariable`绑定路径参数、创建封装类Result和异常处理类GlobalException、定义常量接口Constants、自定义异常ServiceException以及实现用户登录功能。通过这些代码,展示了如何构建RESTful API,处理请求参数,统一返回结果格式,以及全局异常处理等核心功能。
|
4月前
|
前端开发 小程序 Java
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
本文详细介绍了如何在SpringBoot项目中统一处理接口返回结果及全局异常。首先,通过封装`ResponseResult`类,实现了接口返回结果的规范化,包括状态码、状态信息、返回信息和数据等字段,提供了多种成功和失败的返回方法。其次,利用`@RestControllerAdvice`和`@ExceptionHandler`注解配置全局异常处理,捕获并友好地处理各种异常信息。
2049 0
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
|
4月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
57 0
Spring高手之路22——AOP切面类的封装与解析
|
4月前
|
JSON 前端开发 Java
SpringBoot3怎么做统一结果封装?
在Spring Boot应用中,统一结果封装有助于团队协作,确保一致的API响应格式,提升代码质量和维护性。主要优点包括:简化前端集成工作,减少后端重复编码,以及增强接口的可维护性。实现上,首先定义`Result`类来封装响应状态码、消息、数据及时间戳;其次,通过`ResultCode`枚举类标准化状态信息。示例代码展示了如何构建这些类,并通过一个简单的控制器方法演示了如何使用它们返回JSON格式的响应结果。
180 2
|
5月前
|
Java Spring
spring restTemplate 进行http请求的工具类封装
spring restTemplate 进行http请求的工具类封装
236 3
|
5月前
|
XML Java API
springboot基础及上传组件封装
springboot基础及上传组件封装
25 0
|
5月前
|
JSON Java fastjson
Spring Boot返回Json数据及数据封装
本文详细介绍了如何在Spring Boot项目中处理JSON数据的传输 Spring Boot默认使用Jackson作为JSON处理器,并通过`spring-boot-starter-web`依赖自动包含相关组件。文章还展示了如何配置Jackson处理null值,使其转换为空字符串。此外,文章比较了Jackson和FastJson的特点,并提供了FastJson的配置示例,展示了如何处理null值以适应不同应用场景。
|
6月前
|
Java
springboot封装RedisTemplate
springboot封装RedisTemplate