Spring-cloud-openfeign动态指定服务名service-name
自己在工作中定义了一个公用的feign调用包,供各个代码工程引入,但是这里存在一个问题,由于feign的服务名是在@FeignClient中写死的,如果遇到线上的测试和正式环境都部署的情况,就得修改调用的服务名,以保证调用到相应环境的服务名,由此在网上找了一些方法,亲测可行,做法如下。
1、在Service Client中API的URL中定义一个特殊的变量标记,如:
@FeignClient("service-name")
public interface CustomerService {
@GetMapping("//$SERVER-NAME/doSomething")
public String doSomething();
}
上述示例中的customerInfo方法URI中有两个特殊的地方:
一是前面“//”,这个是由于feign template不允许URI有“http://"开头,所以我们用“//”标记为后面紧跟着服务名称,而不是普通的URI 二是“$CLUSTER_ID”,这个是后面要替换成业务单元编号的 在RequestInterceptor中查找到特殊的变量标记,根据路由规则把变量转换成实际值:
@Configuration
public class FeignInterceptorConfig{
@Value("${sys.server-name}")
private String serverName;
@Bean
public RequestInterceptor cloudContextInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
String url = template.url();
if (url.contains("$SERVER-NAME")) {
url = url.replace("$SERVER-NAME", serverName);
template.uri(url);
if (url.startsWith("//")) {
url = "http:" + url;
//去除地址后面的参数,防止下面重新设置target的时候出现参数重复
url=url.substring(0,url.indexOf("?"));
template.target(url);
template.uri("");
}
}
}
};
}
}
这样就能实现服务单元路由了。
另外,上述我用的openfeign是2.2.1.RELEASE版本,据网友说,在Spring-cloud-openfeign 3.0.0.M2版本里面有更优雅的实现方式,实现单元化动态指定服务名,可以参考: https://blog..net/weixin_45357522/article/details/106745468
