Closed
Description
public Map<String, String> getMetaData() {
metaData = new HashMap<>();
Method[] methods = this.getClass().getMethods();
for (Method method : methods) {
try {
String name = method.getName();
if ((name.startsWith("get") || name.startsWith("is"))
&& !name.equals("get")
&& !"getClass".equals(name)
&& Modifier.isPublic(method.getModifiers())
&& method.getParameterTypes().length == 0
&& isPrimitive(method.getReturnType())) {
int i = name.startsWith("get") ? 3 : 2;
String prop = StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");
String key;
Parameter parameter = method.getAnnotation(Parameter.class);
if (parameter != null && parameter.key().length() > 0) {
key = parameter.key();
} else {
key = prop;
}
// treat url and configuration differently, the value should always present in configuration though it may not need to present in url.
//if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
if (method.getReturnType() == Object.class) {
metaData.put(key, null);
continue;
}
Object value = method.invoke(this);
String str = String.valueOf(value).trim();
if (value != null && str.length() > 0) {
if (parameter != null && parameter.escaped()) {
str = URL.encode(str);
}
if (parameter != null && parameter.append()) {
String pre = String.valueOf(metaData.get(Constants.DEFAULT_KEY + "." + key));
if (pre != null && pre.length() > 0) {
str = pre + "," + str;
}
pre = String.valueOf(metaData.get(key));
if (pre != null && pre.length() > 0) {
str = pre + "," + str;
}
}
/* if (prefix != null && prefix.length() > 0) {
key = prefix + "." + key;
}*/
metaData.put(key, str);
} else {
metaData.put(key, null);
}
// TODO check required somewhere else.
/*else if (parameter != null && parameter.required()) {
throw new IllegalStateException(this.getClass().getSimpleName() + "." + key + " == null");
}*/
} else if ("getParameters".equals(name)
&& Modifier.isPublic(method.getModifiers())
&& method.getParameterTypes().length == 0
&& method.getReturnType() == Map.class) {
Map<String, String> map = (Map<String, String>) method.invoke(this, new Object[0]);
if (map != null && map.size() > 0) {
// String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : "");
for (Map.Entry<String, String> entry : map.entrySet()) {
metaData.put(entry.getKey().replace('-', '.'), entry.getValue());
}
}
}
} catch (Exception e) {
System.out.println(this.getClass().getName());
System.out.println(method.getName());
throw new IllegalStateException(e.getMessage(), e);
}
}
return metaData;
}
我在provider端通过泛化的方式提供服务,providers的参数generic=true.在consumer端没有配置generic的值。在mergeUrl的时候应该会拿providerUrl的generic参数。最终consumer端的url的generic应该为true,但是最终发现mergeUrl之后的url的generic=false了,导致后续consumer端调用异常,最后追踪发现在consume端,consumerConfig的refresh发现了问题,这里通过反射获取当前对象的所有方法,如果isGeneric方法在getGeneric后面执行的话,会导致isGeneric的值覆盖掉getGeneric的值。
关于这行代码也许可以改成
if (method.getReturnType() == Object.class) {
metaData.put(key, null);
continue;
}
->
if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
metaData.putIfAbsent(key, null);
continue;
}
这样既可以解决掉上面那种场景,也可以避免设置了genric=true,但是被null覆盖掉的场景。
Activity
horizonzy commentedon May 19, 2020
@mercyblitz 小马哥看看
shengchaojie commentedon Aug 5, 2020
@horizonzy 我也遇到了这个问题,我感觉在mergeurl的时候,应该判断是让provider url 的generic配置 覆盖消费者的配置
shengchaojie commentedon Aug 5, 2020
generic 在泛化实现这个场景下 比较特殊,其他的配置都是本地为主,但是泛化实现是提供者端去控制消费者端的行为,所以要以提供者端=true的情况为主,如果provider的generic=true 那么无条件覆盖消费者端的,如果为false,那么不修改消费者端 @mercyblitz
horizonzy commentedon Nov 12, 2020
过了几个月来看。pr-#4678 fix了这个问题