【JAVA实战】@FeignClient注解类通用请求封装

背景

最近在编写多个系统数据集成过程中,经常会使用到@FeignClient注解标记一个类,类里面编写很多请求方法,如果第三方系统有非常多的URL请求,每个方法对应一个URL请求,那么这个类就会非常的庞大,是否有一种方法能够动态的设置URL,只需要编写一个或者两三个通用的方法解决这个问题,笔者最近就在项目中亲测过以下封装方式。

最初的方式

假如有一个TestFeignClient,如下所示:

@FeignClient(name = "test", url = "http://localhost", contextId = "testFeignClient")
public interface TestFeignClient {

    /**
     * 获取产品列表数据
     *
     * @param map
     * @return
     */
    @PostMapping(value = "/api/v1/getProductList")
    String getProductList(@RequestBody Map<String, Object> map);


    /**
     * 获取订单列表数据
     *
     * @param map
     * @return
     */
    @PostMapping(value = "/api/v1/getOrderList")
    String getOrderList(@RequestBody Map<String, Object> map);
}

以上,如果这个TestFeignClient方法特别多,这个类会非常庞大

改进的方式

将TestFeignClient中两个方法统一封装成一个doPost方法,只需要传递URL请求参数到Map集合中即可通过拦截器自动替换,从而做到了通用,如下:

@FeignClient(name = "test", url = "http://localhost", contextId = "testFeignClient", configuration = TestConfiguration.class)
public interface TestCommonFeignClient {

    /**
     * POST通用请求
     *
     * @param map
     * @return
     */
    @PostMapping(value = "templateReqUrlKey")
    String doPost( @RequestBody Map<String, Object> map);
}

关键类在于TestConfiguration拦截并在请求之前替换了对应的真实URL,大致代码如下:

@Slf4j
@AllArgsConstructor
public class TestConfiguration {

    public final ObjectMapper objectMapper;

    @Bean
    public Retryer retryer() {
        return new TestRetryer();
    }

    /**
     * 配置请求拦截器
     *
     * @return
     */
    @Bean
    public RequestInterceptor testRequestInterceptor() {
        return template -> {
            template.header("Content-Type", "application/json");
            if (template.method().equals(Request.HttpMethod.POST.name())) {
                String body = new String(template.body(), StandardCharsets.UTF_8);
                Map<String, Object> bodyMap = new HashMap<>();
                try {
                    bodyMap = objectMapper.readValue(body,
                            new TypeReference<Map<String, Object>>() {
                            });
                } catch (JsonProcessingException e) {
                    log.error("json解析出错,", e);
                }
                String srcUrl = template.url();
                String templateUrl = "";
                if (bodyMap.containsKey("templateReqUrlKey") && srcUrl.contains("templateReqUrlKey")) {
                    templateUrl = bodyMap.get("templateReqUrlKey").toString();
                    template.uri(templateUrl);
                }
                bodyMap.remove("templateReqUrlKey");
                template.body(JSONUtil.toJsonStr(bodyMap));
            }
        };
    }


    @Bean
    public Decoder decoder() {
        return (response, type) -> {
            String resultStr = IOUtils.toString(response.body().asInputStream(), String.valueOf(StandardCharsets.UTF_8));
            JSONObject obj = JSONUtil.parseObj(resultStr);
            String code = obj.get("code").toString();
            if (Objects.equals("200", code)) {
                // TODO 
                throw new RetryableException(500, obj.getStr("msg"), response.request().httpMethod(), null, response.request());
            }
            return resultStr;
        };
    }

}

以上拦截器testRequestInterceptor中替换了原始templateReqUrlKey,从而实现了客户端设置真实url到bodyMap中,请求之前替换templateReqUrlKey,这样就比较灵活的应对第三方系统数据集成。

最后

以上提到的bodyMap可设置真实的URL地址,笔者将这个真实URL地址做成了一个config配置表存储,每次获取对应接口的URL即可,同时笔者将bodyMap中整个URL请求的json数据都可以做成配置,完全做到了只需要修改数据库配置表,即可完成接口数据集成,实现了动态控制请求,有兴趣的可尝试。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

03_Redis基本操作

1.Redis查询命令 1.1 官网命查询命令 为了便于学习Redis,官方将其用于操作不同数据类型的命令进行了分类整理。你可以通过访问Redis官方网站上的命令参考页面https://redis.io/commands来查阅这些分组的命令,这有助于更系统地理解和使用Redis的各项功能。 1.2 HELP查询命令…

深度解读微软Speech服务:让语音识别走进现实

大家好&#xff0c;今天我们来探讨一个激动人心的技术话题&#xff1a;微软的语音识别服务如何为我们提供强大的语音识别解决方案&#xff0c;特别是在电话录音中识别出不同的说话人。 场景描绘 想象一下&#xff0c;你有一段电话录音&#xff0c;并需要将其中的多个说话人区分…

mapbox基础,expressions表达式汇总

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言二、🍀Expressions简介2.1 expressions 操作符2.1.1 Data expressions2.1.2 Camera expressions2.2 Expressi…

HTML中link的用法

一点寒芒先到&#xff0c;随后&#xff0c;抢出如龙&#xff01; 对于本人而言&#xff0c;这篇笔记内容有些扩展了&#xff0c;有些还未学到的也用上了&#xff0c;但是大概可以使用的明白&#xff0c;坚持下去&#xff0c;相信一定可以建设一个稳固的根基。 该文章为个人成…

宝塔面板 申请证书后 仍然提示不安全

证书显示有效&#xff0c;但是网站显示不安全 导致的原因是引入静态文件使用的是HTTP&#xff0c;查看方法为F12打开console控制台 可以看到静态文件全部都是HTTP 网站采用wordpress搭建&#xff0c;基于问题解决&#xff0c;其他方式搭建也是一样&#xff0c;处理掉所有的H…

Maven 中 scope=provided 和 optional=true 的区别

先说效果&#xff0c;maven依赖声明中加了<scope>provided</scope>&#xff0c;或者加了<optional>true</optional>&#xff0c;从效果上看是一样的&#xff0c;都会中断依赖传递&#xff0c;观察下图&#xff1a; 图中&#xff0c;项目B分别依赖了C和…

Linux标准IOday4

1:思维导图2: 创建2个子进程 父进程负责: 向文件中写入数据 2个子进程负责: 从文件中读取数据 要求: 一定保证1号子进程先读取&#xff0c;2号子进程后读取 使用文件IO去实现 #include <stdio.h>#include <string.h>#include <un…

Spring Boot教程之五十五:Spring Boot Kafka 消费者示例

Spring Boot Kafka 消费者示例 Spring Boot 是 Java 编程语言中最流行和使用最多的框架之一。它是一个基于微服务的框架&#xff0c;使用 Spring Boot 制作生产就绪的应用程序只需很少的时间。Spring Boot 可以轻松创建独立的、生产级的基于 Spring 的应用程序&#xff0c;您可…

ColorGATE 23系列的RIP软件

ColorGATE 23系列的RIP软件。ColorGATE是全球领先的用于无化学胶片生产的RIP软件&#xff0c;以下是对其特点和功能的介绍&#xff1a; 应用领域 适用于柔版、胶版和丝网印刷等领域&#xff0c;利用喷墨打印机进行无化学胶片生产&#xff0c;可应用于高端品质的印刷。 核心技…

Type-C双屏显示器方案

在数字化时代&#xff0c;高效的信息处理和视觉体验已成为我们日常生活和工作的关键需求。随着科技的进步&#xff0c;一款结合了便携性和高效视觉输出的设备——双屏便携屏&#xff0c;逐渐崭露头角&#xff0c;成为追求高效工作和娱乐体验人群的新宠。本文将深入探讨双屏便携…

51单片机 DS18B20温度储传感器

DS18B20温度传感器 64-BITROM&#xff1a;作为器件地址&#xff0c;用于总线通信的寻址&#xff0c;是唯一的&#xff0c;不可更改 SCRATCHPAD&#xff08;暂存器&#xff09;&#xff1a;用于总线的数据交互 EEPROM&#xff1a;用于保存温度触发阈值和配置参数 暂存器 单总线…

对话新晋 Apache SeaTunnel Committer:张圣航的开源之路与技术洞察

近日&#xff0c;张圣航被推选为 Apache SeaTunnel 的 Committer成员。带着对技术的热情和社区的责任&#xff0c;他将如何跟随 Apache SeaTunnel 社区迈向新的高度&#xff1f;让我们一起来聆听他的故事。 自我介绍 请您简单介绍一下自己&#xff0c;包括职业背景、当前的工作…

Linux渗透实战之Hackademic: RTB1靶场提权

0x1 前言 一、浅谈 哈喽师傅们&#xff0c;这次又到了给师傅们分享文章的时候了&#xff0c;这篇文章呢主要是给师傅们以vulnhub中的Hackademic: RTB1靶场&#xff0c;开始使用nmap进行相关渗透测试的操作&#xff0c;端口、目录扫描&#xff0c;得到一个静态的html页面&…

SpringBoot-Day1

1.Springboot入门 创建Maven工程 导入spring-boot-stater-web起步依赖 编写Controller 提供启动类 2.yml配置信息书写与获取 书写 # 发件人信息 email:user: 172349823457qq.comcode: sajdajlwhjfgfkllwhost: smtp.qq.comauth: true ​ # 学生爱好 hobbies:- 打篮球- 踢…

基于扩频解扩+汉明编译码+交织的lora通信系统matlab性能仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…

针对服务器磁盘爆满,MySql数据库始终无法启动,怎么解决

&#xff08;点击即可进入聊天助手&#xff09; 很多站长在运营网站的过程当中都会遇到一个问题,就是网站突然无法打开,数据一直无法启动 无论是强制重启还是,删除网站内的所有应用,数据库一直无法启动 这个时候,就需要常见的运维手段了,需要对服务器后台各个资源,进行逐一排查…

LeetCode1170 比较字符串最小字母出现频次

字符串算法探秘&#xff1a;最小字母频次统计与比较问题剖析 在编程的世界里&#xff0c;字符串处理问题犹如繁星般繁多且各具特色。今天&#xff0c;我们聚焦于一道饶有趣味的题目&#xff0c;它涉及到对字符串中最小字母出现频次的统计以及基于此的比较操作。这道题不仅考验…

Kafka 分区管理

分区是主题的子集&#xff0c;每个主题可以被分割成多个分区&#xff0c;一个分区有一个主副本&#xff08;Leader&#xff09;及一个或多个从&#xff08;Follower&#xff09;副本。分区允许将数据分布在多个broker上&#xff0c;这样可以提高数据的处理能力、并行性及可靠性…

xcrun: error: invalid active developer path 解决

在拉取 github 代码时&#xff0c;提示如下报错&#xff1a; xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun 原因是&#xff1a;这是由于 Xcode command line t…

2025华数杯国际赛A题完整论文讲解(含每一问python代码+数据+可视化图)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了2025“华数杯”国际大学生数学建模竞赛A题Can He Swim Faster的完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文…