Openfeign动态构建client实现同服务serviceId不同instanceId互相调用
本文基于springcloud2.0.0.RELEASE和eureka
openfeign2.0.4.RELEASE版本:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
工具类:
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignClientBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Getter
@Component
public class DynamicFeignClient {
private String serviceId;//一般是xxx-server
private String instanceId;//一般是ip:port
private InstanceInfo thisInfo;
private final FeignClientBuilder feignClientBuilder;
@Resource
private EurekaClient eurekaClient;
public DynamicFeignClient(@Autowired ApplicationContext appContext) {
feignClientBuilder = new FeignClientBuilder(appContext);
}
@PostConstruct
public void init() {
ApplicationInfoManager applicationInfoManager = eurekaClient.getApplicationInfoManager();
serviceId = applicationInfoManager.getEurekaInstanceConfig().getAppname();
thisInfo = applicationInfoManager.getInfo();
instanceId = thisInfo.getInstanceId();
}
/*
* 返回若干个client,分别对应不同的服务实例
* excludeThis=true排除自己
* */
public <T> List<T> getClientsList(Class<T> type, boolean excludeThis) {
FeignClient annotation = AnnotationUtils.findAnnotation(type, FeignClient.class);
if (annotation == null) {
throw new IllegalArgumentException("缺少@FeignClient注解");
}
List<InstanceInfo> instances = eurekaClient.getApplications().getInstancesByVirtualHostName(getServiceId());
if (excludeThis) {
instances = instances.stream().filter(f -> !f.equals(thisInfo)).collect(Collectors.toList());
}
String path = annotation.path();
List<T> ret = new ArrayList<>(instances.size());
for (InstanceInfo instance : instances) {
String homePageUrl = instance.getHomePageUrl();
FeignClientBuilder.Builder<T> builder = feignClientBuilder.forType(type, getServiceId());
builder.url(homePageUrl);
builder.path(path);
ret.add(builder.build());
}
return ret;
}
public <T> List<T> getClientsList(Class<T> type) {
return getClientsList(type, false);
}
}