当前位置: 首页 > news >正文

SpringBoot教程(八) | SpringBoot统一结果封装

SpringBoot教程(八) | SpringBoot统一结果封装

经过了前面几篇文章,SpringBoot中MVC相关的配置其实都已经差不多了,接下来就可以完全进入接口开发阶段了。前面我们写过几个接口,虽然都加了@RestController注解,相当于统一了我们的返回数据的基本形式为JSON,但是由于我们的项目可能是很多人一起开发,所以我们最好能够把我们的返回结果统一一下,让大家都返回一样的数据格式,这样即规范了代码,也方便了前端人员的调用,不然每个人都按照每个人的风格去写,代码会变得非常混乱。

那我我们怎么还封装这个结果呢,那就要关注我们返回给前端的数据都要包含哪些信息。

一般来讲,首先要有一个code, 用来代表我们这次接口的一个状态,比如 0代表成功,1代表失败,2代表必传参数不对, 4代表系统异常等等。这只是个简单的举例。可能很多人会有疑问,Http协议本身不是已经有了相应的返回码的定义了么,比如200代表成功, 500代表服务器错误,404代表找不到页面,为啥咱们还要在定义呢,这就是划分粒度的问题了,就那200来说,它代表是这次请求成功了,但是它描述不了这次请求中的业务结果,比如用户名已存在,其实业务上就不是一种成功,但http的结果肯定是200,所以我们需要一种描述我们业务状态的编码。

除了编码之外,还有要一些提示信息,比如,操作成功,系统异常,用户名已存在等,所以我们再加一个messge字段。

还有什么呢,还有我们的核心数据,比如我根据id获取数据,那个这个数据的具体内容,我们肯定是必须要返回给前端呢,所以还要 有个data, 那这个data 用什么类型呢,这个类型肯定是五花八门,所以我们要用一个统一的父类,Object才可以接收所有类型,当然为了便于操作我们可以采用泛型的方式。

通过上面的分析,我们的这个类基本上就已经可以设计出来了。

java复制代码public class Result<T> implements Serializable {private static final long serialVersionUID = -3960261604605958516L;private int code;private String msg;private T data;// get set方法,限于篇幅问题,这里不写了,大家操作的时候自己生成一下。或者使用lombokpublic static <T> Result<T> success() {return new Result<>();}/*** 成功,默认状态码,返回消息,自定义返回数据** @param data 自定义返回数据* @param <T>  返回类泛型,不能为String* @return 通用返回Result*/public static <T> Result<T> success(T data) {return new Result<>(data);}/*** 成功,默认状态码,自定义返回消息,无返回数据** @param msg 自定义返回消息* @param <T> 返回类泛型* @return 通用返回Result*/public static <T> Result<T> success(String msg) {return new Result<>(msg);}/*** 成功,默认状态码,自定义返回消息,返回数据** @param msg  自定义返回消息* @param data 自定义返回数据* @param <T>  返回类泛型* @return 通用返回Result*/public static <T> Result<T> success(String msg, T data) {return new Result<>(msg, data);}/*** 失败,默认状态码,返回消息,无返回数据** @param <T> 返回类泛型* @return 通用返回Result*/public static <T> Result<T> error() {return new Result<>(ResultCode.ERROR);}/*** 失败,默认状态码,自定义返回消息,无返回数据** @param <T> 返回类泛型* @return 通用返回Result*/public static <T> Result<T> error(String msg) {return new Result<>(ResultCode.ERROR.getCode(), msg);}/*** 失败,自定义状态码,返回消息,无返回数据** @param code 自定义状态码* @param msg  自定义返回消息* @param <T>  返回类泛型* @return 通用返回Result*/public static <T> Result<T> error(int code, String msg) {return new Result<>(code, msg);}/*** 失败,使用CodeMsg状态码,返回消息,无返回数据** @param resultCode CodeMsg,参数如下:*                   <p> code 状态码*                   <p> msg  返回消息* @param <T>        返回类泛型* @return 通用返回Result*/public static <T> Result<T> error(ResultCode resultCode) {return new Result<>(resultCode);}/*** 成功构造器,无返回数据*/private Result() {this(ResultCode.SUCCESS);}/*** 成功构造器,自定义返回数据** @param data 返回数据*/private Result(T data) {this(ResultCode.SUCCESS, data);}/*** 成功构造器,自定义返回消息,无返回数据** @param msg 返回消息*/private Result(String msg) {this(ResultCode.SUCCESS.getCode(), msg);}/*** 成功构造器,自定义返回信息,返回数据** @param msg  返回信息* @param data 返回数据*/private Result(String msg, T data) {this(ResultCode.SUCCESS.getCode(), msg, data);}/*** 构造器,自定义状态码,返回消息** @param code 状态码* @param msg  返回消息*/private Result(int code, String msg) {this.code = code;this.msg = msg;}/*** 构造器,自定义状态码,返回消息,返回数据** @param code 状态码* @param msg  返回消息* @param data 返回数据*/private Result(int code, String msg, T data) {this(code, msg);this.data = data;}/*** 构造器,使用CodeMsg状态码与返回信息** @param resultCode CodeMsg,参数如下:*                   <p> code 状态码*                   <p> msg  返回消息*/private Result(ResultCode resultCode) {this(resultCode.getCode(), resultCode.getMsg());}/*** 构造器,使用CodeMsg状态码与返回信息,自定义返回数据** @param resultCode CodeMsg,参数如下:*                   <p> code 状态码*                   <p> msg  返回消息* @param data       返回数据*/private Result(ResultCode resultCode, T data) {this(resultCode);this.data = data;}}

在定义几个常见的错误:这里为了不写那么多的get,set,我们引入了lombok

java复制代码@Data
@Builder
public class ResultCode implements Serializable {private static final long serialVersionUID = -6269841958947880397L;/*** 状态码*/private int code;/*** 状态信息*/private String msg;/*** 默认成功*/public final static ResultCode SUCCESS = dispose(ResultCodeEnum.SUCCESS);/*** 默认失败*/public final static ResultCode ERROR = dispose(ResultCodeEnum.ERROR);/*** 通用业务异常*/public final static ResultCode BIZ_ERROR = dispose(ResultCodeEnum.BIZ_ERROR);/*** 文件超出最大限制*/public final static ResultCode FILE_OUT_MAX = dispose(ResultCodeEnum.FILE_OUT_MAX);/*** 文件格式不正确*/public final static ResultCode FILE_FORMAT_ERROR = dispose(ResultCodeEnum.FILE_FORMAT_ERROR);/*** 参数错误*/public final static ResultCode PARAM_ERROR = dispose(ResultCodeEnum.PARAM_ERROR);/*** Json解析异常*/public final static ResultCode JSON_FORMAT_ERROR = dispose(ResultCodeEnum.JSON_FORMAT_ERROR);/*** Sql解析异常*/public final static ResultCode SQL_ERROR = dispose(ResultCodeEnum.SQL_ERROR);/*** 网络超时*/public final static ResultCode NETWORK_TIMEOUT = dispose(ResultCodeEnum.NETWORK_TIMEOUT);/*** 未知的接口*/public final static ResultCode UNKNOWN_INTERFACE = dispose(ResultCodeEnum.UNKNOWN_INTERFACE);/*** 请求方式不支持*/public final static ResultCode REQ_MODE_NOT_SUPPORTED = dispose(ResultCodeEnum.REQ_MODE_NOT_SUPPORTED);/*** 系统异常*/public final static ResultCode SYS_ERROR = dispose(ResultCodeEnum.SYS_ERROR);private static ResultCode dispose(ResultCodeEnum codeEnum) {return ResultCode.builder().code(codeEnum.getCode()).msg(codeEnum.getMsg()).build();}public ResultCode(int code, String msg) {this.code = code;this.msg = msg;}
}
java复制代码public enum ResultCodeEnum {SUCCESS(0, "操作成功"),ERROR(1, "操作失败"),BIZ_ERROR(1000, "通用业务异常"),FILE_OUT_MAX(9000, "文件超出最大限制"),FILE_FORMAT_ERROR(9001, "文件格式不正确"),PARAM_ERROR(9050, "参数错误"),JSON_FORMAT_ERROR(9051, "Json解析异常"),SQL_ERROR(9052, "Sql解析异常"),NETWORK_TIMEOUT(9510, "网络超时"),UNKNOWN_INTERFACE(9520, "未知的接口"),REQ_MODE_NOT_SUPPORTED(9530, "请求方式不支持"),SYS_ERROR(9999, "系统异常");/*** 状态码*/private final int code;/*** 状态信息*/private final String msg;public int getCode() {return code;}public String getMsg() {return msg;}ResultCodeEnum(int code, String msg) {this.code = code;this.msg = msg;}
}

这个写完了以后,就可以统一我们的返回结果,以后所有的Controller就都要返回Result类型。比如:

java复制代码@GetMapping("/withinRangeResource")public Result<List<EmergencyExpertResVO>> withinRangeResource(@Valid ResourceRangeReqVO param) {List<EmergencyExpertResVO> expertResVOS = emergencyExpertBiz.getWithinRangeResource(param);return Result.success(expertResVOS);}

另: 配套项目代码已托管中gitCode: gitcode.net/lsqingfeng/…

相关文章:

SpringBoot教程(八) | SpringBoot统一结果封装

SpringBoot教程(八) | SpringBoot统一结果封装 经过了前面几篇文章&#xff0c;SpringBoot中MVC相关的配置其实都已经差不多了&#xff0c;接下来就可以完全进入接口开发阶段了。前面我们写过几个接口&#xff0c;虽然都加了RestController注解&#xff0c;相当于统一了我们的…...

Ubuntu 22.04 安装Fail2Ban

Fail2Ban是一种用来防止暴力破解的工具&#xff0c;一般要和iptables配合使用。其原理是读取系统日志&#xff0c;并通过正则表达式匹配&#xff0c;监控IP在一段时间内的登录尝试、身份验证失败日志等并进行计数。超过阈值则进行IP封禁&#xff0c;过一段时间后再解封。 总的…...

Ubuntu 22.04 编译安装 Qt mysql驱动

参考自 Ubuntu20.04.3 QT5.15.2 MySQL驱动编译 Ubuntu 18.04 编译安装 Qt mysql驱动 下边这篇博客不是主要参考的, 但是似乎解决了我的难题(找不到 libmysqlclient.so) ubuntu18.04.2 LTS 系统关于Qt5.12.3 无法加载mysql驱动&#xff0c;需要重新编译MYSQL数据库驱动的问题以…...

Mindspore 公开课 - CodeGeeX

CodeGeeX: 多语言代码生成模型 CodeGeeX 是一个具有130亿参数的多编程语言代码生成预训练模型。CodeGeeX采用华为MindSpore框架实现&#xff0c;在鹏城实验室“鹏城云脑II”中的192个节点&#xff08;共1536个国产昇腾910 AI处理器&#xff09;上训练而成。截至2022年6月22日&…...

说一下mysql的锁

1、全局锁: 影响整个数据库的锁。例如,当执行 FLUSH TABLES WITH READ LOCK; 命令时,会阻止其他用户写入数据库,但可以读取。全局锁简介 全局锁是一种跨所有数据库实例的锁。它可以确保在任何时刻,只有一个事务能够访问共享资源。全局锁通常用于以下场景: 并发性较高的场…...

rime中州韵小狼毫 日期/农历 时间 事件 节气 滤镜

教程目录&#xff1a;rime中州韵小狼毫须鼠管安装配置教程 保姆级教程 100增强功能配置教程 网络上但凡提到 rime中州韵小狼毫须鼠管输入法&#xff0c;总少不了智能时间&#xff0c;日期等炫技&#xff0c;可见这个便捷时间/日期输入功能是多么的受欢迎。作者也不落窠臼&…...

【前端】前后端的网络通信基础操作(原生ajax, axios, fetch)

概述 前后端网络请求工具 原生ajaxfetch apiaxios GET和POST请求 get只能发纯文本 post可以发不同类型的数据&#xff0c;要设置请求头&#xff0c;需要告诉服务器一些额外信息 测试服务器地址 有一些公共的测试 API 可供学习和测试用途。这些 API 允许你发送 HTTP 请求…...

Matter - 配置工厂数据(2)

部分关键名词参数简介 PASE(Passcode-Authenticated Session Establishment): 基于密码认证的会话建立&#xff0c;用于在 Commissioning 的时候 Commissioner 与 Matter Deivce 之间建立安全信道&#xff0c;生成对称加密密钥用于 Commissioning 后续通信消息进行加、解密和完…...

版本控制背景知识

版本控制背景知识 本文是关于 Git 系列文章的导读&#xff0c;我们先介绍一下版本控制的背景知识。 什么是版本控制 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。它将什么时候、什么人更改了文件的什么内容等信息如实记录下来…...

tensorflow报错: DNN library is no found

错误描述 如上图在执行程序的时候&#xff0c;会出现 DNN library is no found 的报错 解决办法 这个错误基本上说明你安装的 cudnn有问题&#xff0c;或者没有安装这个工具。 首先检测一下你是否安装了 cudnn 进入CUDA_HOME下&#xff0c;也就是进入你的cuda的驱动的安装目…...

DA14531-高级应用篇-用户如何开启OTA服务

文章目录 1. OTA相关文件2.OTA宏定义列表3.OTA主要函数接口4.OTA具体实施步骤5.总结1. OTA相关文件 1)app_suotar_task.c和app_suotar_task.h 2)app_suotar.c和app_suotar.h 2.OTA宏定义列表 宏定义注解CFG_PRF_SUOTAR用户开启SOTA功能BLE_SUOTA_RECEIVERSOTA功能服务CFG_S…...

国内镜像源配置方法(包括临时和永久方法)

国内镜像源&#xff1a; 阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/豆瓣 http://pypi.douban.com/simplePython官方 https://pypi.python.org/simple/v2ex http://pypi.v2ex.com/simple/中国科学院 http://pypi.mi…...

数据结构二叉树--堆(数据结构实现和堆排序的一种实现)

堆是一个数据结构 逻辑结构&#xff1a;完全二叉树&#xff08;要求父节点大于孩子节点或者小于孩子节点&#xff09; 存储结构&#xff1a;顺序存储 typedef int DataType; typedef struct Heap{DataType*data;int size;int capacity; }Heap;void InitHeap(Heap*pH) {asser…...

【Linux】 nohup命令使用

nohup命令 nohup是Linux和Unix系统中的一个命令&#xff0c;其作用是在终端退出时&#xff0c;让进程在后台继续运行。它的全称为“no hang up”&#xff0c;意为“不挂起”。nohup命令可以让你在退出终端或关闭SSH连接后继续运行命令。 nohup 命令&#xff0c;在默认情况下&…...

多维时序 | Matlab实现GRO-CNN-LSTM-Attention淘金算法优化卷积神经网络-长短期记忆网络结合注意力机制多变量时间序列预测

多维时序 | Matlab实现GRO-CNN-LSTM-Attention淘金算法优化卷积神经网络-长短期记忆网络结合注意力机制多变量时间序列预测 目录 多维时序 | Matlab实现GRO-CNN-LSTM-Attention淘金算法优化卷积神经网络-长短期记忆网络结合注意力机制多变量时间序列预测效果一览基本介绍程序设…...

SQL-DQL-基础查询

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…...

Kubernetes (十三) 存储——持久卷-动静态分配

一. 简介 二. NFS持久化存储步骤&#xff08;静态分配&#xff09; 1. 集群外…...

order by之后的injection(sqllabs第四十六关)

order by相关注入知识 这一关的sql语句是利用的order by 根据输入的id不同数据排序不一样可以确定就是order by order by后面无法使用ubion注入&#xff08;靠找不到&#xff09; 可以利用后面的参数进行攻击 1&#xff09;数字 没作用考虑布尔类型 rand和select ***都可以 …...

C++ 树与图的广度优先遍历 || 模版题 :图中点的层次

给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环。 所有边的长度都是 1 &#xff0c;点的编号为 1∼n 。 请你求出 1 号点到 n 号点的最短距离&#xff0c;如果从 1 号点无法走到 n 号点&#xff0c;输出 −1 。 输入格式 第一行包含两个整数 n 和 m 。 …...

k8s---pod控制器

pod控制器发的概念&#xff1a; 工作负载&#xff0c;workload用于管理pod的中间层&#xff0c;确保pod资源符合预期的状态。 预期状态&#xff1a; 1、副本数 2、容器重启策略 3、镜像拉取策略 pod出故障的出去等等 pod控制器的类型&#xff1a; 1、replicaset&#xf…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中&#xff0c;我们训练出的神经网络往往非常庞大&#xff08;比如像 ResNet、YOLOv8、Vision Transformer&#xff09;&#xff0c;虽然精度很高&#xff0c;但“太重”了&#xff0c;运行起来很慢&#xff0c;占用内存大&#xff0c;不适合部署到手机、摄…...