Spring Boot 统一功能处理(二)

news2025/1/2 3:00:37

        本篇主要介绍Spring Boot统一功能处理中的统一数据返回格式。

目录

一、定义统一的返回类

 二、配置统一数据格式

三、测试配置效果

四、统一格式返回的优点 

五、源码角度解析String问题


一、定义统一的返回类

在我们的接口在处理请求时,返回的结果可以说是参差不齐,既可以是一个String类型的数据,又可以是一个Integer类型的数据,这样未免会显得我们的代码很不规范,并且这种不规范的代码还会增加前后端之间的交流成本。因此,我们可以设计一个统一的类来作为所有接口的返回结果。这个统一的类通常需要包含以下三个部分:

  • code:由我们自己定义的一个状态码
  • msg:响应结果的描述
  • data:响应的数据

下面我们通过代码来具体来实现一下这个类 :

这里可以使用泛型来作为data的参数,毕竟返回的数据类型是多种多样的。

下面我们来改造一下上一篇中所定义的login方法:

这里的状态码200代表请求成功,-1代表失败。

仔细观察可以发现,这串代码其实是有点冗余的,每次返回数据时都得设置一次Result的三个属性。因此,我们还可以对Result进行一些优化,具体如下:

这里我们将设置Result属性的代码进行了封装,因此接口在返回数据时,直接调用这里的方法即可(由于fail表示请求失败,请求失败了通常不会有返回的数据,因此fail没有设置data参数)。接下来我们再优化一下前面的login方法:

 

这样代码就看着简洁多了。

 二、配置统一数据格式

虽然我们这里已经定义了统一的数据返回类Result,但我们并不能保证所有接口都会以这个类作为返回结果,因此我们还需要借助Spring 来配置一下统一的数据返回格式。

首先我们需要创建一个类来实现ResposeBodyAdvice:

然后重写两个方法:

 其中supports是用来选择要进行统一返回处理的方法,如果直接返回true那就是所有接口都会进行这个统一处理,如果不想全部都统一处理,也可以通过下面的方式获取相关的类或者方法,并以此来判定是否要统一处理:

         //获取执行返回操作的类
        Class<?> declaringClass = returnType.getMethod().getDeclaringClass();
        //获取执行返回操作的方法
        Method method = returnType.getMethod();

 另一个方法beforeBodyWrite是对返回的数据具体进行统一处理的逻辑,其中body就是我们在接口里返回的数据。这里已经写好了一个大体逻辑,如果是我们前面定义的返回类直接返回,如果不是就把body封装到返回类里再返回。

最后我们还需要再类上加上一个@ControllerAdvice注解:

通过这个注解的实现可以发现,他是@Component的衍生注解,因此加了这个注解的类也会被加到Spring容器中。并且可以发现@ControllerAdvice还多了很多别的功能,这里就不过多介绍了。 

三、测试配置效果

接下来我们通过postMan来测试一下配置的效果。

我们先测试一下返回类型为Result的接口:

postMan请求后的结果:

通过结果可以发现响应符合我们的统一要求。

然后我们创建一个返回值不为Result的接口:

通过PostMan来访问可以发现结果也是符合预期的:

 

然后我们再试试返回集合:

通过postMan来访问一下可以发现结果正常:

接下来我们再看看返回对象,

首先我们创建一个User类然后对这个User类进行返回:

通过PostMan可以发现结果正确。

最后我们再来看一下返回类型是String类型:

 通过PostMan来访问可以发现报错了:

 我们再去后端看一下:

可以发现后端报了一个类型不匹配异常,至于为什么会报这个异常,后面会解释,我们先来看看解决方法。

首先我们得在项目中引入Jackson依赖,由于Spring web中内置了这个依赖,因此不需要自己特意去引入Jackson直接引入Spring web依赖即可。

然后使用Jackson提供的ObjectMapper类,由于Spring中已经自动添加了这个类的Bean,我们可以直接注入使用,然后利用Object将返回的Result转为字符串,由于使用objectmapper转换成字符串需要处理一个异常,因此在这里可以加上@SneakyThrows(使用这个注解可以将受检查异常转为非受检查异常(运行时异常),从而使我们不再需要去处理异常信息)具体代码如下:

我们再通过postMan来测试一下,可以发现,这次没有报错了,但返回类型不在是Json,而是text了:

四、统一格式返回的优点 

为什么要这么大费周章设置一个统一返回的格式呢。因为它具有如下一些优点:

  • 方便前端接受和处理后端响应的数据
  • 降低了前后端的沟通成本
  • 有利于项目统一数据的维护和修改
  • 有利于后端进行统一的规范和标准制定,以免后端返回一些乱七八糟的数据
五、源码角度解析String问题

接下来我们从源码角度来解释一下为什么当返回的数据类型是String时在进行统一返回处理时会出现类型不匹配异常。

Spring mvc在使用时,会自动注册一些自带的HttpMessageConverter来处理返回的数据,注册的先后顺序为:

ByteArrayHttpMessageConverter、StringHttpMessageConverter、SourceHttpMessageCoverter、AllencompassingFormHttpMessageConverter

在注册AllencompassingFormHttpMessageConverter时会去引入一些根据项目依赖去引入其它的拓展HttpMessageConvert,例如,项目中如果添加了Jackson则会引入MappingJackson2HttpMessageConverter。

这些HttpMessageConverter会按照注册的顺序形成一条调用链,如果有数据返回时,spring会对这条链按照先后顺序进行遍历 ,如果找到能处理当前返回数据的数据类型的HttpMessageConverter则会直接使用这个HttpMessageConverter来处理,当我们返回的数据类型是非String时,例如集合,对象等,由于前面的几个HttpMessageConverter都不能使用,所以会使用前面最后引入的MappingJackson2HttpMessageConverter来处理数据,而当返回的是String时,则能够使用StringHttpMessageConverter来进行处理,而StringHttpMessageConverter又在链中靠前的位置,因此在返回String时会使用StringHttpMessageConverter来进行处理。

接下来我们进到HttpMessageConverter处理数据的具体方法writeWithHttpMessageConvert来看一下:

打开方法实现往下翻可以看到这样一行代码

仔细观察可以发现这行代码就是在调用我们前面所设置beforeBodyWrite方法,由此可以推断出在执行完这行代码后body由String转换为我们前面所设置的Result类型了。

继续往下翻可以发现这样一行代码

 由于我们返回的是String,所以这里的converter应该是StringHttpMessageConverter类型的,我们进到write(这里使用的是StringHttpMessageConverter父类AbstarctHttpMessageConverter实现的write方法)方法来看一下:

可以发现在这里使用的是泛型参数t来接收body,因此没有出现类型匹配问题,在这个方法里调用了一个addDefaultHeaders方法,由于StringHttpMessageConverter重写了这个方法,因此在这里使用的是StringHttpMessageConverter实现的这个方法,我们进到里面去看一下:

进到里面可以发现这个方法采用的是String类型的s来接收我们前面的t,也就是body,但body已经在前面通过我们定义的beforeBdoyWriter方法由String转换为了Result类型,因此这里在接收参数时,发生了类型不匹配异常,从而也就产生了前面类型不匹配的报错。

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

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

相关文章

UE C++ 学习

UBT&#xff08;虚幻编译工具&#xff08;UnrealBuildTool&#xff09;&#xff09;和UHT虚幻头工具&#xff08;UnrealHeaderTool&#xff09; UE有一组用于自动执行编译虚幻引擎过程的工具&#xff0c;包括 UBT和UHT&#xff08;以及其他工具&#xff09;。实现这一套工具的目…

Aritest+python+Jenkins解放双手iOS/Android自动化

ARITest、Python 和 Jenkins 可以结合在一起创建一个自动化测试解决方案&#xff0c;实现持续集成和持续测试的目标。以下是三者如何协同工作的基本概念&#xff1a; 1. **ARITest**&#xff1a; ARITest 是一款功能全面的自动化测试工具&#xff0c;提供 UI 自动化、接口自…

CSS3 立体 3D 变换

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 ✍CSS3 立体 3D 变换&#x1f48e;1 坐标轴&#x1f48e;2 perspective 透视视…

Vue(二):报错调试,vue3响应式原理、computed和watch,ref,props,接口

一、准备工作调试 跟着张天禹老师看前几集的时候可能会遇到如下问题&#xff1a; 1.下载插件&#xff1a;Vue Language Features (Volar)或者直接下载vue-offical 2.npm run serve时运行时出现错误&#xff1a;Error: vitejs/plugin-vue requires vue (&#xff1e;3.2.13) …

Flutter仿Boss-7.首页列表

效果 考察使用 Flutter Model的创建TabBar及TabBarView 的使用标签Wrap控件的使用列表ListView的使用 具体实现 今天懒的写文字了&#xff0c;想看具体实现的可以直接去我的github上&#xff1a; github&#xff1a;github.com/yixiaolunhui/flutter_project

PostgreSQL入门到实战-第二十四弹

PostgreSQL入门到实战 PostgreSQL中表连接操作(八)官网地址PostgreSQL概述PostgreSQL中CROSS JOIN命令理论PostgreSQL中CROSS JOIN命令实战更新计划 PostgreSQL中表连接操作(八) 使用PostgreSQL CROSS JOIN从连接的表中生成行的笛卡尔乘积。 官网地址 声明: 由于操作系统, 版…

Xcode 15.0 新 #Preview 预览让 SwiftUI 界面调试更加悠然自得

概览 从 Xcode 15 开始&#xff0c;苹果推出了新的 #Preview 宏预览机制&#xff0c;它无论从语法还是灵活性上都远远超过之前的预览方式。#Preview 不但可以实时预览 SwiftUI 视图&#xff0c;而且对 UIKit 的界面预览也是信手拈来。 想学习新 #Preview 预览的一些超实用调试…

计算机服务器中了360后缀勒索病毒怎么办?360后缀勒索病毒解密步骤

网络技术的不断应用与发展&#xff0c;为企业的生产运营提供了极大便利&#xff0c;利用网络可以开展各项工作业务&#xff0c;可以大大提高企业的生产效率&#xff0c;然而&#xff0c;网络是一把双刃剑&#xff0c;在为企业提供便利的同时&#xff0c;也为企业的数据安全带来…

蓝桥杯【第15届省赛】Python B组

这题目难度对比历届是相当炸裂的简单了…… A&#xff1a;穿越时空之门 【问题描述】 随着 2024 年的钟声回荡&#xff0c;传说中的时空之门再次敞开。这扇门是一条神秘的通道&#xff0c;它连接着二进制和四进制两个不同的数码领域&#xff0c;等待着勇者们的探索。 在二进制…

Leetcode刷题之移除元素(C语言版)

Leetcode刷题之移除元素&#xff08;C语言版&#xff09; 一、题目描述二、题目解析 一、题目描述 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅…

旧版本jquery升级新版本后如何处理兼容性问题

前言 最近项目在漏洞扫描过程中发现现在的jquery版本受多个跨站点脚本漏洞影响&#xff0c;需要升级jquery版本。 1、首先下载高版本的jquery&#xff0c;我这里升级的是3.6.0 2、对应的bootstrap版本也要升级&#xff0c;这里升级的是3.3.7 本来以为替换完这两个文件后&#…

LeetCode654:最大二叉树

题目描述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums 构建的 …

STM32+ESP8266水墨屏天气时钟:文字取模和图片取模教程

项目背景 本次的水墨屏幕项目需要显示一些图片和文字&#xff0c;所以需要对图片和文字进行取模。 取模步骤 1.打开取模软件 2.选择图形模式 3.设置字模选项 注意&#xff1a;本次项目采用的是水墨屏&#xff0c;并且是局部刷新的代码&#xff0c;所以设置字模选项可能有点…

自定义注解(二)——系统日志记录

在上一篇自定义注解&#xff08;一&#xff09;——统一请求拦截中对自定义注解做了简单说明及关于统一token认证的应用示例。其实对于自定义注解&#xff0c;还有一种常用的方法是用于系统日志记录&#xff0c;此处的系统日志记录&#xff0c;区别于Slf4j或Log4j把日志文件写入…

Big Data and Cognitive Computing (IF=3.7) 期刊投稿

Special Issue: Artificial Cognitive Systems for Computer Vision 欢迎计算机视觉相关工作的投稿&#xff01; 影响因子3.7&#xff0c;截止时间2024年12月31日 投稿咨询&#xff1a;lqyan18fudan.edu.cn 投稿网址&#xff1a;https://www.mdpi.com/journal/BDCC/special_iss…

模板方法模式:定义算法骨架的设计策略

在软件开发中&#xff0c;模板方法模式是一种行为型设计模式&#xff0c;它在父类中定义一个操作的算法框架&#xff0c;允许子类在不改变算法结构的情况下重定义算法的某些步骤。这种模式是基于继承的基本原则&#xff0c;通过抽象类达到代码复用的目的。本文将详细介绍模板方…

【算法刷题 | 回溯思想 02】4.12(电话号码的字母组合)

文章目录 4.电话号码的字母组合4.1问题4.2解法&#xff1a;回溯4.2.1回溯思路&#xff08;1&#xff09;函数返回值以及参数&#xff08;2&#xff09;终止条件&#xff08;3&#xff09;遍历过程 4.2.2代码实现 4.电话号码的字母组合 4.1问题 给定一个仅包含数字 2-9 的字符…

阻塞队列和生产消费模型

阻塞队列 阻塞队列的概念 队列相信我们已经不陌生了 之前也学过很多队列 比如: 普通队列 和 优先级队列 两种 这两种队列都是线程不安全的 而我们讲的阻塞队列 刚好可以解决线程安全问题 也是先进先出 并且带有阻塞功能. 阻塞功能是怎么回事呢 就是如果入队的时候阻塞队列为…

AI的智商如何测试?

一、AI的智商测试 AI的智商测试不同于人类的智商测试&#xff0c;因为它涉及到不同类型的智能和功能衡量标准。以下是几种常见的AI智商测试或评估方式&#xff1a; 此图片来源于网络 1. **功能性测试**&#xff1a; - 对于算法或机器学习模型&#xff0c;可以通过标准化的基…

探秘大模型:《提示工程:技巧、方法与行业应用》背后的故事

提示工程是一种新兴的利用人工智能的技术&#xff0c;它通过设计提示引导生成式 AI 模型产生预期的输出&#xff0c;来提升人与 AI 的互动质量&#xff0c;激发 AI 模型的潜力&#xff0c;提升AI的应用水平。 为了让每一个人都拥有驱动大模型的能力&#xff0c;以微软全球副总裁…