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

经验分享 程序员 微信小程序 职场和发展