Feign返回值统一处理
背景
服务端的接口一般有固定的返回格式,有数据、返回码和异常时错误信息。结构如下
@Data
public class BaseResponse<T> {private String code;private String message;private T data;public boolean isSuccess() {return "SUCCESS".equals(code);}
}
正常情况下我们只关注里面的data字段。不做任何处理情况下,需要将BaseResponse
类型作为Feign Client方法的返回值,然后在调用Feign的业务代码处手动调用getData()
方法来获取数据。这种重复的代码可以抽出来统一处理(请求数据也类似)。
解决方案
使用自定义Decoder
来统一处理,重写Object decode(Response response, Type type)
方法,其中Response
就是被调用接口返回的响应,Type
就是Feign Client方法的返回值,它的实际类型有四种基本情况(其他都是这四种的排列组合),一种是不带泛型的类,一种带固定泛型的类,一种是不固定的T类型的泛型,最后一种是带?的分别如下
本文只讨论前面两种类型,后面两种类型实际传到
Decode
中是没法知道实际类型的,除非通过某种方法把返回的实际类型传到Decode
中(比如ThreadLocal、方法参数、请求头等等),或者泛型是有上界的,如<T ? extends UpUser>
,那么可以通过type
的getBounds()
方法获取到上界类型,进行序列化。否则无法确定确定类型的,进行反序列化。
现在就是要将Response中的返回值转换成BaseResponse
类型,而且是包括BaseResponse
里面T这个泛型的,如果T中还带了泛型,不论嵌套几层都需要转换好,这样调用地方可以直接使用。我使用的序列化工具是Gson(ObjectMapper也是类似的)。
带泛型的转换其实是有现有的方法可以直接转的,但是这里有点难处理的是,将BaseResponse
类型和参数中的Type
合并成一个,作为参数传到Gson
的fromJson
方法中,查看Type
类的实现类,发现有一个ParameterizedType
接口,这个就是描述了对象的参数类型。每个方法说明如下
public interface ParameterizedType extends Type {/*** 返回里面的泛型,比如List<String>, 那么这个方法返回String,如果是Map<String, Integer>那么这个方法返回{String, Integer}的数组* @since 1.5*/Type[] getActualTypeArguments();/*** 返回当前这个类的类型,比如List<String>, 那么这个方法返回List,如果是Map<String, Integer>那么这个方法返回Map*/Type getRawType();/*** 如果是内部类的情况,这个方法返回的是最外层的类,也就是封闭类,比如O<T>.I<S>这种类型,返回的是O<T>*/Type getOwnerType();
}
要注意一点,Class对象也是实现了Type接口的。
ParameterizedType
接口解决了参数合并的问题,自定一个参数类型类,实现这三个方法
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class MyParameterizedType implements ParameterizedType {private Type type;/*** 将Feign Client方法的返回值注入,只要两种类型,一种是ParameterizedTypeImpl,另一种是具体的Class对象*/public MyParameterizedType(Type type) {this.type = type;}/*** 属性Type就是BaseResponse的泛型类型,直接返回type就可以*/@Overridepublic Type[] getActualTypeArguments() {Type[] types = new Type[1];types[0] = type;return types;}/*** 最外层的类型就是我们要与type合并的BaseResponse类型*/@Overridepublic Type getRawType() {return BaseResponse.class;}/*** 这个Owner一般没用到,如果type是个内部类静态类情况下,需要返回最外部的类型,这里直接调用Class对象获取封闭类的方法*/@Overridepublic Type getOwnerType() {if (type instanceof ParameterizedTypeImpl) {ParameterizedTypeImpl typeImpl = (ParameterizedTypeImpl) type; return typeImpl.getRawType().getEnclosingClass();}if (type instanceof Class) {return ((Class) type).getEnclosingClass();}return null;}
}
这样序列化问题就能解决了,现在只要编写Decoder
类就可以了。
import com.google.gson.Gson;
import feign.FeignException;
import feign.Response;
import feign.codec.Decoder;import java.io.IOException;
import java.lang.reflect.Type;public class MyDecode implements Decoder {private Gson gson = new Gson();@Overridepublic Object decode(Response response, Type type) throws FeignException, IOException {MyParameterizedType myType = new MyParameterizedType(type);BaseResponse baseResponse = gson.fromJson(response.body().asReader(), myType);if (type instanceof BaseResponse) {return baseResponse;}if (baseResponse.isSuccess()) {return baseResponse.getData();}throw new RuntimeException("返回异常");}
}
这里加了一个BaseResponse
判断,如果需要返回整个数据,比如根据BaseResponse
的返回码做业务逻辑,就可以在Feign Client的方法返回值直接写带泛型的BaseResponse
类型。也加了一个统一的校验,如果要获取数据,需要返回码是正常才行。
总结
这种写法优点就是一次性反序列化到位,后续使用根据泛型里面的类型直接使用,如果不进行泛型合并,只转成BaseResponse
类型,如果data的类型是有很多泛型嵌套的,那么可能反序列化类型是有问题的,比如data的类型是List<User>,那么不指定详细的泛型类型,直接转成BaseResponse
类型,那么data字段序列化结果会是List<Map<String, String>,没法直接使用的。
关于参数化合并问题,这种思路可以借鉴,运用到其他场景。还有像请求数据统一封装其实也是类似,自定义一个Encoder
即可,请求就没有参数泛型的问题了。
相关文章:
![](https://img-blog.csdnimg.cn/d50ab76d6a0645d791eaa95db98aee2f.png#pic_center)
Feign返回值统一处理
背景 服务端的接口一般有固定的返回格式,有数据、返回码和异常时错误信息。结构如下 Data public class BaseResponse<T> {private String code;private String message;private T data;public boolean isSuccess() {return "SUCCESS".equals(cod…...
![](https://www.ngui.cc/images/no-images.jpg)
探究如何在Linux系统中修改进程资源限制:四种方法调整进程限制,让你的系统高效运行(包含应用层getrlimit和setrlimit API)
探究如何在Linux系统中修改进程资源限制1.进程资源限制的概念2.修改进程资源限制的意义与应用场景1.软限制与硬限制2.常见资源限制类型Linux中的资源限制1.ulimit命令a. 语法及选项b. 示例与应用2./etc/security/limits.conf配置文件a. 配置文件结构b.示例与应用3. 使用cgroups…...
![](https://img-blog.csdnimg.cn/4a70e874f4704d1abb7ea34bb7c22916.png)
9.5. 机器翻译与数据集
笔记 9.5. 机器翻译与数据集 — 动手学深度学习 2.0.0 documentation 1.下载文件 读文件 2.处理数据 在所有标点符号前面加空格 后面用于分割 因为法语英语可能有半角全角的字符区分用utf编码的方式统一成半角字符的空格 3.因为分隔用的是空格split 所有vocab是没有空格的 …...
![](https://img-blog.csdnimg.cn/img_convert/f28c52a40c66f11b35126739566bca58.jpeg)
跟着凯新生物2 Arm PEG Biotin,2-Branched PEG Biotin,生物素-聚乙二醇-二臂/支,学试剂知识
中英文名:2 Arm/Branched PEG Biotin,2 ArmPEG Biotin,二臂/支 PEG 生物素一、Product specifications: 1.CAS No:N/A 2.Packaging specification:10mg,25mg,50mg, flexible packagi…...
![](https://img-blog.csdnimg.cn/bf7ec763a130472096d37de6a92a6732.png)
react组件进阶(四)
文章目录1. 组件通讯介绍2. 组件的 props3. 组件通讯的三种方式3.1 父组件传递数据给子组件3.2 子组件传递数据给父组件3.3 兄弟组件4. Context5. props 深入5.1 children 属性5.2 props 校验5.3 props 的默认值6. 组件的生命周期6.1 组件的生命周期概述6.2 生命周期的三个阶段…...
![](https://img-blog.csdnimg.cn/img_convert/d9847aa9f47a456d5f8a6643cae112d9.jpeg)
阿维塔城区NCA智驾导航辅助,复杂路口,全面胜任
阿维塔11城区NCA智驾导航辅助将于3月在上海、深圳等城市分阶段开启体验,以看得清、判得准、控得稳的“智驾”,进一步巩固业界智能天花板的地位。智能驾驶里程碑,拨杆两下开启都市安适旅程作为AVATRANS智能领航系统的重要组成部分,…...
![](https://img-blog.csdnimg.cn/ab8f0f65939049ddbfcdaaf14bd8ae26.png)
[Pandas] div()函数
div()方法将DataFrame中的每个值除以指定的值,并返回一个计算处理后的Dataframe结果 DataFrame.div()函数其实是除法运算,表格中的每个数据都是被除数 导入数据 import pandas as pd df pd.DataFrame({"col1":[5, 3, None, 4], "col2…...
![](https://www.ngui.cc/images/no-images.jpg)
c++并发与多线程
c并发与多线程 子线程结束,主线程不能结束,否则会出错,和java不一样。 可以用join的方式让主线程等待子线程执行结束。 quickStart 线程相关头文件 #include <thread> 使用全局函数构造一个线程对象 #include <iostream> #…...
![](https://img-blog.csdnimg.cn/a90effcf11da4be4bd1d4c21deb5e42c.jpeg)
Vinylsulfone PEG Biotin,Biotin-PEG-VS,生物素聚乙二醇乙烯砜,VS基团容易与游离巯基发生反应
●中文名:乙烯砜PEG生物素,生物素聚乙二醇乙烯砜 ●英文名:Vinylsulfone PEG Biotin, VS-PEG-Biotin,Vinyl sulfone-PEG-Biotin,Biotins-PEG-sulfone Vinyl●产品理化指标: CAS号:N/A 分子量&am…...
![](https://img-blog.csdnimg.cn/d2d7272c83e1412cac95c3f8be0aca16.png)
论文学习——Tune-A-Video
Tune-A-Video: One-Shot Tuning of Image Diffusion Models for Text-to-Video Generation Abstract 本文提出了一种方法,站在巨人的肩膀上——在大规模图像数据集上pretrain并表现良好的 text to image 生成模型——加入新结构并进行微调,训练出一套 …...
![](https://img-blog.csdnimg.cn/f87b822287a7493fa7630d597745fcfe.png)
C++类与对象part1
目录 1.类的6个默认函数 2.构造函数(相当于init) 3.析构函数 (相当于destroy) 4.拷贝构造函数 赋值运算符重载 运算符重载 赋值运算符重载 引入: 你知道为什么cout可以自动识别类型吗? 其实cout是一…...
![](https://www.ngui.cc/images/no-images.jpg)
记一次抓取网页内容
已打码 // UserScript // name --------- // namespace http://tampermonkey.net/ // version 0.1 // description https://---------oups/{id}/topics?scopeall&count20&begin_time2022-09-01T00%3A00%3A00.000%2B0800&end_time2022-10-01T00%…...
![](https://img-blog.csdnimg.cn/img_convert/17654c2a7bbe24f235c038b6bc6c7755.png)
parasoft帮助史密斯医疗通过测试驱动开发提供安全、高质量的医疗设备
parasoft是一家专门提供软件测试解决方案的公司,Parasoft通过其经过市场验证的自动化软件测试工具集成套件,帮助企业持续交付高质量的软件。Parasoft的技术支持嵌入式、企业和物联网市场,通过将静态代码分析和单元测试、Web UI和API测试等所有…...
![](https://img-blog.csdnimg.cn/d6cbceb9cf564574bd0cad74cb047398.png)
SpringBoot整合Oauth2开放平台接口授权案例
<!-- SpringBoot整合Web组件 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId>&l…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux_创建用户
创建一个名为hello的用户,并指定/home/hello为根目录useradd -d /home/hello -m hello 设置密码 ,密码会输入两次,一次设置密码,一次确认密码,两次密码要输入的一样passwd hellouseradd的常用参数含义-d指定用户登入时的主目录&am…...
![](https://img-blog.csdnimg.cn/f25dec5be4e549f3b71b71626e2b2c1d.png)
RDD(弹性分布式数据集)总结
文章目录一、设计背景二、RDD概念三、RDD特性四、RDD之间的依赖关系五、阶段的划分六、RDD运行过程七、RDD的实现一、设计背景 1.某些应用场景中,不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入。如:迭代式算法…...
![](https://img-blog.csdnimg.cn/img_convert/c80dfe51f82e7901659629f3c6738331.png)
服务器版RstudioServer安装与配置详细教程
Docker部署Rstudio server 背景:如果您想在服务器上运行RstudioServer,可以按照如下方法进行操作,笔者测试时使用腾讯云服务器(系统centos7),需要在管理员权限下运行 Rstudio 官方提供了使用不同 R 版本的 …...
![](https://www.ngui.cc/images/no-images.jpg)
如何在Java中将一个列表拆分为多个较小的列表
在Java中,有多种方法可以将一个列表拆分为多个较小的列表。在本文中,我们将介绍三种不同的方法来实现这一目标。 方法一:使用List.subList()方法 List接口提供了一个subList()方法,它可以用来获取列表中的一部分元素。我们可以使…...
![](https://img-blog.csdnimg.cn/12d3c32a656342909bf75cbb47ae0d8c.png)
TryHackMe-Inferno(boot2root)
Inferno 现实生活中的机器CTF。该机器被设计为现实生活(也许不是?),非常适合刚开始渗透测试的新手 “在我们人生旅程的中途,我发现自己身处一片黑暗的森林中,因为直截了当的道路已经迷失了。我啊…...
![](https://www.ngui.cc/images/no-images.jpg)
微信原生开发中 JSON配置文件的作用 小程序中有几种JSON配制文件
关于json json是一种数据格式,在实际开发中,JSON总是以配制文件的形式出现,小程序与不例外,可对项目进行不同级别的配制。Q:小程序中有几种配制文件A:小程序中有四种配制文件分别是:project.config.json si…...
![](https://www.ngui.cc/images/no-images.jpg)
【python】为什么使用python Django开发网站这么火?
关注“测试开发自动化” 弓中皓,获取更多学习内容) Django 是一个基于 Python 的 Web 开发框架,它提供了许多工具和功能,使开发者可以更快地构建 Web 应用程序。以下是 Django 开发中的一些重要知识点: MTV 模式&#…...
![](https://img-blog.csdnimg.cn/3b8eac671492422a956eba00f1006f91.png)
Java设计模式(五)—— 责任链模式
责任链模式定义如下:使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。 适合使用责任链模式的情景如下: 有许多对…...
![](https://www.ngui.cc/images/no-images.jpg)
VMLogin:虚拟浏览器提供的那些亮眼的功能
像VMLogin这样的虚拟浏览器具有多种功能,如安全的浏览环境、可定制的设置、跨平台的兼容性、更快的浏览速度、广告拦截等等。 虚拟浏览器的不同功能可以为您做什么? 使用虚拟浏览器是浏览互联网和完成其他任务的安全方式,没有风险。您可以在…...
![](https://www.ngui.cc/images/no-images.jpg)
第一个错误的版本
题目 你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。 假设你有 n 个版本 [1, 2, …, n],你想找出…...
![](https://img-blog.csdnimg.cn/623115940ca04093afd6b959a57fcadd.png)
2023爱分析·AIGC市场厂商评估报告:拓尔思
AIGC市场定义 市场定义: AIGC,指利用自然语言处理技术(NLP)、深度神经网络技术(DNN)等人工智能技术,基于与人类交互所确定的主题,由AI算法模型完全自主、自动生成内容,…...
![](https://www.ngui.cc/images/no-images.jpg)
MobTech|场景唤醒的实现
什么是场景唤醒? 场景唤醒是moblink的一项核心功能,可以实现从打开的Web页面,一键唤醒App,并恢复对应的场景。 场景是指用户在App内的某个特定页面或状态,比如商品详情页、活动页、个人主页等。每个场景都有一个唯一…...
![](https://img-blog.csdnimg.cn/5eda415957624e09a51921216ee7bd47.jpeg)
不在路由器上做端口映射,如何访问局域网内网站
假设现在外网有一台ADSL直接拨号上网的电脑,所获得的是公网IP。然后它想访问局域网内的电脑上面的网站,那么就需要在路由器上做端口映射。在路由器上做端口映射的具体规则是:将所有发向自己端口的数据,都转发到内网的计算机。 访…...
![](https://img-blog.csdnimg.cn/img_convert/8ca91fed20fffd0a9ce41456b803c1ef.png)
ChatGPT 辅助科研写作
前言 总结一些在科研写作中 ChatGPT 的功能,以助力提升科研写作的效率。 文章目录前言一、ChatGPT 简介1. ChatGPT 普通版与 Plus 版的区别1)普通账号2)Plus账号二、New Bing 简介1. 快速通过申请三、辅助学术写作1. 改写论文表述2. 语言润色…...
![](https://img-blog.csdnimg.cn/img_convert/1bd45ed34baf757d07012e09a5d40142.png)
MySQL最大建议行数 2000w,靠谱吗?
本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~ Github地址 1 背景 作为在后端圈开车的多年…...
![](https://img-blog.csdnimg.cn/80840d0c54704fcd951104a452692bee.png)
【Tomcat 学习】
Tomcat 学习 笔记记录一、Tomcat1. Tomcat目录2. Tomcat启动3. Tomcat部署项目4. 解决Tomcat启动乱码问题5. JavaWeb项目创建部署6. 打war包发布项目7. Tomcat配置文件8. Tomcat配置虚拟目录(不用在webapps目录下)9. Tomcat配置虚拟主机10. 修改web项目默认加载资源路径一、Tom…...
![](/images/no-images.jpg)
怎么介绍自己做的静态网站/关键词排名seo
本文主要是介绍使用prerender-spa-plugin插件在针对前端代码进行预渲染。 预渲染(SSG)和服务端(SSR)渲染有一定的区别,大家想要了解的话可以看:https://segmentfault.com/a/1190000023469150。 背景 因为…...
![](https://img-blog.csdnimg.cn/img_convert/fe1018dd36dc6d1473a19782cc09b364.png)
百度抓取网站图片/seo快速提升排名
一年前,在公司大佬的指点之下,我开始写系统级重构工具 Coca (https://github.com/phodal/coca) 。哦,不,不对,是刚开始学习 Golang,因为我的第一次提交是从一个 Go 的 hello, world 写起的。commit a685d69…...
![](/images/no-images.jpg)
怎样做班级网站/搜索引擎优化的方法有哪些
ie6下不支持PNG 24 的透明度; 所以保存为PNG 8最为靠谱。杂边选择“无”; PS我玩的还可以。大家有问题可以问我。 网页制作时记得把PS首选项的单位改成像素; 今天试了一下切图插件:cutterman 这个插件有个BUG 会自动覆盖重名文件。࿰…...
![](https://images2015.cnblogs.com/blog/7841/201603/7841-20160302112933111-249108144.png)
制作一个视频网站/冯站长之家
**本文针对的是启明星系统的数据库备份与还原,这同样适合其他数据库。 数据库自动备份工具(最后更新时间2015.7.24):http://files.cnblogs.com/files/mqingqing123/dbback_release.rar (1)数据库如何备份&a…...
![](/images/no-images.jpg)
登陆国外的网站要这么做/色盲测试图动物
当你学完了这个部分,你将逐渐变成一个很牛的程序员,对计算机系统以及它们对程序的影响有很成熟的理解。 第10章 系统级I/O 第11章 网络编程 第12章 并发编程转载于:https://www.cnblogs.com/rayhill/archive/2012/05/31/2529046.html...
![](https://img-blog.csdnimg.cn/img_convert/a8be8c0e34f90ff2a7ad9f1c13e548c4.png)
wordpress搬站流程/seo网站内部优化方案
我们对内存条是“情有独钟”,电脑卡了我们会直接加装内存条,游戏运行不流畅也会直接加装内存条,总之在很多人心中认为电脑内存条 就像电脑的“救世主”,那么,内存条在电脑中的作用究竟有多大呢?电脑内存条的…...