Spring统一格式返回

目录

一:统一结果返回

1:统一结果返回写法

2:String类型报错问题

解决方法

二:统一异常返回

统一异常返回写法

三:总结


同志们,今天咱来讲一讲统一格式返回啊,也是好久没有讲过统一格式返回了,说实话这个统一格式返回就是一个让咱返回的数据能有一个统一的格式嘛,不为别的就为了和你一块共事的同事不会提着刀追着你满大街跑,要跟你交流交流工作经验。

前端:我这数据咋老是对不上啊?

后端:奥兄弟,这个接口我返回的是Boolean类型

前端:我这数据怎么又对不上了啊?

后端:奥好兄弟,我觉得Boolean类型太丑了我就换成String类型了,我觉得它顺眼点。

前端:

那咱肯定不能让同事追着我们交流经验啊,所以我们一定要让咱返回的数据能有一个统一的格式

一:统一结果返回

1:统一结果返回写法

定义返回模板

想要统一返回一个结果,就肯定要有一个返回结果的模板这里我们用Result类来定义

下面代码中有Result有三个属性,状态码,错误信息,返回的数据,三个方法分别是成功时返回,和失败时返回。

@Data
public class Result<T> {private Integer code;//后端响应状态码,成功200,失败-1,-2表示未登录private String errmsg;//后端发生错误的原因private T data;//每个接口返回的类型(BookInfo,boolean之类的,类型不固定所以要用泛型)/** 成功时设置* */public  static<T> Result<T> success(T data){//泛型方法加static需要加上<T>Result result = new Result<>();result.setData(data);result.setCode(200);return result;}/*失败时设置* */public  static<T> Result<T> fail(String errMsg){Result result = new Result<>();result.setCode(-1);result.setErrmsg(errMsg);return result;}public  static<T> Result<T> fail(T data,String errMsg){Result result = new Result<>();result.setData(data);result.setCode(-1);result.setErrmsg(errMsg);return result;}
}

实现ResponseBodyAdvice接口并重写方法,再加上@ControllerAdvice注解

@ControllerAdvice:这个注解的作用就是标记这个类为全局控制器增强类

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {return Result.success(body);//返回封装后结果结果}
}

support()方法:

作用:

supports 方法用于判断是否需要对某个返回值进行处理,返回true就是处理,返回false就是不处理

参数解析:

returnType:这个参数就是表示控制器方法(Controller类)的返回类型信息,它封装的有方法的返回参数的详细信息,比如方法本身,方法所属的类,返回的类型等等...可以根据这些信息来决定是否要对返回值进行处理,返回对应的true或false

Class converterType:这个参数的意思就是用于将响应体对象,转换为,HTTP响应消息的那个消息转换器的类型,后面我们会说到,先按下不表

beforeBodyWrite()方法:

作用:

我们直译一下这个方法的名字是:写 body 之前 ,意思就是在控制器方法返回之前进行的处理

当support方法返回true之后,beforeBodyWrite()方法就需要对返回值进行一些处理

参数解析:

Object body:该参数表示控制器方法实际返回的响应体对象

MethodParameter returnType:同supports方法中的returnType

 MediaType selectedContentType:表示响应的类型,如application/json

 Class selectedConverterType:表示用于将响应体对象转换为 HTTP 响应的消息转换器的类型

 request和response:这个我们很熟悉,就是代表Http的请求和响应

我们定义几个简单的控制器类

@RestController
public class Controller {@RequestMapping("/t1")public int t1(){return 1;}@RequestMapping("/t2")public Boolean t2(){return true;}@RequestMapping("/t2")public String t3(){return "老皇甫";}
}

然后启动项目测试发现

t1和t2方法没问题,都对控制器的返回结果进行了封装,但是返回String类型的t3却报错了,这是为什么呢?

 

2:String类型报错问题

首先明确一点,这个报错的原因是类型不匹配问题,报的是ClassCastException

我黄色框框里面框的翻译一下就是Result类型和String类型不匹配,那么为什么呢?

还记得我在解释方法的参数的时候那个先按下不表的Class converterType 参数吗?converterType的意思是转换器类型,SpringMVC默认会注册⼀些⾃带的 HttpMessageConverter(Http消息转换器),它是以链表的形式组织的,它们的顺序是

 ByteArrayHttpMessageConverter()->StringHttpMessageConverter()
->SourceHttpMessageConverter<>()->AllEncompassingFormHttpMessageConverter()

 其中这个AllEncompassingFormHttpMessageConverter()是根据项目的依赖情况来添加对应的转换器的,如果我们添加了Jackson依赖一般会添加MappingJackson2HttpMessageConverter()转换器到消息转换器链表的末尾

Spring会根据返回的数据类型, 从 messageConverters 链(就是那个链表)选择 合适的消息转换器 .
当返回的数据是⾮字符串时, 使⽤的 MappingJackson2HttpMessageConverter 写⼊返回对象(那个在链表末尾的消息转换器)
.
当返回的数据是字符串时 StringHttpMessageConverter 会先被遍历到,这时会认为
StringHttpMessageConverter 可以使⽤,然后就会用StringHttpMessageConverter

我们下面调用的堆栈信息中也发现,最后AbstractMessageConverterMethodProcessor调用的也是StringHttpMessageConverter

这里是AbstractMessageConverterMethodProcessor中的逻辑,body在经过beforeBody方法包装过之后,就会从String类型变为Result类型,但现在匹配到的还是StringHttpMessageConverter 消息转换器

我们点进去这个 StringHttpMessageConverter 的write方法中看一下(点击那个由AbstractHttpMessageConverter实现的

)发现里面有一个addDefaultHeader方法(由 StringHttpMessageConverter实现的),再点进去这个方法,发现这个方法接收到的是String参数,但在上面的我们在beforBodyWrite方法中已经将参数转换为了Result类型,所以才会报出类型不匹配异常

解决方法

既然是因为参数不匹配导致的错误,那就只需要将参数搞成匹配的就行了,如下图所示,如果返回的是字符串类型,那么就将返回类型序列化成字符串类型,而不是Result类型
 

我知道同志们有时候看源码很懵,不知道哪个调用哪个,这里可以说一下在控制台打印的日志中,调用的顺序一般就是下面的调用上面的,一层一层的,Spring的调用链几乎都有十几层,所以看的很懵是很正常的 

二:统一异常返回

还有一个问题,不知道同志们发现没有,就是上面我们在由于String类型不匹配报错的时候哪个返回结果状态码竟然还是200,但这个200可是成功的状态码,这都报错了,那状态码肯定能是200啊,所以这个返回结果肯定是不正确的。

统一异常返回写法

这时候我们就需要通过统一异常捕获,构造出另一种返回结果失败的格式,来返回我们可以用

@ControllerAdvice + @ExceptionHandler 两个注解来实现
写法非常简单,就是加上个@ExceptionHandler后面指定要捕获哪种类型的异常,然后进行对应的封装逻辑,Exception你也可以进行自定义异常,来满足你不同的项目需求
因为我们希望给客户端返回的是数据类型,而不是一个视图,所以要加上@ResponseBody注解
@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {@ExceptionHandler(Exception.class)//捕获所有异常public Result handleException(Exception e) {return Result.fail(e.getMessage()+"异常");}@ExceptionHandler(Error.class)//捕获error类型public Result handleError(Error e) {return Result.fail(e.getMessage()+"错误");}@ExceptionHandler(RuntimeException.class)//捕获运行时异常public Result handleRuntimeException(RuntimeException e) {return Result.fail(e.getMessage()+"运行时异常");}@ExceptionHandler(NullPointerException.class)//捕获空指针异常public Result handleNullPointerException(NullPointerException e) {return Result.fail(e.getMessage()+"空指针异常");}}

我们来认为制造几个异常

查看测试结果

状态码为-1,返回结果符合预期

三:总结

这篇我们说的也不多,大概就是说了一下

为什么要进行统一的格式返回,

然后统一格式返回的写法

再是String类型会报错的问题以及源码级别的原因,

然后是统一异常返回问题

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

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

相关文章

【无标题】四色拓扑模型与宇宙历史重构的猜想框架

### 四色拓扑模型与宇宙历史重构的猜想框架 --- #### **一、理论基础&#xff1a;四色拓扑与时空全息原理的融合** 1. **宇宙背景信息的拓扑编码** - **大尺度结构网络**&#xff1a;将星系团映射为四色顶点&#xff0c;纤维状暗物质结构作为边&#xff0c;构建宇宙尺度…

蓝桥杯 封闭图形个数

蓝桥杯 封闭图形个数 题目 链接 解答 # 数字个数 n int(input()) # 数字 ls input().split() # 统计数字的圈数 o_nums {} for i, x in enumerate(ls):o_num 0for c in x:if int(c) in [0, 4, 6, 9]:o_num 1elif c 8:o_num 2o_nums[i] o_num # 字典根据圆圈数排序 …

基于javaweb的SpringBoot学生在线考试管理系统设计和实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…

国产编辑器EverEdit - 超多样式设置

1 设置-编辑-样式 1.1 设置说明 1.1.1 折叠样式 默认为箭头&#xff0c;折叠样式选项如下&#xff1a; 箭头&#xff1a; 矩形和线条 五边形 圆形图标 1.1.2 光标样式 光标用于指示当前用户输入位置&#xff0c;光标样式选项如下&#xff1a; 默认 纤细 字宽 …

Linux - 线程控制

一、线程概念 1&#xff09;线程地址空间 线程与进程共享相同的虚拟地址空间&#xff0c;因此线程在访问内存时与进程没有本质的区别。但线程共享和独占的内存区域有不同的特点&#xff0c;理解这些特性对于正确使用线程至关重要。 1. 线程地址空间的组成 线程的地址空间是…

通过多线程分别获取高分辨率和低分辨率的H264码流

目录 一.RV1126 VI采集摄像头数据并同时获取高分辨率码流和低分辨率码流流程 ​编辑 1.1初始化VI模块&#xff1a; 1.2初始化RGA模块&#xff1a; 1.3初始化高分辨率VENC编码器、 低分辨率VENC编码器&#xff1a; 1.4 VI绑定高分辨率VENC编码器&#xff0c;VI绑定RGA模块…

部署RabbitMQ集群详细教程

部署RabbitMQ集群详细教程 下面是一份在 Ubuntu 环境下部署 RabbitMQ 集群的详细步骤说明&#xff0c;涉及主机名设置、Erlang & RabbitMQ 安装、管理插件启用、集群通信 Cookie 配置、节点加入集群、镜像队列策略设置以及集群验证等。为了演示方便&#xff0c;以下示例假…

【Linux】之【Bug】VMware 虚拟机开机 一直卡在黑屏左上角下划线闪烁界面

解决 参考&#xff1a; 解决Ubuntu20.04 开机黑屏光标闪烁进不去系统 Centos根目录100%解决思路 当前界面 ctrlaltf3-f6 暂时进入终端界面 df -h 查看发现根目录 磁盘空间已满 执行命令 查看当前目录占用内存明细 sudo du -h -x --max-depth1清理无用的大内存文件 或者安装…

webflux集成langchain4j基础版

伴随着大模型应用的兴起&#xff0c;webflux逐渐引起关注。为了以java的方式运行AI应用&#xff0c;让我们一起学习webflux集成langchain4j吧。 1. 项目依赖 首先&#xff0c;你需要在 pom.xml 中添加必要的依赖&#xff1a; <dependencies><!-- Spring WebFlux --…

使用GitLink个人建站服务部署Allure在线测试报告

更多技术文章&#xff0c;访问软件测试社区 文章目录 &#x1f680;前言&#x1f511;开通GitLink个人建站服务1. 前提条件2. 登录GitLink平台&#xff08;https://www.gitlink.org.cn/login&#xff09;3. 进入设置>个人建站>我的站点4. 新建站点5. 去仓部进行部署6. 安…

go数组的声明和初始化

1.数组简介 数组是可以存放多个同一类型的数据。数组也是一种数据类型&#xff0c;在go中&#xff0c;数组是值类型。数组的长度也是数组类型的一部分&#xff0c;所以[2]int和[3]int属于不同的数据类型。 2.数组的长度也是类型的一部分 var arr1 [2]intvar arr2 [3]intfmt.P…

四款GIS工具箱软件解析:满足企业多样化空间数据需求

概述 随着地理信息系统&#xff08;GIS&#xff09;在城市规划、环境监测、资源管理等领域的广泛应用&#xff0c;各种GIS工具箱软件不断涌现&#xff0c;为用户提供了强大的数据处理、空间分析和地图制图功能。本文将为大家介绍4款GIS工具箱软件&#xff0c;这些软件各具特色…

VirtualBox虚拟机安装Mac OS启动后的系统设置

VirtualBox虚拟机安装Mac OS一直没装成功&#xff0c;本来想要放弃的&#xff0c;后来想着再试一次&#xff0c;于是在关机的情况&#xff0c;执行那几句设置&#xff1a; cd "E:\Program Files\Oracle\VirtualBox\" VBoxManage.exe modifyvm "MacOS" --c…

[力扣每日一练]关于所有不同域名的查找

一、题目要求&#xff1a; 表&#xff1a;Emails---------------------- | Column Name | Type | ---------------------- | id | int | | email | varchar | ---------------------- id 是这张表的主键&#xff08;有不同值的列&#xff09;。 这张表的…

blender看不到导入的模型

参考&#xff1a;blender 快捷键 常见问题_blender材质预览快捷键-CSDN博客 方法一&#xff1a;视图-裁剪起点&#xff0c;设置一个很大的值 方法二&#xff1a;选中所有对象&#xff0c;对齐视图-视图对齐活动项-选择一个视图

HarmonyOS Next~鸿蒙系统ArkCompiler跨平台编译技术的革新实践

HarmonyOS Next~鸿蒙系统ArkCompiler跨平台编译技术的革新实践 引言 在万物互联时代&#xff0c;操作系统对编译技术的需求已从单纯的代码转换演变为跨设备协同、高效资源调度与极致性能优化的综合挑战。华为鸿蒙系统&#xff08;HarmonyOS&#xff09;自主研发的ArkCompiler…

Kanna 与 Swift:结合使用提升网络请求效率

Kanna 是一个基于 Swift 的轻量级、高性能的 XML/HTML 解析库&#xff0c;它能够帮助开发者快速解析和处理网络返回的 HTML 或 XML 数据。通过结合 Kanna 和 Swift 的网络请求功能&#xff0c;我们可以构建更加高效、灵活的网络交互模块。本文将详细介绍如何在 Swift 中使用 Ka…

《大语言模型的原理发展与应用》:此文为AI自动生成

《大语言模型的原理发展与应用》&#xff1a;此文为AI自动生成 一、引言&#xff1a;大语言模型&#xff0c;AI 时代的 “新引擎” 在当今数字化浪潮中&#xff0c;大语言模型宛如一颗璀璨的明星&#xff0c;照亮了人工智能发展的道路&#xff0c;成为推动各领域变革的核心驱…

RabbitMQ消息队列 面试专题

RabbitMQ消息队列 面试专题 RabbitMQ的实现原理为什么需要消息队列常见消息队列比较如何保证消息不丢失如何防止消息重复消费如何保证消息的有序性如何处理消息堆积 RabbitMQ的实现原理 RabbitMQ 是一个基于 AMQP&#xff08;Advanced Message Queuing Protocol&#xff09; 协…

【Hudi-SQL DDL创建表语法】

CREATE TABLE 命令功能 CREATE TABLE命令通过指定带有表属性的字段列表来创建Hudi Table。 命令格式 CREATE TABLE [ IF NOT EXISTS] [database_name.]table_name[ (columnTypeList)]USING hudi[ COMMENT table_comment ][ LOCATION location_path ][ OPTIONS (options_lis…