OpenFeign返回参数统一处理

自定义解码器

package com.itheima.feign;import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.exception.BusinessException;
import feign.Response;
import feign.Util;
import feign.codec.Decoder;
import org.springframework.core.ResolvableType;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;/*** @author 阿呆* @desciption:* @since 2023/4/23 23:09*/
public abstract class AbstractCustomDecoder <T> implements Decoder{protected final Class<T> targetClazz;protected Set<Class> clazzSet;protected ObjectMapper objectMapper;protected AbstractCustomDecoder(ObjectMapper objectMapper) {this.targetClazz = retrieveAnnotationType();this.objectMapper = objectMapper;this.clazzSet = new HashSet<>();this.clazzSet.add(this.targetClazz);this.fillTargetClazz(this.clazzSet);}protected abstract <D> Supplier<D> getData(T obj);protected abstract <C> Supplier<C> getCode(T obj);protected abstract <M> Supplier<M> getMes(T obj);protected abstract boolean isSuccess(T obj);protected abstract void fillTargetClazz(Set<Class> clazzSet);@Overridepublic Object decode(Response response, Type type) throws IOException {return customDecoder(response, type);}/*** 检索泛型对应的实际类型* @return*/private Class<T> retrieveAnnotationType(){Type type = getClass().getGenericSuperclass();if (type instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) type;for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) {if (actualTypeArgument instanceof Class) {return (Class) actualTypeArgument;}}}return null;}protected Object customDecoder(Response response, Type type) throws IOException {String body = Util.toString(response.body().asReader(StandardCharsets.UTF_8));Class<?> clazz = ResolvableType.forType(type).getRawClass();if (this.clazzSet.contains(clazz)){return this.objectMapper.readValue(body,clazz);}try{return this.objectMapper.readValue(body,clazz);}catch (Exception e){JavaType paramterType = this.objectMapper.getTypeFactory().constructType(type);JavaType resultType = this.objectMapper.getTypeFactory().constructParametricType(this.targetClazz, paramterType);T data = (T)this.objectMapper.readValue(body,resultType);if (isSuccess(data)){return getData(data).get();}throw new BusinessException(Integer.valueOf(getCode(data).get().toString()),getMes(data).get().toString());}}}package com.itheima.feign;import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.Result;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Set;
import java.util.function.Supplier;/*** @author 阿呆* @desciption: @Configuration 加入 该注解后 全局有效 , 替换 SpringDecoder 没有 局部引用也会生效* @since 2023/4/23 23:27*/public class CustomDecoderConfig extends AbstractCustomDecoder<FeignResponse> {protected CustomDecoderConfig(ObjectMapper objectMapper) {super(objectMapper);}@Overrideprotected Supplier getData(FeignResponse obj) {return obj::getData;}@Overrideprotected Supplier<String> getCode(FeignResponse obj) {return obj::getCode;}@Overrideprotected Supplier<String> getMes(FeignResponse obj) {return obj::getMsg;}@Overrideprotected boolean isSuccess(FeignResponse obj) {return obj.isSuccess();}@Overrideprotected void fillTargetClazz(Set<Class> clazzSet) {clazzSet.add(Result.class);}}package com.itheima.feign;import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.Result;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Set;
import java.util.function.Supplier;/*** @author 阿呆* @desciption: @Configuration 加入 该注解后 全局有效 , 替换 SpringDecoder 没有 局部引用也会生效* @since 2023/4/23 23:27*/
@Configuration
public class FeignClientCustomDecoderConfig {@Beanpublic Decoder decoder(ObjectMapper objectMapper) {// 方法入口:feign.InvocationContext , 默认执行链: ResponseEntityDecoder、OptionalDecoder、SpringDecoderreturn new ResponseEntityDecoder(new OptionalDecoder(new CustomDecoderConfig(objectMapper)));}
}

局部、全价有效

全价有效,FeignClientCustomDecoderConfig需要配置@Configuration 进行标记,局部有效则去掉。没有配置的默认使用SpringDecoder 进行解码

package com.itheima.client;import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.User;
import com.itheima.feign.FeignClientCustomDecoderConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;/*** 局部有效,FeignClientCustomDecoderConfig 不要注入bean , 不然会替换掉默认的SpringDecode 解码器* value 服务名称   contextId  bean名称 */
@FeignClient(value = "nacos-client-feign", contextId = "nacosClientFeignWrapper", configuration = FeignClientCustomDecoderConfig.class)
public interface NacosClientFeignWrapper {@RequestMapping("/findWrapUsers")List<User> findWrapUsers(@RequestBody User user);@RequestMapping("/updateWrapperUser")User updateWrapperUser(@RequestBody User user);@RequestMapping("/findWrapUsers")FeignResponse<List<User>> findWrapUsers2(@RequestBody User user);@RequestMapping("/updateWrapperUser")FeignResponse<User> updateWrapperUser2(@RequestBody User user);@RequestMapping("/handlerError")FeignResponse<User> handlerError(@RequestBody User user);}

Feign接口编写,继承实现方式

package com.itheima.client;import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.User;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;# 共有类/*** @author 阿呆* @desciption:* @since 2024/10/26 20:26*/
public interface UserWebApi {@RequestMapping("/user/findWrapUsers")List<User> findWrapUsers(@RequestBody User user);@RequestMapping("/user/updateWrapperUser")User updateWrapperUser(@RequestBody User user);@RequestMapping("/user/findWrapUsers")FeignResponse<List<User>> findWrapUsers2(@RequestBody User user);@RequestMapping("/user/updateWrapperUser")FeignResponse<User> updateWrapperUser2(@RequestBody User user);@RequestMapping("/user/handlerError")FeignResponse<User> handlerError(@RequestBody User user);}# 调用方 实现接口package com.itheima.client;import com.itheima.feign.FeignClientCustomDecoderConfig;
import org.springframework.cloud.openfeign.FeignClient;/*** @author 阿呆* @desciption:* @since 2024/10/26 20:27*/
@FeignClient(value = "nacos-client-feign", contextId = "nacosClientFeignWrapper", configuration = FeignClientCustomDecoderConfig.class)
public interface UserFeignApi extends UserWebApi{}# 提供方服务器接口实现package com.itheima.client;import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.User;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @author 阿呆* @desciption:* @since 2024/10/26 20:28*/
@RestController
public class UserController implements UserWebApi{@Overridepublic List<User> findWrapUsers(User user) {return null;}@Overridepublic User updateWrapperUser(User user) {return null;}@Overridepublic FeignResponse<List<User>> findWrapUsers2(User user) {return null;}@Overridepublic FeignResponse<User> updateWrapperUser2(User user) {return null;}@Overridepublic FeignResponse<User> handlerError(User user) {return null;}
}

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

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

相关文章

2024.7最新子比主题zibll7.9.2开心版源码+授权教程

授权教程&#xff1a; 1.进入宝塔搭建一个站点 绑定 api.zibll.com 域名 并上传 index.php 文件 2.设置伪静态 3.开启SSL证书&#xff0c;找一个能用的域名证书&#xff0c;将密钥(KEY)和证书(PEM格式)复制进去即可 4.在宝塔文件地址栏中输入 /etc 找到 hosts文件并打开&a…

【Docker】docker | 部署nginx

一、概述 记录下nginx的部署流程&#xff1b;将conf配置文件映射到宿主机 前提依赖&#xff1a;自行准备nginx的镜像包 二、步骤 1、运行、无映射 docker run --name nginx -p 80:80 -d nginx:1.18.0-alpine 80&#xff1a;80&#xff0c;前面是宿主机端口&#xff1b;如果冲…

uniapp:上拉加载更多、下拉刷新、页面滚动到指定位置

提醒 本文实例是使用uniapp进行开发演示的。 一、需求场景 在开发商品&#xff08;SKU&#xff09;列表页面时&#xff0c;通常有三个需求&#xff1a; 页面下拉刷新&#xff0c;第一页展示最新数据&#xff1b;上拉加载更多数据&#xff1b;列表页面可以滚动到指定位置&#x…

Liunx权限概念及权限管理

目录 一&#xff1a;shell命令以及运行原理 二&#xff1a;Linux权限的概念 三&#xff1a;Linux的权限管理 3.1文件访问者的分类 3.2文件类型和访问权限&#xff08;事物属性&#xff09; 3.3文件权限的表达方式&#xff1a; 3.4文件访问权限的相关设置方法 四&…

前沿技术与未来发展第一节:C++与机器学习

第六章&#xff1a;前沿技术与未来发展 第一节&#xff1a;C与机器学习 1. C在机器学习中的应用场景 C在机器学习中的应用优势主要体现在高效的内存管理、强大的计算能力和接近底层硬件的灵活性等方面。以下是 C 在机器学习领域的几个主要应用场景&#xff1a; 1.1 深度学习…

Vue3 学习笔记(七)Vue3 语法-计算属性 computed详解

#1024程序员节|征文# 1、计算属性 computed 在 Vue.js 中&#xff0c;计算属性&#xff08;computed properties&#xff09;是一种特殊的响应式属性&#xff0c;它们根据依赖的响应式数据自动更新。计算属性非常适合用于当你需要根据现有数据派生出一些状态时。 (1)、基本用法…

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt+7

IntelliJ IDEA 查看类class的结构Structure轮廓outline窗口, 快捷键是Alt7 idea的结构Structure窗口相当于Eclipse的outline 快捷键是: Alt7 或者点击左上角主菜单面包屑,打开主菜单 然后菜单找到-视图&#xff08;View&#xff09;→ 工具窗口&#xff08;Tool Windows&…

基于大数据 Python+Vue 酒店爬取可视化系统(源码+LW+部署讲解+数据库+ppt)

&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 会持续一直更新下去 有问必答 一键收藏关注不迷路 源码获取&#xff1a;https://pan.baidu.com/s/1aRpOv3f2sdtVYOogQjb8jg?pwdjf1d 提取码: jf1d &#…

FineReport 分栏报表

将报表中的数据根据所需要的展示的样式将数据进行分栏展示列分栏 报表中数据是横向扩展的,超过一页的数据会显示在下一页,而每页下面会有很大的一片空白区域,不美观且浪费纸张。希望在一页中第一行扩展满后自动到下一行继续扩展 1、新建数据集 SELECT * FROM 公司股票2、内…

前端代码分享--爱心

给对象写的&#xff0c;顺便源码给大家分享一下 就是简单的htmlcssjs&#xff0c;不复杂 xin1.html <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <title>写你自己的</title> <lin…

深入解析机器学习算法

深入解析机器学习算法 机器学习已经成为当今技术进步的核心推动力量&#xff0c;推动了众多行业的创新。其背后依赖的是各种各样的算法&#xff0c;帮助计算机通过从数据中学习来完成任务。这篇文章将对常见的几类机器学习算法进行深入探讨&#xff0c;帮助你理解其工作原理、…

攻防世界的新手web题解

攻防世界引导模式 1、disabled_button 好&#xff0c;给了一个按钮&#xff0c;第一道题目就不会做 看的wp<input disabled class"btn btn-default" style"height:50px;width:200px;" type"submit" value"flag" name"auth&q…

qt 滚动条 美化

qt QScrollBar 滚动条分为竖直与水平滚动条&#xff0c;两者设置上类似&#xff0c;但也有一些不同&#xff0c;下面主要讲述美化及注意事项。 一、竖直滚动条 竖直滚动条分为7个部分&#xff1a; sub-line、 up-arrow 、sub-page、 hanle、 add-line、 dow-arrow、 add-pag…

猴子请来的补丁——Python中的Monkey Patching

猴子补丁&#xff08;Monkey Patching&#xff09;在Python中是一种允许在运行时修改对象行为的技术。这种技术可以在不直接修改原始源代码的情况下&#xff0c;动态地改变或扩展程序的行为。 猴子补丁的原理 猴子补丁的核心原理是利用Python的动态特性&#xff0c;即在运行时…

研究生论文学习记录

文献检索 检索论文的网站 知网&#xff1a;找论文&#xff0c;寻找创新点paperswithcode &#xff1a;这个网站可以直接找到源代码 直接再谷歌学术搜索 格式&#xff1a;”期刊名称“ 关键词 在谷歌学术搜索特定期刊的关键词相关论文&#xff0c;可以使用以下几种方法&#…

Java并发学习总结:原子操作类

本文是学习尚硅谷周阳老师《JUC并发编程》的总结&#xff08;文末有链接&#xff09;。 基本类型原子类 AtomicIntegerAtomicLongAtomicBoolean AtomicInteger 的方法 getAndIncrement 和 incrementAndGet 的区别&#xff1a; 两个方法都能实现对当前值加 1 &#xff0c; 但…

web服务实验

http实验 先创建需要访问的web页面文件index.html 编辑vim /etc/nginx/conf.d/testip.conf 测试通过域名访问需要编辑/etc/hosts 如果通过windows的浏览器访问需要编辑下面的文件通过一管理员身份打开的记事本编辑 C:\Windows\System32\drivers\etc下的hosts文件 192.168.1…

软考:GPU算力,AI芯片

算力 FLOPS&#xff08;每秒浮点操作&#xff09; NVIDIA 去年就有超过 1 exa 的新闻&#xff0c;所以这个数值是越大越好。 AI芯片的技术架构类型 GPU&#xff1a;图形处理单元&#xff0c;擅长并行处理&#xff0c;适用于深度学习等AI计算密集型任务。FPGA&#xff1a;现…

OpenStack将运行的系统导出 QCOW2 镜像并导入阿里云

项目背景 OpenStack&#xff0c;作为一个开源的云计算平台&#xff0c;经常被用于构建私有云和公有云服务。然而&#xff0c;随着业务的发展和扩展&#xff0c;企业可能会面临将在OpenStack上运行的虚拟机迁移到其他云服务供应商的需求 需求 因为运营团队在本地机房有一台 O…

Netty-TCP服务端粘包、拆包问题(两种格式)

前言 最近公司搞了个小业务&#xff0c;需要使用TCP协议&#xff0c;我这边负责服务端。客户端是某个设备&#xff0c;客户端传参格式、包头包尾等都是固定的&#xff0c;不可改变&#xff0c;而且还有个蓝牙传感器&#xff0c;透传数据到这个设备&#xff0c;然后通过这个设备…