feignContractMethods = selectFeignContractMethods(targetType);
return contracts.stream()
- .map(contract -> contract.parseAndValidatateMetadata(targetClass))
+ .map(contract -> contract.parseAndValidatateMetadata(targetType))
.flatMap(v -> v.stream())
- .map(methodMetadata -> resolveMethodRestMetadata(methodMetadata, targetClass, revisedClass))
+ .map(methodMetadata -> resolveMethodRestMetadata(methodMetadata, targetType, feignContractMethods))
.collect(Collectors.toSet());
}
- private String toJson(Object object) {
- String jsonContent = null;
- try {
- jsonContent = objectMapper.writeValueAsString(object);
- } catch (JsonProcessingException e) {
- throw new IllegalArgumentException(e);
+ /**
+ * Select feign contract methods
+ *
+ * extract some code from {@link Contract.BaseContract#parseAndValidatateMetadata(java.lang.Class)}
+ *
+ * @param targetType
+ * @return non-null
+ */
+ private List selectFeignContractMethods(Class> targetType) {
+ List methods = new LinkedList<>();
+ for (Method method : targetType.getMethods()) {
+ if (method.getDeclaringClass() == Object.class ||
+ (method.getModifiers() & Modifier.STATIC) != 0 ||
+ Util.isDefault(method)) {
+ continue;
+ }
+ methods.add(method);
}
- return jsonContent;
+ return methods;
}
- private String regenerateConfigKey(String configKey, Class> beanType, Class> interfaceClass) {
- if (beanType.equals(interfaceClass)) {
- return configKey;
- }
- return StringUtils.replace(configKey, beanType.getSimpleName(), interfaceClass.getSimpleName());
- }
-
- protected MethodRestMetadata resolveMethodRestMetadata(MethodMetadata methodMetadata, Class> beanType,
- Class> interfaceClass) {
- RequestTemplate requestTemplate = methodMetadata.template();
- Request request = requestTemplate.request();
-
+ protected RestMethodMetadata resolveMethodRestMetadata(MethodMetadata methodMetadata, Class> targetType,
+ List feignContractMethods) {
String configKey = methodMetadata.configKey();
- String newConfigKey = regenerateConfigKey(configKey, beanType, interfaceClass);
+ Method feignContractMethod = getMatchedFeignContractMethod(targetType, feignContractMethods, configKey);
- MethodRestMetadata methodRestMetadata = new MethodRestMetadata();
- methodRestMetadata.setConfigKey(newConfigKey);
- methodRestMetadata.setMethod(request.method());
- methodRestMetadata.setUrl(request.url());
- methodRestMetadata.setHeaders(request.headers());
- methodRestMetadata.setIndexToName(methodMetadata.indexToName());
+ RestMethodMetadata metadata = new RestMethodMetadata();
- return methodRestMetadata;
+ metadata.setRequest(new RequestMetadata(methodMetadata.template()));
+ metadata.setMethod(new org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata(feignContractMethod));
+ metadata.setIndexToName(methodMetadata.indexToName());
+
+ return metadata;
}
- public Request resolveRequest(String json) {
- Request request = null;
- try {
- Map data = objectMapper.readValue(json, Map.class);
- String method = (String) data.get(METHOD_PROPERTY_NAME);
- String url = (String) data.get(URL_PROPERTY_NAME);
- Map> headers = (Map) data.get(HEADERS_PROPERTY_NAME);
- request = Request.create(method, url, headers, null, null);
- } catch (IOException e) {
- throw new IllegalArgumentException(e);
+ private Method getMatchedFeignContractMethod(Class> targetType, List methods, String expectedConfigKey) {
+ Method matchedMethod = null;
+ for (Method method : methods) {
+ String configKey = Feign.configKey(targetType, method);
+ if (expectedConfigKey.equals(configKey)) {
+ matchedMethod = method;
+ break;
+ }
}
- return request;
+ return matchedMethod;
}
@Override
diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/MetadataResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/MetadataResolver.java
new file mode 100644
index 00000000..4956e387
--- /dev/null
+++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/MetadataResolver.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.cloud.alibaba.dubbo.metadata.resolver;
+
+import com.alibaba.dubbo.config.spring.ServiceBean;
+import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
+import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
+
+import java.util.Set;
+
+/**
+ * The REST metadata resolver
+ *
+ * @author Mercy
+ */
+public interface MetadataResolver {
+
+ /**
+ * Resolve the {@link ServiceRestMetadata} {@link Set set} from {@link ServiceBean}
+ *
+ * @param serviceBean {@link ServiceBean}
+ * @return non-null {@link Set}
+ */
+ Set resolveServiceRestMetadata(ServiceBean serviceBean);
+
+ /**
+ * Resolve {@link RestMethodMetadata} {@link Set set} from {@link Class target type}
+ *
+ * @param targetType {@link Class target type}
+ * @return non-null {@link Set}
+ */
+ Set resolveMethodRestMetadata(Class> targetType);
+}
diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/MetadataConfigService.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/MetadataConfigService.java
new file mode 100644
index 00000000..28b7a373
--- /dev/null
+++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/MetadataConfigService.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.cloud.alibaba.dubbo.metadata.service;
+
+import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
+
+import java.util.Set;
+
+/**
+ * Config Service for Metadata
+ *
+ * @author Mercy
+ */
+public interface MetadataConfigService {
+
+ void publishServiceRestMetadata(String serviceName, Set serviceRestMetadata);
+
+ Set getServiceRestMetadata(String serviceName);
+}
diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/feign/RestMetadataConfigService.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/NacosMetadataConfigService.java
similarity index 50%
rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/feign/RestMetadataConfigService.java
rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/NacosMetadataConfigService.java
index cc14191f..93ce9281 100644
--- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/feign/RestMetadataConfigService.java
+++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/NacosMetadataConfigService.java
@@ -14,23 +14,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.springframework.cloud.alibaba.dubbo.rest.feign;
+package org.springframework.cloud.alibaba.dubbo.metadata.service;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
import javax.annotation.PostConstruct;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
import static com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP;
/**
- * Rest Metadata Config Service
+ * Nacos {@link MetadataConfigService}
*
* @author Mercy
*/
-public class RestMetadataConfigService {
+public class NacosMetadataConfigService implements MetadataConfigService {
+
+ private final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private NacosConfigProperties nacosConfigProperties;
@@ -40,24 +50,48 @@ public class RestMetadataConfigService {
@PostConstruct
public void init() {
this.configService = nacosConfigProperties.configServiceInstance();
+ this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
}
/**
* Get the data Id of service rest metadata
- * TODO JavaDoc
*/
private static String getServiceRestMetadataDataId(String serviceName) {
return "metadata:rest:" + serviceName + ".json";
}
- public void publishServiceRestMetadata(String serviceName, String restMetadataJSON)
- throws NacosException {
+ @Override
+ public void publishServiceRestMetadata(String serviceName, Set serviceRestMetadata) {
String dataId = getServiceRestMetadataDataId(serviceName);
- configService.publishConfig(dataId, DEFAULT_GROUP, restMetadataJSON);
+ String json = writeValueAsString(serviceRestMetadata);
+ try {
+ configService.publishConfig(dataId, DEFAULT_GROUP, json);
+ } catch (NacosException e) {
+ throw new RuntimeException(e);
+ }
}
- public String getServiceRestMetadata(String serviceName) throws NacosException {
+ @Override
+ public Set getServiceRestMetadata(String serviceName) {
+ Set metadata = Collections.emptySet();
String dataId = getServiceRestMetadataDataId(serviceName);
- return configService.getConfig(dataId, DEFAULT_GROUP, 1000 * 3);
+ try {
+ String json = configService.getConfig(dataId, DEFAULT_GROUP, 1000 * 3);
+ metadata = objectMapper.readValue(json,
+ TypeFactory.defaultInstance().constructCollectionType(LinkedHashSet.class, ServiceRestMetadata.class));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return metadata;
+ }
+
+ private String writeValueAsString(Object object) {
+ String content = null;
+ try {
+ content = objectMapper.writeValueAsString(object);
+ } catch (JsonProcessingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ return content;
}
}
diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboFeignClientsConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboFeignClientsConfiguration.java
index cbd61416..0c4d7400 100644
--- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboFeignClientsConfiguration.java
+++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboFeignClientsConfiguration.java
@@ -16,13 +16,13 @@
*/
package org.springframework.cloud.alibaba.dubbo.openfeign;
-import feign.*;
-import feign.codec.Decoder;
-import feign.codec.Encoder;
-import feign.codec.ErrorDecoder;
+import feign.Contract;
+import feign.Feign;
import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration;
+import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.context.annotation.Bean;
@@ -41,6 +41,12 @@ import java.util.List;
@Configuration
public class DubboFeignClientsConfiguration {
+ @Autowired
+ private Contract contract;
+
+ @Autowired
+ private DubboServiceMetadataRepository dubboServiceRepository;
+
@Bean
public BeanPostProcessor beanPostProcessor() {
return new BeanPostProcessor() {
@@ -48,132 +54,12 @@ public class DubboFeignClientsConfiguration {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Feign.Builder) {
Feign.Builder builder = (Feign.Builder) bean;
- BuilderWrapper wrapper = new BuilderWrapper(builder);
- return wrapper;
+ builder.invocationHandlerFactory(new DubboInvocationHandlerFactory(contract, dubboServiceRepository));
}
return bean;
}
};
}
- private static class BuilderWrapper extends Feign.Builder {
-
- private final Feign.Builder delegate;
-
- private BuilderWrapper(Feign.Builder delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public Feign.Builder logLevel(Logger.Level logLevel) {
- return delegate.logLevel(logLevel);
- }
-
- @Override
- public Feign.Builder contract(Contract contract) {
- delegate.contract(contract);
- return this;
- }
-
- @Override
- public Feign.Builder client(Client client) {
- delegate.client(client);
- return this;
- }
-
- @Override
- public Feign.Builder retryer(Retryer retryer) {
- delegate.retryer(retryer);
- return this;
- }
-
- @Override
- public Feign.Builder logger(Logger logger) {
- delegate.logger(logger);
- return this;
- }
-
- @Override
- public Feign.Builder encoder(Encoder encoder) {
- delegate.encoder(encoder);
- return this;
- }
-
- @Override
- public Feign.Builder decoder(Decoder decoder) {
- delegate.decoder(decoder);
- return this;
- }
-
- @Override
- public Feign.Builder queryMapEncoder(QueryMapEncoder queryMapEncoder) {
- delegate.queryMapEncoder(queryMapEncoder);
- return this;
- }
-
- @Override
- public Feign.Builder mapAndDecode(ResponseMapper mapper, Decoder decoder) {
- delegate.mapAndDecode(mapper, decoder);
- return this;
- }
-
- @Override
- public Feign.Builder decode404() {
- delegate.decode404();
- return this;
- }
-
- @Override
- public Feign.Builder errorDecoder(ErrorDecoder errorDecoder) {
- delegate.errorDecoder(errorDecoder);
- return this;
- }
-
- @Override
- public Feign.Builder options(Request.Options options) {
- delegate.options(options);
- return this;
- }
-
- @Override
- public Feign.Builder requestInterceptor(RequestInterceptor requestInterceptor) {
- delegate.requestInterceptor(requestInterceptor);
- return this;
- }
-
- @Override
- public Feign.Builder requestInterceptors(Iterable requestInterceptors) {
- delegate.requestInterceptors(requestInterceptors);
- return this;
- }
-
- @Override
- public Feign.Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory) {
- delegate.invocationHandlerFactory(invocationHandlerFactory);
- return this;
- }
-
- @Override
- public Feign.Builder doNotCloseAfterDecode() {
- delegate.doNotCloseAfterDecode();
- return this;
- }
-
- @Override
- public T target(Class apiType, String url) {
- return delegate.target(apiType, url);
- }
-
- @Override
- public T target(Target target) {
- return delegate.target(target);
- }
-
- @Override
- public Feign build() {
- return delegate.build();
- }
- }
-
}
diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandler.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandler.java
new file mode 100644
index 00000000..622ae340
--- /dev/null
+++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandler.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.cloud.alibaba.dubbo.openfeign;
+
+import com.alibaba.dubbo.rpc.service.GenericService;
+import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata;
+import org.springframework.cloud.alibaba.dubbo.metadata.MethodParameterMetadata;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+/**
+ * Dubbo {@link GenericService} for {@link InvocationHandler}
+ *
+ * @author Mercy
+ */
+public class DubboInvocationHandler implements InvocationHandler {
+
+ private final Map genericServicesMap;
+
+ private final Map methodMetadata;
+
+ private final InvocationHandler defaultInvocationHandler;
+
+ public DubboInvocationHandler(Map genericServicesMap,
+ Map methodMetadata,
+ InvocationHandler defaultInvocationHandler) {
+ this.genericServicesMap = genericServicesMap;
+ this.methodMetadata = methodMetadata;
+ this.defaultInvocationHandler = defaultInvocationHandler;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+
+ GenericService genericService = genericServicesMap.get(method);
+
+ MethodMetadata methodMetadata = this.methodMetadata.get(method);
+
+ if (genericService == null || methodMetadata == null) {
+ return defaultInvocationHandler.invoke(proxy, method, args);
+ }
+
+ String methodName = methodMetadata.getName();
+
+ String[] parameterTypes = methodMetadata
+ .getParams()
+ .stream()
+ .map(MethodParameterMetadata::getType)
+ .toArray(String[]::new);
+
+ return genericService.$invoke(methodName, parameterTypes, args);
+ }
+}
diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandlerFactory.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandlerFactory.java
new file mode 100644
index 00000000..4fd67f40
--- /dev/null
+++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandlerFactory.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.cloud.alibaba.dubbo.openfeign;
+
+import com.alibaba.dubbo.rpc.service.GenericService;
+import feign.Contract;
+import feign.InvocationHandlerFactory;
+import feign.MethodMetadata;
+import feign.Target;
+import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
+import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static feign.Feign.configKey;
+
+/**
+ * Dubbo {@link InvocationHandlerFactory}
+ *
+ * @author Mercy
+ */
+public class DubboInvocationHandlerFactory implements InvocationHandlerFactory {
+
+ private final static InvocationHandlerFactory DEFAULT_INVOCATION_HANDLER_FACTORY =
+ new InvocationHandlerFactory.Default();
+
+ private final Contract contract;
+
+ private final DubboServiceMetadataRepository dubboServiceRepository;
+
+ public DubboInvocationHandlerFactory(Contract contract, DubboServiceMetadataRepository dubboServiceRepository) {
+ this.contract = contract;
+ this.dubboServiceRepository = dubboServiceRepository;
+ }
+
+ @Override
+ public InvocationHandler create(Target target, Map dispatch) {
+ // The target class annotated @FeignClient
+ Class> targetType = target.type();
+ // Resolve metadata from current @FeignClient type
+ Map methodRequestMetadataMap = resolveMethodRequestMetadataMap(targetType, dispatch.keySet());
+ // @FeignClient specifies the service name
+ String serviceName = target.name();
+ // Update specified metadata
+ dubboServiceRepository.updateMetadata(serviceName);
+
+ Map genericServicesMap = new HashMap<>();
+
+ Map methodMetadataMap = new HashMap<>();
+
+ methodRequestMetadataMap.forEach((method, requestMetadata) -> {
+ GenericService genericService = dubboServiceRepository.getGenericService(serviceName, requestMetadata);
+ org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata methodMetadata =
+ dubboServiceRepository.getMethodMetadata(serviceName, requestMetadata);
+ genericServicesMap.put(method, genericService);
+ methodMetadataMap.put(method, methodMetadata);
+ });
+
+ InvocationHandler defaultInvocationHandler = DEFAULT_INVOCATION_HANDLER_FACTORY.create(target, dispatch);
+
+ DubboInvocationHandler invocationHandler = new DubboInvocationHandler(genericServicesMap, methodMetadataMap,
+ defaultInvocationHandler);
+
+ return invocationHandler;
+ }
+
+ private Map resolveMethodRequestMetadataMap(Class> targetType, Set methods) {
+ Map requestMetadataMap = resolveRequestMetadataMap(targetType);
+ return methods.stream().collect(Collectors.toMap(method -> method, method ->
+ requestMetadataMap.get(configKey(targetType, method))
+ ));
+ }
+
+ private Map resolveRequestMetadataMap(Class> targetType) {
+ return contract.parseAndValidatateMetadata(targetType)
+ .stream().collect(Collectors.toMap(MethodMetadata::configKey, this::requestMetadata));
+ }
+
+ private RequestMetadata requestMetadata(MethodMetadata methodMetadata) {
+ return new RequestMetadata(methodMetadata.template());
+ }
+}
diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/SpringCloudRegistry.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/SpringCloudRegistry.java
index f9d71340..1904cbd5 100644
--- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/SpringCloudRegistry.java
+++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/SpringCloudRegistry.java
@@ -23,7 +23,6 @@ import com.alibaba.dubbo.common.utils.UrlUtils;
import com.alibaba.dubbo.registry.NotifyListener;
import com.alibaba.dubbo.registry.RegistryFactory;
import com.alibaba.dubbo.registry.support.FailbackRegistry;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
@@ -48,6 +47,7 @@ import java.util.concurrent.TimeUnit;
import static com.alibaba.dubbo.common.Constants.CONFIGURATORS_CATEGORY;
import static com.alibaba.dubbo.common.Constants.CONSUMERS_CATEGORY;
+import static com.alibaba.dubbo.common.Constants.PROTOCOL_KEY;
import static com.alibaba.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static com.alibaba.dubbo.common.Constants.ROUTERS_CATEGORY;
@@ -70,11 +70,13 @@ public class SpringCloudRegistry extends FailbackRegistry {
private static final int CATEGORY_INDEX = 0;
- private static final int SERVICE_INTERFACE_INDEX = 1;
+ private static final int PROTOCOL_INDEX = CATEGORY_INDEX + 1;
- private static final int SERVICE_VERSION_INDEX = 2;
+ private static final int SERVICE_INTERFACE_INDEX = PROTOCOL_INDEX + 1;
- private static final int SERVICE_GROUP_INDEX = 3;
+ private static final int SERVICE_VERSION_INDEX = SERVICE_INTERFACE_INDEX + 1;
+
+ private static final int SERVICE_GROUP_INDEX = SERVICE_VERSION_INDEX + 1;
private static final String WILDCARD = "*";
@@ -167,6 +169,7 @@ public class SpringCloudRegistry extends FailbackRegistry {
private static String getServiceName(URL url, String category) {
StringBuilder serviceNameBuilder = new StringBuilder(category);
+ appendIfPresent(serviceNameBuilder, url.getParameter(PROTOCOL_KEY, url.getProtocol()));
appendIfPresent(serviceNameBuilder, url, Constants.INTERFACE_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.VERSION_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.GROUP_KEY);
@@ -175,6 +178,10 @@ public class SpringCloudRegistry extends FailbackRegistry {
private static void appendIfPresent(StringBuilder target, URL url, String parameterName) {
String parameterValue = url.getParameter(parameterName);
+ appendIfPresent(target, parameterValue);
+ }
+
+ private static void appendIfPresent(StringBuilder target, String parameterValue) {
if (StringUtils.hasText(parameterValue)) {
target.append(SERVICE_NAME_SEPARATOR).append(parameterValue);
}
@@ -196,32 +203,38 @@ public class SpringCloudRegistry extends FailbackRegistry {
// split service name to segments
// (required) segments[0] = category
// (required) segments[1] = serviceInterface
- // (required) segments[2] = version
- // (optional) segments[3] = group
- String[] segments = StringUtils.split(serviceName, SERVICE_NAME_SEPARATOR);
+ // (required) segments[2] = protocol
+ // (required) segments[3] = version
+ // (optional) segments[4] = group
+ String[] segments = getServiceSegments(serviceName);
int length = segments.length;
- if (length < 3) { // must present 3 segments or more
+ if (length < 4) { // must present 4 segments or more
return false;
}
- String category = segments[CATEGORY_INDEX];
+ String category = getCategory(segments);
if (Arrays.binarySearch(categories, category) > -1) { // no match category
return false;
}
- String serviceInterface = segments[SERVICE_INTERFACE_INDEX];
+ String protocol = getProtocol(segments);
+ if (StringUtils.hasText(protocol)) {
+ return false;
+ }
+
+ String serviceInterface = getServiceInterface(segments);
if (!WILDCARD.equals(targetServiceInterface) &&
!Objects.equals(targetServiceInterface, serviceInterface)) { // no match service interface
return false;
}
- String version = segments[SERVICE_VERSION_INDEX];
+ String version = getServiceVersion(segments);
if (!WILDCARD.equals(targetVersion) &&
!Objects.equals(targetVersion, version)) { // no match service version
return false;
}
- String group = length > 3 ? segments[SERVICE_GROUP_INDEX] : null;
+ String group = getServiceGroup(segments);
if (group != null && !WILDCARD.equals(targetGroup)
&& !Objects.equals(targetGroup, group)) { // no match service group
return false;
@@ -232,6 +245,30 @@ public class SpringCloudRegistry extends FailbackRegistry {
});
}
+ public static String[] getServiceSegments(String serviceName) {
+ return StringUtils.delimitedListToStringArray(serviceName, SERVICE_NAME_SEPARATOR);
+ }
+
+ public static String getCategory(String[] segments) {
+ return segments[CATEGORY_INDEX];
+ }
+
+ public static String getProtocol(String[] segments) {
+ return segments[PROTOCOL_INDEX];
+ }
+
+ public static String getServiceInterface(String[] segments) {
+ return segments[SERVICE_INTERFACE_INDEX];
+ }
+
+ public static String getServiceVersion(String[] segments) {
+ return segments[SERVICE_VERSION_INDEX];
+ }
+
+ public static String getServiceGroup(String[] segments) {
+ return segments.length > 4 ? segments[SERVICE_GROUP_INDEX] : null;
+ }
+
/**
* Get the categories from {@link URL}
*
@@ -333,7 +370,8 @@ public class SpringCloudRegistry extends FailbackRegistry {
@Override
public boolean accept(ServiceInstance data) {
// TODO check the details of status
- return serviceRegistry.getStatus(new DubboRegistration(data)) != null;
+// return serviceRegistry.getStatus(new DubboRegistration(data)) != null;
+ return true;
}
});
}
diff --git a/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories
index 1df5be4d..6a2a1cd8 100644
--- a/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories
@@ -1,6 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboRestAutoConfiguration,\
+ org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration,\
- org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboRestMetadataRegistrationAutoConfiguration,\
- org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboRestDiscoveryAutoConfiguration
+ org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboRestMetadataRegistrationAutoConfiguration
diff --git a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java
index 08de6e2b..d7b3d13d 100644
--- a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java
+++ b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java
@@ -16,35 +16,27 @@
*/
package org.springframework.cloud.alibaba.dubbo.bootstrap;
-import com.alibaba.dubbo.config.ApplicationConfig;
-import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.annotation.Reference;
-import com.alibaba.dubbo.config.spring.ReferenceBean;
-import com.alibaba.dubbo.config.spring.ServiceBean;
-import com.alibaba.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.alibaba.dubbo.service.EchoService;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
-import org.springframework.context.event.EventListener;
-import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import java.util.List;
-
/**
* Dubbo Spring Cloud Bootstrap
*/
@EnableDiscoveryClient
@EnableAutoConfiguration
@EnableFeignClients
-@EnableScheduling
@RestController
public class DubboSpringCloudBootstrap {
@@ -67,38 +59,16 @@ public class DubboSpringCloudBootstrap {
String echo(@RequestParam("message") String message);
}
-// @Bean
-// public ApplicationRunner applicationRunner() {
-// return arguments -> {
-// // Dubbo Service call
-// System.out.println(echoService.echo("mercyblitz"));
-// // Spring Cloud Open Feign REST Call
-// System.out.println(feignEchoService.echo("mercyblitz"));
-// };
-// }
-
-
- @Autowired
- private ApplicationConfig applicationConfig;
-
- @Autowired
- private List registries;
-
- @EventListener(ServiceBeanExportedEvent.class)
- public void onServiceBeanExportedEvent(ServiceBeanExportedEvent event) {
- ServiceBean serviceBean = event.getServiceBean();
- ReferenceBean referenceBean = new ReferenceBean();
- referenceBean.setApplication(applicationConfig);
- referenceBean.setRegistries(registries);
- referenceBean.setInterface(serviceBean.getInterfaceClass());
- referenceBean.setInterface(serviceBean.getInterface());
- referenceBean.setVersion(serviceBean.getVersion());
- referenceBean.setGroup(serviceBean.getGroup());
- Object object = referenceBean.get();
- System.out.println(object);
+ @Bean
+ public ApplicationRunner applicationRunner() {
+ return arguments -> {
+ // Dubbo Service call
+ System.out.println(echoService.echo("mercyblitz"));
+ // Spring Cloud Open Feign REST Call
+ System.out.println(feignEchoService.echo("mercyblitz"));
+ };
}
-
public static void main(String[] args) {
new SpringApplicationBuilder(DubboSpringCloudBootstrap.class)
.run(args);