![JAR search and dependency download from the Maven repository](/logo.png)
com.github.linyuzai.dynamicfeign.mapper.DynamicFeignClientMapper Maven / Gradle / Ivy
package com.github.linyuzai.dynamicfeign.mapper;
import com.github.linyuzai.dynamicfeign.factory.DynamicFeignClientFactoryBean;
import com.github.linyuzai.dynamicfeign.targeter.Targeter;
import feign.Client;
import feign.Feign;
import feign.Target;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* feign clients存储配置类
*/
public class DynamicFeignClientMapper {
/**
* 微服务对应的feign map
*/
private static Map feignClientMap = new ConcurrentHashMap<>();
/**
* 获得所有的feign client
*
* @return 所有的feign client
*/
public static List getFeignClientEntities() {
return feignClientMap.values().stream().map(ConfigurableFeignClient::getEntity).collect(Collectors.toList());
}
/**
* 获得某个微服务的feign配置
*
* @param key 微服务名称
* @return 某个微服务的feign配置
*/
public ConfigurableFeignClientEntity getConfigurableFeignClientEntity(String key) {
ConfigurableFeignClient client = feignClientMap.get(key);
return client == null ? null : client.entity;
}
/**
* 获得某个微服务的feign client
*
* @param key 微服务名称
* @return 某个微服务的feign client
*/
public ConfigurableFeignClient getConfigurableFeignClient(String key) {
return feignClientMap.get(key);
}
/**
* 添加一个feign client,一般扫描配置的时候才会用到
*
* @param client 需要添加的client
*/
public static void add(ConfigurableFeignClient client) {
if (client.entity.key == null) {
throw new RuntimeException("key is null");
}
ConfigurableFeignClient feignClient = feignClientMap.get(client.entity.key);
if (feignClient == null) {
if (client.entity.inUrl == null) {
throw new RuntimeException("inUrl is null");
}
if (client.entity.feignOut && client.entity.outUrl == null) {
throw new RuntimeException("outUrl is null when feignOut=true");
}
client.entity.inUrl = getParsedUrl(client.entity.inUrl);
client.in = client.newInstance(null);
if (client.entity.outUrl != null) {
client.entity.outUrl = getParsedUrl(client.entity.outUrl);
client.out = client.newInstance(client.entity.outUrl);
}
feignClientMap.put(client.entity.key, client);
} else {
throw new RuntimeException("key exists");
}
}
/**
* 更新某个feign配置
*
* @param entity 需要更新的feign配置
* @return 是否成功
*/
public static synchronized boolean update(ConfigurableFeignClientEntity entity) {
ConfigurableFeignClient client = getExistConfigurableFeignClient(entity.key);
if (entity.outUrl != null) {
entity.outUrl = getParsedUrl(entity.outUrl);
Object out = client.newInstance(entity.outUrl);
client.entity.outUrl = entity.outUrl;
client.out = out;
}
if (entity.feignOut && client.out == null) {
throw new RuntimeException("Set outUrl if you want feignOut");
}
client.entity.feignOut = entity.feignOut;
client.entity.feignMethod = entity.feignMethod;
return true;
}
private static ConfigurableFeignClient getExistConfigurableFeignClient(String key) {
if (key == null) {
throw new RuntimeException("key is null");
}
ConfigurableFeignClient client = feignClientMap.get(key);
if (client == null) {
throw new RuntimeException("key not found");
}
return client;
}
/**
* 添加方法对应的url
*
* @param key 微服务名称
* @param methodName 方法名称
* @param url url
* @return 是否成功
*/
public static synchronized boolean addMethodUrl(String key, String methodName, String url) {
if (url == null) {
throw new RuntimeException("url is null");
}
if (methodName == null) {
throw new RuntimeException("method name is null");
}
ConfigurableFeignClient client = getExistConfigurableFeignClient(key);
url = getParsedUrl(url);
Object out = client.newInstance(url);
if (client.entity.methodUrls == null) {
client.entity.methodUrls = new ConcurrentHashMap<>();
}
client.entity.methodUrls.put(methodName, url);
if (client.methodFeigns == null) {
client.methodFeigns = new ConcurrentHashMap<>();
}
client.methodFeigns.put(methodName, out);
return true;
}
public static synchronized boolean removeMethodUrl(String key, String methodName) {
if (methodName == null) {
throw new RuntimeException("method name is null");
}
ConfigurableFeignClient client = getExistConfigurableFeignClient(key);
if (client.entity.methodUrls != null) {
client.entity.methodUrls.remove(methodName);
}
if (client.methodFeigns != null) {
client.methodFeigns.remove(methodName);
}
return true;
}
public static synchronized boolean clearMethodUrl(String key) {
ConfigurableFeignClient client = getExistConfigurableFeignClient(key);
if (client.entity.methodUrls != null) {
client.entity.methodUrls.clear();
}
if (client.methodFeigns != null) {
client.methodFeigns.clear();
}
return true;
}
public static String getParsedUrl(String url) {
url = url.trim();
while (url.startsWith("/")) {
url = url.substring(1);
}
while (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
if (!url.startsWith("http")) {
url = "http://" + url;
}
return url;
}
/**
* feign client配置类
*/
public static class ConfigurableFeignClientEntity {
/**
* 微服务名称
*/
private String key;
/**
* feign接口
*/
private Class> type;
/**
* 内网服务间的url
*/
private String inUrl;
/**
* 指定的url
*/
private String outUrl;
/**
* 是否使用指定url
*/
private boolean feignOut;
/**
* 是否映射方法指定url
*/
private boolean feignMethod;
private Map methodUrls;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Class> getType() {
return type;
}
public void setType(Class> type) {
this.type = type;
}
public String getInUrl() {
return inUrl;
}
public void setInUrl(String inUrl) {
this.inUrl = inUrl;
}
public String getOutUrl() {
return outUrl;
}
public void setOutUrl(String outUrl) {
this.outUrl = outUrl;
}
public boolean isFeignOut() {
return feignOut;
}
public void setFeignOut(boolean feignOut) {
this.feignOut = feignOut;
}
public boolean isFeignMethod() {
return feignMethod;
}
public void setFeignMethod(boolean feignMethod) {
this.feignMethod = feignMethod;
}
public Map getMethodUrls() {
return methodUrls;
}
public void setMethodOutUrls(Map methodUrls) {
this.methodUrls = methodUrls;
}
}
public static class ConfigurableFeignClient {
private FeignContext context;
private Feign.Builder builder;
private Client client;
private Targeter targeter;
private DynamicFeignClientFactoryBean factory;
/**
* 默认内网间调用的feign
*/
private Object in;
/**
* 指定url的feign
*/
private Object out;
/**
* 根据方法映射的feign
*/
private Map methodFeigns;
private ConfigurableFeignClientEntity entity;
public ConfigurableFeignClient(FeignContext context, Feign.Builder builder, Client client,
Targeter targeter, DynamicFeignClientFactoryBean factory) {
if (client == null) {
throw new IllegalStateException(
"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
}
this.context = context;
this.builder = builder;
this.client = client;
this.targeter = targeter;
this.factory = factory;
this.entity = new ConfigurableFeignClientEntity();
}
/**
* 实例化feign
*
* @param url 如果为null,实例化in
* @return feign的实例
*/
public synchronized Object newInstance(String url) {
if (url == null) {
builder.client(client);
return targeter.target(factory, builder, context,
new Target.HardCodedTarget<>(entity.type, entity.key, entity.inUrl));
} else {
if (url.equals(entity.inUrl)) {
return in;
}
if (url.equals(entity.outUrl)) {
return out;
}
if (entity.methodUrls != null) {
for (Map.Entry entry : entity.methodUrls.entrySet()) {
if (url.equals(entry.getValue())) {
Object feign = methodFeigns.get(entry.getKey());
if (feign != null) {
return feign;
}
}
}
}
if (client instanceof LoadBalancerFeignClient) {
builder.client(((LoadBalancerFeignClient) client).getDelegate());
}
return targeter.target(factory, builder, context,
new Target.HardCodedTarget<>(entity.type, entity.key, url));
}
}
public Object dynamic(Method method) {
if (entity.feignMethod) {
String key = method.getName();
if (entity.feignOut) {
return methodFeigns == null ? out : methodFeigns.getOrDefault(key, out);
} else {
return methodFeigns == null ? in : methodFeigns.getOrDefault(key, in);
}
} else {
return entity.feignOut ? out : in;
}
}
public FeignContext getContext() {
return context;
}
public void setContext(FeignContext context) {
this.context = context;
}
public Feign.Builder getBuilder() {
return builder;
}
public void setBuilder(Feign.Builder builder) {
this.builder = builder;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Targeter getTargeter() {
return targeter;
}
public void setTargeter(Targeter targeter) {
this.targeter = targeter;
}
public DynamicFeignClientFactoryBean getFactory() {
return factory;
}
public void setFactory(DynamicFeignClientFactoryBean factory) {
this.factory = factory;
}
public Object getIn() {
return in;
}
public void setIn(Object in) {
this.in = in;
}
public Object getOut() {
return out;
}
public void setOut(Object out) {
this.out = out;
}
public Map getMethodFeigns() {
return methodFeigns;
}
public void setMethodFeigns(Map methodFeigns) {
this.methodFeigns = methodFeigns;
}
public ConfigurableFeignClientEntity getEntity() {
return entity;
}
public void setEntity(ConfigurableFeignClientEntity entity) {
this.entity = entity;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy