Feign动态定义调用serverName与path
方案一(DynamicProcessFeign)
1. 定义FeignClient工厂
@Component
public class DynamicProcessFeign<T> {
    /**
     * 缓存feignClient,提高客户端性能
     */
    private static Map<String, Object> processMap = new HashMap<>();
    private final FeignClientBuilder feignClientBuilder;
    public DynamicProcessFeign(@Autowired ApplicationContext appContext) {
        this.feignClientBuilder = new FeignClientBuilder(appContext);
    }
    public T getFeignClient(final Class<T> type, String serviceName, String path) {
        String key = serviceName + path;
        Object api = processMap.get(key);
        if (api != null) {
            return (T) api;
        }
        synchronized (DynamicProcessFeign.class) {
            api = processMap.get(key);
            if (api != null) {
                return (T) api;
            }
            api = this.feignClientBuilder.forType(type, serviceName).path(path).build();
            processMap.put(key, api);
        }
        return (T) api;
    }
}
2. 定义测试接口
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
    @PostMapping(value = "/test")
    public AjaxResult test(@RequestBody JSONObject object) {
        return AjaxResult.success(object);
    }
}
3. 提供业务feignClient,并定义服务声明接口
@FeignClient(name = "TestClient", contextId = "TestClient")
public interface TestClient {
    @PostMapping(value = "")
    AjaxResult test01(@RequestBody JSONObject object);
}
4. 动态调用
@Slf4j
@RestController
@RequestMapping("/test")
public class TestFeignController {
    @Autowired
    private DynamicProcessFeign dynamicProcessFeign;
    @PostMapping(value = "/test01")
    public AjaxResult test01(@RequestBody JSONObject object) {
        //微服务名称:shine-test-feign,请求路径/test/test
        TestClient testClient = dynamicProcessFeign.getFeignClient(TestClient.class, "shine-test-feign", "/test/test");
        AjaxResult result = testClient.test(object);
        log.info("result:{}", result);
        return result;
    }
}
方案二(FeignInterceptorConfig)
1. 对feignClient中API的URL中定义一个特殊的变量标记
@FeignClient(name = "TestClient", contextId = "TestClient")
public interface TestClient {
    @GetMapping("//$SERVER-NAME//test/test")
    public String test();
}
2. 定义FeignInterceptorConfig
@Data
@Configuration
@ConfigurationProperties(prefix = "feign-interceptor-config")
public class FeignInterceptorConfig {
    
    private Map<String, String> serverMap = new HashMap<>();
    @Bean
    public RequestInterceptor cloudContextInterceptor() {
        return template -> {
            replaceKey(template);
            replaceSlash(template);
        };
    }
    private void replaceKey(RequestTemplate template) {
        String url = template.url();
        for (Map.Entry<String, String> entry : serverMap.entrySet()) {
            String key = entry.getKey();
            if (url.contains(key)) {
                url = url.replace(key, entry.getValue());
                template.uri(url);
            }
        }
    }
    private void replaceSlash(RequestTemplate template) {
        String url = template.url();
        if (url.startsWith("//")) {
            url = "http:" + url;
            //去除地址后面的参数,防止下面重新设置target的时候出现参数重复
            int index = url.indexOf("?");
            if (index > 0) {
                url = url.substring(0, index);
            }
            template.target(url);
            template.uri("");
        }
    }
}
3. 配置文件配置动态映射替换
feign-interceptor-config:
  server-map:
    "[$SERVER-NAME]" : shine-test-feign
4. 动态调用
@Slf4j
@RestController
@RequestMapping("/test")
public class TestFeignController {
    @PostMapping(value = "/test02")
    public AjaxResult test02(@RequestBody JSONObject object) {
        AjaxResult result = testClient.test02(object);
        log.info("result:{}", result);
        return result;
    }
}
方案三(@PathVariable)
1. 在对feignClient中API定义
@FeignClient(name = "TestClient", contextId = "TestClient")
public interface TestClient {
    
    @PostMapping(value = "//{serviceName}/{contextPath}")
    AjaxResult test(@PathVariable(name = "serviceName") String serviceName, @PathVariable(name = "contextPath") String contextPath, @RequestBody JSONObject object);
}
2. 定义FeignInterceptorConfig
同方案二
3.动态调用
@Slf4j
@RestController
@RequestMapping("/test")
public class TestFeignController {
    @PostMapping(value = "/test03")
    public AjaxResult test03(@RequestBody JSONObject object) {
        AjaxResult result = testClient.test03("shine-test-feign", "/test/test", object);
        log.info("result:{}", result);
        return result;
    }
}