解读MyabtisPlus中的R类(通用响应包装类)

目录

  • 前言
  • 1. 概念
  • 2. 源码解读
  • 3. Demo

前言

大部分R类可以自已手写一个适配的,但MybatisPlus中有专门的R类,于是就使用封装好的类即可

1. 概念

通用R类是一种用于处理API响应的通用响应包装类。

概念含义作用示例用途
1.R类是一个泛型类,可以用于封装任意类型的API响应数据。

2.通过对响应进行包装,提供了一种一致的方式来表示成功、失败或异常情况。
1.R类的名称可能表示"Response",代表着它是用于处理响应的类。

2.通过包含业务错误码、结果集和描述信息等属性,提供了对API响应的全面描述。
1.封装响应: 提供了一种封装API响应的结构,包括成功和失败的情况。

2.统一格式: 定义了统一的响应格式,使得在不同的API请求中都能够使用相同的响应结构。

3.易于处理: 通过提供静态工厂方法和实用方法,简化了对响应的处理和判断。

4.异常处理: 通过serviceData方法,可以方便地处理服务间调用时的异常情况。

5.清晰的代码流: 使用ok方法使得代码中对成功响应的判断更加清晰,提高了代码的可读性。
1.在服务层封装的方法中,使用R类来包装成功或失败的响应,使得调用方能够清晰地了解操作的结果。

2.在Controller层中,根据R类的响应进行不同的处理,例如成功时显示数据,失败时返回错误信息。

总体而言,通用R类的设计旨在提供一种简单、灵活、一致且易于处理的方式来处理不同类型的API响应,使得代码更加清晰和可维护。

2. 源码解读

里头具体的一些方法类如下:

IErrorCode 类的接口

public interface IErrorCode {/*** 错误编码 -1、失败 0、成功*/long getCode();/*** 错误描述*/String getMsg();
}

ApiErrorCode实现类 (主要是code以及msg的属性类)

public enum ApiErrorCode implements IErrorCode {/*** 失败*/FAILED(-1, "操作失败"),/*** 成功*/SUCCESS(0, "执行成功");private final long code;private final String msg;ApiErrorCode(final long code, final String msg) {this.code = code;this.msg = msg;}public static ApiErrorCode fromCode(long code) {ApiErrorCode[] ecs = ApiErrorCode.values();for (ApiErrorCode ec : ecs) {if (ec.getCode() == code) {return ec;}}return SUCCESS;}@Overridepublic long getCode() {return code;}@Overridepublic String getMsg() {return msg;}@Overridepublic String toString() {return String.format(" ErrorCode:{code=%s, msg=%s} ", code, msg);}
}

再查看其源码:

package com.baomidou.mybatisplus.extension.api;import java.io.Serializable;
import java.util.Optional;import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;import lombok.Data;
import lombok.experimental.Accessors;/*** REST API 返回结果** @author hubin* @since 2018-06-05*/
@Data
@Accessors(chain = true)
public class R<T> implements Serializable {/*** serialVersionUID*/private static final long serialVersionUID = 1L;/*** 业务错误码*/private long code;/*** 结果集*/private T data;/*** 描述*/private String msg;public R() {// to do nothing}public R(IErrorCode errorCode) {errorCode = Optional.ofNullable(errorCode).orElse(ApiErrorCode.FAILED);this.code = errorCode.getCode();this.msg = errorCode.getMsg();}public static <T> R<T> ok(T data) {ApiErrorCode aec = ApiErrorCode.SUCCESS;if (data instanceof Boolean && Boolean.FALSE.equals(data)) {aec = ApiErrorCode.FAILED;}return restResult(data, aec);}public static <T> R<T> failed(String msg) {return restResult(null, ApiErrorCode.FAILED.getCode(), msg);}public static <T> R<T> failed(IErrorCode errorCode) {return restResult(null, errorCode);}public static <T> R<T> restResult(T data, IErrorCode errorCode) {return restResult(data, errorCode.getCode(), errorCode.getMsg());}private static <T> R<T> restResult(T data, long code, String msg) {R<T> apiResult = new R<>();apiResult.setCode(code);apiResult.setData(data);apiResult.setMsg(msg);return apiResult;}public boolean ok() {return ApiErrorCode.SUCCESS.getCode() == code;}/*** 服务间调用非业务正常,异常直接释放*/public T serviceData() {if (!ok()) {throw new ApiException(this.msg);}return data;}
}

对应该源码的相关完整知识点可看我如下文章:

  1. spring中@Data注解详细解析
  2. java之序列化与反序列化的详细解析(全)
  3. 详解Java中@Accessors注解(全)

简易的解释如下:

  • @Data:Lombok注解,用于自动生成样板代码,如getter、setter、toString和equals。
  • @Accessors(chain = true):Lombok注解,用于启用流畅的setter方法(支持方法链)。

属性如下:

  • code:表示业务错误码的属性。
  • data:表示结果集的属性。
  • msg:表示描述信息的属性。
  1. 静态工厂方法:

提供了一些静态工厂方法用于创建R对象,例如ok和failed。

public static <T> R<T> ok(T data) {// 创建成功响应的工厂方法
}public static <T> R<T> failed(String msg) {// 创建失败响应的工厂方法
}
  1. 其他方法:
  • restResult方法用于创建R对象的实例。
  • ok方法用于判断响应是否成功。
  • serviceData方法用于在服务间调用时,处理非业务正常的情况。
public static <T> R<T> restResult(T data, IErrorCode errorCode) {// 创建R对象实例的方法
}public boolean ok() {// 判断响应是否成功的方法
}public T serviceData() {// 处理服务间调用时的方法
}

这个类的设计旨在提供一种简单而灵活的方式来处理不同类型的API响应,包括成功、失败和异常情况。

上述的源码比较简单,不做过多的解读= - =
请看下方demo辅助理解!

3. Demo

类似的Demo如下:

假设有一个用户服务,包含了一个方法用于获取用户信息:

public class UserService {public R<User> getUserById(Long userId) {// 模拟从数据库或其他服务中获取用户信息User user = userRepository.findById(userId);if (user != null) {// 用户存在,返回成功响应return R.ok(user);} else {// 用户不存在,返回失败响应return R.failed("User not found");}}
}

在这个例子中,UserService类中的getUserById方法使用了R类来封装API响应。如果用户存在,它会创建一个成功的R对象,否则创建一个失败的R对象。

然后,在调用这个服务的地方,可以这样处理响应:

public class UserController {private UserService userService;public void handleUserRequest(Long userId) {try {// 调用用户服务获取用户信息R<User> userResponse = userService.getUserById(userId);if (userResponse.ok()) {// 处理成功响应User user = userResponse.getData();System.out.println("User details: " + user);} else {// 处理失败响应System.out.println("Failed to get user: " + userResponse.getMsg());}} catch (ApiException e) {// 处理异常情况System.out.println("Error: " + e.getMessage());}}
}

在这个例子中,UserController类中的handleUserRequest方法处理了从UserService中获取用户信息的响应。

它检查响应是否成功,并根据情况执行相应的操作。异常情况也被捕获和处理,确保在服务调用中发生异常时能够进行适当的处理。这样的设计使得API响应的处理更加清晰和可控。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/609720.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C++汇编学习(六)——数据结构汇编实例:链表、树、图。

我们继续开展 目录 一、链表 1. C代码 2. 链表部分转为汇编并注释 二、树 1. C代码 2. 链表部分转为汇编并注释 3. 汇编伪代码 三、图 1. C代码 2. 汇编伪代码 四、总结 一、链表 1. C代码 #include <iostream>struct ListNode {int data;ListNode* next;…

vue 前端等比例压缩图片(再转换成文件后上传后端)

前端压缩图片总的来说还是转base64 然后等比例放小宽和高 这个是上次压缩图片的一个扩展 压缩完之后 再将base64 转成blob再转成文件然后再上传 一生要强的前端崽子&#xff08;后端不支持base64上传&#xff09; 自己改吧改吧 // 图片上传async changePic(e) {this.isshang…

【Docker】Docker基础

文章目录 安装使用帮助启动命令镜像命令容器命令 安装 # 卸载旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine # 设置存储库 sudo yum install -y yum-utils …

关于git使用的tips

前言 这里是一些git指令使用的tips&#xff0c;如果你作为初学者的话&#xff0c;我认为它将对你有所帮助。 常见指令 常见问题处理 1、使用git clone下载【huggingface.co】资源超时或无法请求问题 绝大多数情况是网络问题&#xff0c;首先如果是比较大的资源&#xff0c;你需…

数据库:如何取消mysql的密码

因为调试MySQL数据接口&#xff0c;总是需要输入密码很烦&#xff0c;所以决定取消mysql的root密码&#xff0c; 网上推荐的有两种方法&#xff1a; 1、mysql命令 SET PASSWORD FOR rootlocalhostPASSWORD(); 2、运行 mysqladmin 命令 mysqladmin -u root -p password …

C# 错误: 集合已修改,可能无法执行枚举操作

出错原因是使用了RemoveAt()函数移除了数据中的某一个数&#xff0c;导致数据发生了错位&#xff08;参考链接一&#xff09; 解决方案&#xff1a; 第一种解决方法&#xff1a;使用for循环 第二种解决方法&#xff1a;调用ToArray()方法&#xff0c;然后再进行foreach循环 …

vue设置height:100vh导致页面超出屏幕可以上下滑动

刚开始设置的height:100vh&#xff0c;就会出现如图的效果&#xff0c;会出现上下滚动 <template><view class"container">......</view> </template><style lang"scss">.container {height: 100vh;} </style> 解决方…

精确掌控并发:分布式环境下并发流量控制的设计与实现(一)

这是《百图解码支付系统设计与实现》专栏系列文章中的第&#xff08;10&#xff09;篇。 本篇主要讲清楚常用的并发流量控制方案&#xff0c;包括固定窗口、滑动窗口、漏桶、令牌桶、分布式消息中间件等&#xff0c;以及各种方案在支付系统不同场景下的应用。 在非支付场景&a…

故事机手机平板等智能硬件DVT阶段可靠性测试方法

DVT是什么 DVT是设计样品验证测试评审阶段&#xff0c;这个阶段要进行全面的&#xff0c;客观的测试&#xff0c; 主要测试项目包括&#xff1a;功能测试&#xff0c;安规测试&#xff0c;性能测试&#xff0c;合规测试&#xff08;兼容性&#xff09;&#xff0c;机械测试&am…

QT上位机开发(树形控件在地图软件中的应用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 树形控件还是非常有用的&#xff0c;比如在选择文件的时候、选择目录的时候、以及选择同类型数据中某一个特定选项的时候。当然&#xff0c;对于ca…

JVM工作原理与实战(十一):双亲委派机制

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、双亲委派机制 1.双亲委派机制详解 2.父类加载器 3.双亲委派机制的主要作用 二、双亲委派机制常见问题 总结 前言 ​JVM作为Java程序的运行环境&#xff0c;其负责解释和执行字…

STM32的FMC独立管理和控制外部存储器

在STM32中&#xff0c;FMC&#xff08;Flexible Memory Controller&#xff09;是一个功能强大的外部存储器控制器&#xff0c;用于管理和控制外部存储器设备&#xff0c;如SRAM、SDRAM、NOR Flash等。FMC允许将多个存储器设备连接到微控制器&#xff0c;并通过不同的片选线进行…

LLM之长度外推(一)| 基于位置编码的长度外推研究综述

论文&#xff1a;Length Extrapolation of Transformers: A Survey from the Perspective of Position Encoding地址&#xff1a;https://arxiv.org/abs/2312.17044 Transformer自诞生以来就席卷了NLP领域&#xff0c;因为它具有对序列中复杂依赖关系进行建模的优越能力。尽管基…

001 Golang-channel-practice

最近在练习并发编程。加上最近也在用Golang写代码&#xff0c;所以记录一下练习的题目。 第一道题目是用10个协程打印100条信息&#xff0c;创建10个协程。每个协程都会有自己的编号。每个协程都会被打印10次。 package mainimport ("fmt""strconv" )func …

1-07基本数据类型

一、概述 C语言的基本数据类型&#xff08;也叫内置数据类型&#xff09;在日常编程中被频繁使用&#xff0c;本章我们主要简单地介绍下 C 语言的基本数据类型。 基本数据类型主要包括&#xff1a;整数类型&#xff0c;浮点数类型和字符类型&#xff0c;其中字符类型也可以看…

gradient_checkpointing

点评&#xff1a;本质是减少内存消耗的一种方式&#xff0c;以时间或者计算换内存 gradient_checkpointing&#xff08;梯度检查点&#xff09;是一种用于减少深度学习模型中内存消耗的技术。在训练深度神经网络时&#xff0c;反向传播算法需要在前向传播和反向传播之间存储中…

前端系列:正则表达式RegExp详解

文章目录 正则创建匹配方法元字符字符集合边界分组数量词汇匹配模式RegExp 方法特性 正则创建 字面量创建 const str asdf123sds3234 const regexp /\d/g const res str.match(regexp) console.log(res) //[123, 3234]构造函数 const str asdf123asad23121 const regexp n…

[②C++ Boost]: Boost库编译,arm交叉编译方法

前言 Boost是十分实用的C库&#xff0c;如果想在arm环境下使用&#xff0c;就需要自己下载源码编译&#xff0c;本篇博客就记录下Boost库的编译方法。 下载Boost源码 Boost源码的下载路径可以使用&#xff1a;https://sourceforge.net/projects/boost/files/boost/ 编译 …

408重要数据结构+算法汇总——C语言手搓版(全)

该套代码&#xff0c;大学期间跟着网课一遍一遍打下来的&#xff0c;408大概就这些了&#xff0c;别的杂七杂八其实还有很多&#xff0c;遗憾的是&#xff0c;一直没有整理和归纳。导致一遍遍地学一遍遍地忘记。大四就快毕业了&#xff0c;研也考了。这里做个整理&#xff0c;算…

JavaScript小案例

烟花 html <body><div id"box"></div><script src"./move.js"></script><script src"./fire.js"></script> </body>js代码 fire.js function Fire(){// 获取box盒子this.box document.que…