Springboot优雅实现对接口返回统一封装
前端在调用后端接口时往往不同的接口返回的数据是不一样的,但是通常我们会与前端约定一个固定的返回格式,通过固定的格式告诉他们什么时候接口是返回成功,什么时候返回失败,返回成功后他们如何拿到接口返回的数据去渲染前端页面。
在不对接口统一包装时,你可能会这样的返回如一个查询接口
@PostMapping(value = "/list")public List<Map<String, Object>> list() {List<Map<String, Object>> mapList = new ArrayList<>();HashMap<String, Object> map = new HashMap<>();map.put("dazhi", "大智");map.put("zhangsan", "张三");map.put("laoliu", "老六");mapList.add(map);return mapList;}
接口返回

又或者这样的如一个删除接口
@PostMapping(value = "/delete")public String delete() {return "删除完毕";}
接口返回

像这些情况如果你和前端开发人员联调接口她们就会很懵逼,由于我们没有给他一个统一的格式,前端人员不知道如何处理返回值。所以我们需要定义一个统一的标准返回格式的。
一个标准的返回格式至少包含3部分:
code 状态码:统一定义各种返回结果的状态码。
msg 描述:接口调用的结果描述。
data 数据:返回的数据。
{"code": "S000","msg": "操作成功!","data": "数据更新成功!"
}
我们使用@RestControllerAdvice注解并且实现ResponseBodyAdvice接口来实现统一返回格式的封装,关于使用@RestControllerAdvice实现全局异常处理可以看我以前的文章《Springboot全局异常处理从配置文件中读取自定义异常信息》,接下来展示一下大概的代码
定义一个标准的统一返回实体
package com.yx.limit.base.vo;import com.yx.limit.base.enums.ResponseEnum;
import lombok.Data;/*** @Author yx* @Description 统一响应实体*/
@Data
public class ResponseVo<T> {/*** 响应编码*/private String code;/*** 消息内容*/private String msg;/*** 响应数据*/private T data;private ResponseVo() {}private enum Singleton{INSTANCE;private ResponseVo responseVo;Singleton(){if (responseVo == null){responseVo = new ResponseVo();}}public ResponseVo getInstance(){return responseVo;}}public static <T> ResponseVo<T> success() {return success(null);}public static <T> ResponseVo<T> success(T data) {ResponseVo<T> responseVo = Singleton.INSTANCE.getInstance();responseVo.setCode(ResponseEnum.SUCCESS.getResultCode());responseVo.setMsg(ResponseEnum.SUCCESS.getResultMsg());responseVo.setData(data);return responseVo;}public static <T> ResponseVo<T> error(String code, String msg) {ResponseVo<T> responseVo = Singleton.INSTANCE.getInstance();responseVo.setCode(code);responseVo.setMsg(msg);responseVo.setData(null);return responseVo;}public static <T> ResponseVo<T> error(String msg) {ResponseVo<T> responseVo = Singleton.INSTANCE.getInstance();responseVo.setCode(ResponseEnum.ERROR.getResultCode());responseVo.setMsg(ResponseEnum.ERROR.getResultMsg());responseVo.setData(null);return responseVo;}
}
定义一个状态码枚举
package com.yx.limit.base.enums;import lombok.AllArgsConstructor;
import lombok.Getter;/*** @Author yx* @Description 响应编码枚举*/
@AllArgsConstructor
public enum ResponseEnum {/*** 数据操作错误定义*/SUCCESS("S000","操作成功!"),ERROR("E000","操作失败!"),SIGNATURE_NOT_MATCH("E001","请求的数字签名不匹配!"),BODY_NOT_MATCH("E002","请求的数据格式不符!"),INTERNAL_SERVER_ERROR("E003", "服务器内部错误!");/*** 错误码*/@Getterprivate String resultCode;/*** 错误描述*/@Getterprivate String resultMsg;
}
定义一个忽略自动包装返回功能的注解
package com.yx.limit.base.annotations;import java.lang.annotation.*;/*** @Author yx* @Description 忽略自动返回构造注解*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreAutoResponse {
}
统一响应结果通知类
package com.yx.light.element.mybatis.advice;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yx.limit.base.annotations.IgnoreAutoResponse;
import com.yx.limit.base.vo.ResponseVo;
import lombok.SneakyThrows;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
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 yx* @Description 统一响应结果通知*/
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {private final ObjectMapper objectMapper;public ResponseAdvice(ObjectMapper objectMapper) {this.objectMapper = objectMapper;}@Overridepublic boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {return !methodParameter.hasMethodAnnotation(IgnoreAutoResponse.class);}@SneakyThrows@Overridepublic Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {//SpringBoot的Controller中的方法返回值是String时会直接返回if (o instanceof String) {return objectMapper.writeValueAsString(ResponseVo.success(o));}//全局异常处理的结果直接返回即可if (o instanceof ResponseVo) {return o;}return ResponseVo.success(o);}
}
这个时候我们再来请求原来的两个方法查看返回结果
list方法:

delete方法:

我们发现delete的方法返回的json格式没有格式化,我们只需要稍加改造一下delete方法就能正常返回格式化的数据
@PostMapping(value = "/delete", produces = "application/json; charset=UTF-8")public String delete() {return "删除完毕";}

对于一些不想返回固定包装的方法可以在方法上加上@IgnoreAutoResponse注解即可返回原始的格式
@PostMapping(value = "/original")@IgnoreAutoResponsepublic String original() {return "原始字符串";}

相关文章:
Springboot优雅实现对接口返回统一封装
前端在调用后端接口时往往不同的接口返回的数据是不一样的,但是通常我们会与前端约定一个固定的返回格式,通过固定的格式告诉他们什么时候接口是返回成功,什么时候返回失败,返回成功后他们如何拿到接口返回的数据去渲染前端页面。…...
Kafka 安装与部署
目录 Kafka 下载 (1)将 kafka_2.11-2.4.1.tgz 上传至 /opt/software/ (2)解压安装包至 /opt/module/ [huweihadoop101 ~]$ cd /opt/software/ [huweihadoop101 software]$ tar -zxvf kafka_2.11-2.4.1.tgz -C ../module/&#…...
计算 N*4*4 位姿形状的逆变换,在N*3*4位姿后补充 [0,0,0,1]
针对 [N,4,4] shape 的 poses,函数 ComputeInversePoses 返回 相同 shape,但是每个 pose 都是前面的 逆 pose。 针对 [N,3,4] shape 的 poses,函数 AddIdentityToPoses 返回 在每个 [3,4] pose下加上 [0,0,0,1] 后的pose,返回的…...
人工智能可以战胜人类智慧大脑么?
引言 在当今快速发展的科技时代,人工智能的进步日新月异,引发了一场深刻的讨论:能否有一天,人工智能能够超越甚至战胜人类智慧?这个问题涉及到人类认知的广泛领域,牵涉到人类思维的深层次特质以及AI技术在…...
【数据结构和算法】 K 和数对的最大数目
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一:双指针排序 三、代码 3.1 方法一:双指针排序 3.2 方法二࿱…...
基于ssm高校推免报名系统源码和论文
网络的广泛应用给生活带来了十分的便利。所以把高校推免报名管理与现在网络相结合,利用java技术建设高校推免报名管理系统,实现高校推免报名的信息化。则对于进一步提高高校推免报名管理发展,丰富高校推免报名管理经验能起到不少的促进作用。…...
算法设计与分析2023秋-头歌实验-实验七 动态规划
文章目录 第1关:数塔问题任务描述相关知识编程要求解题思路测试说明参考答案 第2关:最长公共子序列任务描述相关知识编程要求解题思路:测试说明参考答案 第3关:求序列-2 11 -4 13 -5 -2的最大子段和任务描述相关知识编程要求解题思…...
复杂 SQL 实现分组分情况分页查询
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、根据 camp_status 字段分为 6 种情况 1.1 SQL语句 1.2 SQL解释 二、分页 SQL 实现 2.1 SQL语句 2.2 根据 camp_type 区分返…...
JavaScript---如何完美的判断返回对象是否有值
如何判断一个对象为空是我们在开发中经常会遇到的问题,今天我们来聊聊几种经常使用的方法,以及在不同的场景下我们如何去使用。 1. JSON.stringify JSON.stringify 方法可以使对象序列化,转为相应的 JSON 格式。 js 复制代码 const obj {…...
kafka offset sasl加密连接
kafka-tool(offset) 进行SCRAM连接,直接上图 填写jaas的认证(账密 引用包)...
Android studio矩形背景颜色以及弧度的设置
在这里插入图片描述 Android的shape中主要设置的属性 corners:用于设置形状的圆角,可以设置圆角的半径、颜色等属性。 stroke:用于设置形状的边框,可以设置边框的宽度、颜色等属性。 padding:用于设置形状的内边距&…...
Acrel-1000DP分布式光伏系统在某重工企业18MW分布式光伏中应用——安科瑞 顾烊宇
摘 要:分布式光伏发电特指在用户场地附近建设,运行方式以用户侧自发自用、余电上网,且在配电系统平衡调节为特征的光伏发电设施,是一种新型的、具有广阔发展前景的发电和能源综合利用方式,它倡导就近发电,就…...
3 python基本语法 - Dict 字典
Python 中字典(dict)是一种无序的、可变的序列,它的元素以“键值对(key-value)”的形式存储。相对地,列表(list)和元组(tuple)都是有序的序列,它们…...
Magnific AI:彻底改变 AI 生成图像的升级
在我最近与 Magnific AI 的讨论中,我不仅感到惊讶,而且对该工具提供的质量和可能性着迷。我发现 Magnific AI 能够转换人工智能生成的图像(这些图像通常只能以低分辨率提供),尤其令人印象深刻,不仅在可打印…...
BKP 备份寄存器 RTC 实时时钟-stm32入门
这一章节我们要讲的主要内容是 RTC 实时时钟,对应手册,是第 16 章的位置。 实时时钟这个东西,本质上是一个定时器,但是这个定时器,是专门用来产生年月日时分秒,这种日期和时间信息的。所以学会了 STM32 的…...
1.1 数据结构-数据的表示
文章目录 1.1.1 二元关系及其性质:1.1.1.1 笛卡尔积:1.1.1.2 二元关系:持续更新当中 ....... 1.1.1 二元关系及其性质: 数据的基本单元称为额数据元素,数据是从客观事物的观测中的到的,数据元素并不是鼓励存在的,而是存在密切的联系,也因此才能表示和描述客观事物,数据元素之间…...
UNIX Linux系统 启动PPOCRLabel报错[已放弃 (核心已转储)]
参照官方教程安装后,启动PPOCRLabel报错:[已放弃 (核心已转储)] 官方链接地址:PPOCRLabelv2 $~ PPOCRLabel --lang ch QObject::moveToThread: Current thread (0x561534309430) is not the objects thread (0x56153929eac0). Cannot move to…...
前端开发中的webpack打包工具
前端技术发展迅猛,各种可以提高开发效率的新思想和框架层出不穷,但是它们都有一个共同点,即源代码无法直接运行,必须通过转换后才可以正常运行。webpack是目前主流的打包模块化JavaScript的工具之一。 本章主要涉及的知识点有&am…...
Mybatis配置-数据库厂商标识(databaseIdProvider)
MyBatis可以根据数据库供应商执行不同的语句。多数据库供应商支持是基于映射语句的databaseId属性。MyBatis将加载所有没有databaseId属性或具有与当前数据库匹配的databaseId属性的语句。如果找到具有和不具有databaseId的相同语句,则后者将被丢弃。要启用多供应商…...
【Java】使用递归的方法获取层级关系数据demo
使用递归来完善各种业务数据的层级关系的获取 引言:在Java开发中,我们通常会遇到层层递进的关系型数据的获取问题,有时是树状解构,或金字塔结构,怎么描述都行,错综复杂的关系在程序中还是可以理清的。 这…...
零基础玩转Qwen2.5-7B:5分钟本地部署,小白也能跑通AI对话
零基础玩转Qwen2.5-7B:5分钟本地部署,小白也能跑通AI对话 1. 前言:为什么选择Qwen2.5-7B AI大模型正在改变我们与技术互动的方式,但对于普通用户来说,部署和使用这些模型往往充满挑战。Qwen2.5-7B作为阿里开源的最新…...
影墨·今颜效果实测:100张生成图中98.3%通过小红书内容审核标准
影墨今颜效果实测:100张生成图中98.3%通过小红书内容审核标准 1. 真实效果惊艳展示 「影墨今颜」作为基于FLUX.1-dev引擎的高端AI影像系统,在实际测试中展现出了令人印象深刻的效果表现。我们进行了严格的批量测试,生成100张不同风格的人像…...
mrm-can-bus:轻量级嵌入式CAN设备服务协议库
1. 项目概述mrm-can-bus是一个面向嵌入式设备控制场景的轻量级 CAN 总线通信库,定位为“CAN Bus connectivity and local functions exposed via CAN Bus, common part”——即提供标准化的 CAN 连接能力,并将本地设备功能(如 GPIO 控制、ADC…...
AI教材生成大揭秘!工具选择与低查重教材编写的实用干货
在教材编写的过程中,许多编辑者常常会感到遗憾:尽管正文章节已经经过了反复打磨,但因为缺乏必要的配套资源,整体教学效果却受到影响。课后练习的设计需要具有层次感,但缺乏灵活的想法;教学课件希望能做到形…...
CTE、临时表、子查询如何选?
在 SQL Server 等关系型数据库中,处理复杂查询逻辑时,子查询 (Subquery)、临时表 (Temporary Table) 和公共表表达式 (CTE, Common Table Expression) 是三种核心工具。它们各有优劣,选择哪种取决于具体的性能需求、数据规模、代码可读性以及…...
2026 LinkedIn账号安全机制分析与稳定运营实践
随着 LinkedIn 风控机制的不断完善,账号的登录环境、行为模式以及网络条件,都会直接影响账号的稳定性。对于需要长期运营账号的用户来说,理解平台的风控逻辑,比单纯增加操作频率更为重要。本文将从使用场景、常见环境问题、账号行…...
STM32实现智能酒驾监测系统设计
基于STM32的酒后驾车监测报警系统设计与实现1. 项目概述1.1 系统背景酒后驾车是全球交通事故的主要诱因之一,传统的人工检测方法存在效率低、覆盖范围有限等问题。随着嵌入式系统和物联网技术的发展,智能化的酒精监测系统成为解决这一问题的有效方案。1.…...
AD21实战:3种方法搞定Keepout和机械层互转,最后一种能救急
AD21实战:3种高效解决Keepout与机械层互转难题的方法 在PCB设计过程中,Keepout层和机械层的正确使用与转换是确保设计准确性的关键环节。许多工程师都遇到过这样的困境:当设计文件中包含复杂图形元素时,简单的层切换或属性批量修…...
管人对账累垮人?巨有科技智慧市集系统一招减负
从城市商圈到景区古镇,从乡村田园到文创园区,各类市集遍地开花,但管理难题始终是制约行业发展的最大瓶颈。人工登记杂乱、对账结算繁琐、现场管控滞后、数据完全空白,一场中型市集就要耗费大量人力物力,大型市集更是纠…...
开源编解码引擎OpenH264全解析:技术原理与实战技巧
开源编解码引擎OpenH264全解析:技术原理与实战技巧 【免费下载链接】openh264 Open Source H.264 Codec 项目地址: https://gitcode.com/gh_mirrors/op/openh264 在视频通信、直播和多媒体应用开发中,如何在保证画质的同时实现高效压缩ÿ…...
