当前位置: 首页 > 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…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...