【Java EE进阶 --- SpringBoot】统一功能处理


🚀 欢迎来到我的优快云博客:Optimistic _ chen
一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!


🚀我的专栏推荐

专栏内容特色适合人群
🔥C语言从入门到精通系统讲解基础语法、指针、内存管理、项目实战零基础新手、考研党、复习
🔥Java基础语法系统解释了基础语法、类与对象、继承Java初学者
🔥Java核心技术面向对象、集合框架、多线程、网络编程、新特性解析有一定语法基础的开发者
🔥Java EE 进阶实战Servlet、JSP、SpringBoot、MyBatis、项目案例拆解想快速入门Java Web开发的同学
🔥Java数据结构与算法图解数据结构、LeetCode刷题解析、大厂面试算法题面试备战、算法爱好者、计算机专业学生

🚀我的承诺:
✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例

✅ 持续更新:专栏内容定期更新,紧跟技术趋势

✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)


🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨

📌 标签:#技术博客#编程学习#Java#C语言#算法#程序员

统一数据返回格式

SpringBoot 统一功能处理:

定义:指在SpringBoot应用中,通过一些统一的处理机制,对具有共性的功能进行集中管理,以提高代码的可维护性和开发效率。
应用范围:通常包括统一异常处理、统一数据返回格式、统一用户认证与授权等。

博主任认为,统一数据返回格式在项目中起到至关重要的作用,没有统一的返回格式,那么前端就很难有序、正确的接收到后端的响应。所以前端准确的接收响应,后端必须有一个统一的返回格式(通过各种类型转换实现)。

全局拦截自动包装模式

为确保数据格式规范统一,我们首先采用@ControllerAdvice注解配合ResponseBodyAdvice接口实现方案。其中@ControllerAdvice用于定义全局控制器增强类。


@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        //false:不处理
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //如果返回体是String类型,使用objectMapper将其转换成JSON字符串,再使用Result.success()包装
            if(body instanceof String){
            return objectMapper.writeValueAsString(Result.success(body));
        }
        //如果返回体已经是Result类型,则直接返回
        if(body instanceof Result){
            return body;
        }
        //其他类型,直接使用Result.success()包装
        return Result.success(body);
    }
}

supports方法是判断是否要执行beforeBodyWrite方法。true为执行,false不执行。通过该方法可以选择哪些类或者哪些方法的响应要进行统一格式处理,其他的不处理。
beforeBodyWrite用于在控制器方法返回结果之前对响应体进行统一处理。目的就说对返回的数据格式进行统一封装。

我们通过postman来测试一下,统一格式返回前后的区别:
在这里插入图片描述
转换后:
在这里插入图片描述

手动显示封装模式

手动显示模式指的是在控制器方法中显式地返回统一结果对象,而不是依赖全局拦截器自动包装。它对于每个功能模块都有更强的掌控力,更加明确代码中的返回类型。

@Data
public class CommonResult<T> implements Serializable {//序列化实现的接口(标记”这个类的对象可以被序列化,便于网络传输和持久化存储)
    /**
     * 返回的错误码
     */
    private Integer code;

    /**
     * 返回的泛型数据
     */
    private T data;

    /**
     * 返回的错误描述
     */
    private String message;



    public static <T> CommonResult <T> success(T data) {
        CommonResult<T> result=new CommonResult<>();
        result.code= GlobalErrorCode.SUCCESS.getCode();
        result.data=data;
        result.message="";
        return result;
    }

    public static <T> CommonResult <T> error(Integer code,String message) {
        Assert.isTrue(!GlobalErrorCode.SUCCESS.getCode().equals(code),"不是错误的异常");
        CommonResult<T> result=new CommonResult<>();
        result.code= GlobalErrorCode.INTERNAL_SERVER_ERROR.getCode();
        result.message= message;
        return result;
    }

    public static <T> CommonResult <T> error(ErrorCode errorCode) {
        return error(errorCode.getCode(),errorCode.getMessage());
    }
}

每个接口返回类型都**需要手动去包装响应,达到精细化处理响应效果。**同时你也可以去定义全局的错误或者异常,以便统一处理,这个我们后面再说。

注意:
在全局拦截自动包装模式中 ,返回结果为String类型。 SpringBoot开始选择消息转化器,

但是有自动全局拦截器,开始使用手动JSON序列化,(objectMapper将其转换成JSON字符串)最终响应输出一个JSON字符串(不是JSON对象)。

而手动显示封装模式先手动包装Spring类型,在CommontResult类下返回的是对象,

然后SpringBoot开始选择消息转化器,引入jackson包后,容器会把MappingJackson2HttpMessageConverter⾃动注册到messageConverters链的末尾被SpringBoot选中,进行Jackson自动序列化为JSON对象。

统一异常处理

统⼀异常处理使⽤的是@ControllerAdvice + @ExceptionHandler来实现的,@ControllerAdvice 表⽰控制器通知类,@ExceptionHandler 是异常处理器,两个结合表⽰当出现异常的时候执⾏某个通知,也就是执⾏某个⽅法事件

@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {
    @ExceptionHandler
    public Result handlerException(Exception e) {
        return Result.fail(e.getMessage());
    }
}

注意:接口返回为数据时,需要@ResponseBody注解。
这个原因在学习@ResponseBody注解时介绍过:注解告诉Spring:方法的返回值应该直接写入HTTP响应体,而不是被解释为视图名称。

调用Result.fail(e.getMessage())方法返回错误信息,所有的异常都有统一的返回格式,

结果状态枚举类:ResultCodeEnum


import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@AllArgsConstructor
public enum ResultCodeEnum {
    SUCCESS(200),    // 成功状态码
    FAIL(-1);        // 失败状态码
    
    @Setter @Getter
    private int code;
}

统一结果封装类:Result


import com.zc.blog.enums.ResultCodeEnum;
import lombok.Data;

@Data
public class Result {
    private ResultCodeEnum code;  // 业务状态码(使用枚举)
    private String errMsg;        // 错误信息(成功时为null)
    private Object data;          // 响应数据(任意类型)

    // 成功响应 - 带数据
    public static Result success(Object data){
        Result result = new Result();
        result.setCode(ResultCodeEnum.SUCCESS);
        result.setData(data);
        return result;
    }

    // 失败响应 - 只有错误信息
    public static Result fail(String errMsg){
        Result result = new Result();
        result.setCode(ResultCodeEnum.FAIL);
        result.setErrMsg(errMsg);
        return result;
    }
    
    // 失败响应 - 带错误信息和数据
    public static Result fail(String errMsg, Object data){
        Result result = new Result();
        result.setCode(ResultCodeEnum.FAIL);
        result.setErrMsg(errMsg);
        result.setData(data);
        return result;
    }
}

全局异常处理:

@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    public Result handleBlogException(BlogException e) {
        // 捕获业务异常,返回统一的失败结果
        return Result.fail(e.getErrMsg());
    }
}

自定义异常类:Experience

import lombok.Data;

@Data
public class Exception extends RuntimeException{
    private int code;        // 异常状态码
    private String errMsg;   // 异常信息

    // 构造方法 - 指定码和消息
    public Exception(int code, String errMsg) {
        this.code = code;
        this.errMsg = errMsg;
    }
    
    // 构造方法 - 只指定消息(使用默认码)
    public Exception(String errMsg) {
        this.errMsg = errMsg;
    }
}

接口返回格式经过Spring 会使用消息转换器将对象转化为JSON

统一处理的优点

1. 能提供统一的API响应格式,方便前端更好的接收和解析后端数据
2. 降低前后端沟通成本
3. 有利于项目维护和扩展
4. 提供友好的报错信息

评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Optimistic _ chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值