• Java skill - 动态指定feign的访问地址


    场景

    在有下沉节点项目的前提下,使用feign调用内部服务的时候,在redis查询需要调用的内部服务的elb地址并调用

    编码

    新增feign传参类

    @Data
    public class TestDto {
        private String id;
    }
    
    • 1
    • 2
    • 3
    • 4

    新增调用内部服务的feign接口

    @FeignClient(name = "test", url = "http://localhost:1234", configuration = FeignConfig.class)
    public interface TestClient {
        @PostMapping(value = "/v1/test/get_name")
        Object getNameById(@RequestParam("id") String id, @RequestBody TestDto body);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    feign配置类逻辑修改

    @Configuration
    public class FeignConfig {
    
        @Bean
        public RequestInterceptor headerInterceptor() {
            return new RequestInterceptor() {
                @Override
                public void apply(RequestTemplate requestTemplate) {
                	// 只有请求url的前缀是【/v1/test/】才需要指定地址
                    if(requestTemplate.url().startsWith("/v1/test/")){
                    	// 初始化地址信息
                    	String url = "";
                    	// 获取@RequestBody 中的参数
                        Object parse = JSONObject.parse(new String(requestTemplate.body()));
                        Map<String,String> info = (Map<String, String>) parse;
                        String id= info.get("id");
                        if(StringUtils.isBlank(id)){
                            // 如果body中没有id,去@RequestParam 查询
                            Map<String, Collection<String>> queries = requestTemplate.queries();
                            //================ 业务逻辑 begin
                                                 .
                                                 .
                                                 .
                                                 .
                            //================ 业务逻辑 end
                            // 拿到要访问的地址之后,配置RequestTemplate.target,这样就可以实现feign指定地址调用了
                            requestTemplate.target(url);
                        }
                    }
    
                }
            };
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    大坑

    1. 如果feign接口中@FeignClient注解的name值是nacos注册的服务名,那要实现动态指定访问地址的话,分以下两种情况:
    1. 指定的地址在nacos的服务名中不存在,url参数一定要赋初始值,否则,就会发现requestTemplate.target 就失效了,实质是在debug日志级别会打印负载均衡失败的日志。
    2. 指定的地址在nacos的服务名中存在,url参数没有硬性要求。
    3. 还是建议大家,动态指定feign的访问地址,url参数最好赋一个初始值
    1. requestTemplate.target(url)中的参数url内容一定是完整的地址(如:http://127.0.0.1:8080)
    2. 不要在这个apply()方法中使用ThreadLocal这种获取当前线程中的相关信息的类,因为feign是线程池管理的,主线程进入到feign之后,就进入到了一个子线程,在feign中的所有操作都是在一个子线程中的操作,所以使用ThreadLocal这种类时会出问题。

    如果必须要在feign中获取到此次请求中的一个全局参数的话,可以考虑一下使用MDC(log4j和logback等日志框架提供的一种机制),ThreadLocal是面向单个线程的,MDC是面向单个请求的(跨线程),使用MDC就不用考虑多个线程的问题了,但一定要注意请求结束之后要清除

  • 相关阅读:
    springboot基于Android的洗衣店预约APP毕业设计源码260839
    CentOS7设置添加shell脚本开机自动启动服务
    【方法封装】时间格式化输出,获取请求设备和IP
    手动添加扩展到composer中
    java-net-php-python-ssm二手商品交易平台的设计与实现(2)计算机毕业设计程序
    【以图会意】文件系统从外存到内存到用户空间
    “亚马逊依赖”之下,傲基科技的品牌势能如何提升?
    [R] How to communicate with your data? - ggplot2
    使用 【jacoco】对基于 SpringBoot 和 Dubbo RPC 的项目生成测试覆盖率报告:实践+原理
    winform 获取指定的form
  • 原文地址:https://blog.csdn.net/m0_63164811/article/details/133310923