diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java similarity index 61% rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestAutoConfiguration.java rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java index c325e96e..d5db05ea 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java @@ -16,34 +16,31 @@ */ package org.springframework.cloud.alibaba.dubbo.autoconfigure; -import com.fasterxml.jackson.databind.ObjectMapper; -import feign.Contract; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfigureOrder; -import org.springframework.cloud.alibaba.dubbo.rest.feign.FeignRestMetadataResolver; -import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataConfigService; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; +import org.springframework.cloud.alibaba.dubbo.metadata.service.MetadataConfigService; +import org.springframework.cloud.alibaba.dubbo.metadata.service.NacosMetadataConfigService; +import org.springframework.cloud.alibaba.nacos.NacosConfigProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.core.Ordered; /** - * Spring Boot Auto-Configuration class for Dubbo REST + * Spring Boot Auto-Configuration class for Dubbo Metadata * * @author Mercy */ @Configuration +@Import(DubboServiceMetadataRepository.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) -public class DubboRestAutoConfiguration { +public class DubboMetadataAutoConfiguration { @Bean - public FeignRestMetadataResolver metadataJsonResolver( - ObjectProvider objectMapper, ObjectProvider contract) { - return new FeignRestMetadataResolver(objectMapper, contract); - } - - @Bean - public RestMetadataConfigService restMetadataConfigService() { - return new RestMetadataConfigService(); + @ConditionalOnBean(NacosConfigProperties.class) + public MetadataConfigService metadataConfigService() { + return new NacosMetadataConfigService(); } } \ No newline at end of file diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java index 877d2ccd..d37d8dc0 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java @@ -16,28 +16,20 @@ */ package org.springframework.cloud.alibaba.dubbo.autoconfigure; +import feign.Contract; import feign.Feign; -import feign.RequestInterceptor; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.alibaba.dubbo.metadata.resolver.FeignMetadataResolver; +import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver; import org.springframework.cloud.alibaba.dubbo.openfeign.DubboFeignClientsConfiguration; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.FeignAutoConfiguration; -import org.springframework.cloud.openfeign.FeignContext; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.event.EventListener; - -import java.util.LinkedHashSet; -import java.util.Set; - -import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration.FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME; /** @@ -45,52 +37,18 @@ import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFei * * @author Mercy */ -@ConditionalOnClass(value = Feign.class, name = FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME) -@EnableFeignClients(defaultConfiguration = DubboFeignClientsConfiguration.class) +@ConditionalOnClass(value = Feign.class) @AutoConfigureAfter(FeignAutoConfiguration.class) +@EnableFeignClients(defaultConfiguration = DubboFeignClientsConfiguration.class) @Configuration public class DubboOpenFeignAutoConfiguration { - static final String FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME = - "org.springframework.cloud.openfeign.FeignClientFactoryBean"; - - @Autowired - private ObjectProvider feignContextObjectProvider; - - @EventListener(ApplicationReadyEvent.class) - public void onApplicationReady(ApplicationReadyEvent event) { - ConfigurableApplicationContext applicationContext = event.getApplicationContext(); - // Resolve the subscribed service names for @FeignClient - Set feignClientServiceNames = resolveFeignClientServiceNames(applicationContext); - // FeignContext - FeignContext feignContext = feignContextObjectProvider.getIfAvailable(); - - } - - /** - * Resolve the subscribed service names for @FeignClient - * - * @param applicationContext Current {@link ConfigurableApplicationContext} - * @return non-null {@link Set} - */ - private Set resolveFeignClientServiceNames(ConfigurableApplicationContext applicationContext) { - Set feignClientServiceNames = new LinkedHashSet<>(); - ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); - for (String beanName : beanFactory.getBeanDefinitionNames()) { - BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); - if (FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME.equals(beanDefinition.getBeanClassName())) { - String feignClientServiceName = (String) beanDefinition.getPropertyValues().get("name"); - feignClientServiceNames.add(feignClientServiceName); - } - } - return feignClientServiceNames; - } + @Value("${spring.application.name}") + private String currentApplicationName; @Bean - public RequestInterceptor requestInterceptor() { - return template -> { - System.out.println(template); - }; + @ConditionalOnMissingBean + public MetadataResolver metadataJsonResolver(ObjectProvider contract) { + return new FeignMetadataResolver(currentApplicationName, contract); } - -} +} \ No newline at end of file diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestDiscoveryAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestDiscoveryAutoConfiguration.java deleted file mode 100644 index 0dcfdec1..00000000 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestDiscoveryAutoConfiguration.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * 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.autoconfigure; - -import com.alibaba.boot.dubbo.autoconfigure.DubboAutoConfiguration; -import com.alibaba.dubbo.config.ApplicationConfig; -import com.alibaba.dubbo.config.RegistryConfig; -import com.alibaba.dubbo.config.spring.ReferenceBean; -import com.fasterxml.jackson.databind.ObjectMapper; -import feign.Client; -import feign.Request; -import feign.Response; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataConfigService; -import org.springframework.cloud.alibaba.dubbo.rest.feign.FeignRestMetadataResolver; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.StringUtils; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -/** - * The Auto-Configuration class for Dubbo REST Discovery - * - * @author Mercy - */ -@ConditionalOnProperty(value = "spring.cloud.config.discovery.enabled", matchIfMissing = true) -@AutoConfigureAfter(value = { - DubboAutoConfiguration.class, - DubboRestAutoConfiguration.class, - DubboRestMetadataRegistrationAutoConfiguration.class}) -@Configuration -public class DubboRestDiscoveryAutoConfiguration { - - private static final String FEIGN_CLIENT_FACTORY_BEAN_CLASS_NAME = - "org.springframework.cloud.openfeign.FeignClientFactoryBean"; - - @Autowired - private DiscoveryClient discoveryClient; - - @Autowired - private FeignRestMetadataResolver feignRestMetadataResolver; - - @Autowired(required = false) - private ObjectMapper objectMapper = new ObjectMapper(); - - /** - * Feign Request -> Dubbo ReferenceBean - */ - private Map referenceBeanCache = new HashMap<>(); - - @Autowired - private ApplicationConfig applicationConfig; - - @Value("${spring.application.name}") - private String applicationName; - - @Value("${spring.cloud.nacos.discovery.server-addr}") - private String nacosServerAddress; - - @Autowired - private RestMetadataConfigService restMetadataConfigService; - - private ReferenceBean buildReferenceBean(String dubboServiceName) { - ReferenceBean referenceBean = new ReferenceBean(); - applicationConfig.setName("service-consumer"); - referenceBean.setApplication(applicationConfig); - RegistryConfig registryConfig = new RegistryConfig(); - // requires dubbo-registry-nacos - registryConfig.setAddress("nacos://" + nacosServerAddress); - referenceBean.setRegistry(registryConfig); - String[] parts = StringUtils.delimitedListToStringArray(dubboServiceName, ":"); - referenceBean.setInterface(parts[1]); - referenceBean.setVersion(parts[2]); - referenceBean.setGroup(parts.length > 3 ? parts[3] : null); - referenceBean.get(); - return referenceBean; - } - - @Bean - public BeanPostProcessor wrapClientBeanPostProcessor() { - return new BeanPostProcessor() { - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof Client) { - Client client = (Client) bean; - // wrapper - return new DubboFeignClientProxy(client); - } - return bean; - } - }; - } - - class DubboFeignClientProxy implements Client { - - private final Client delegate; - - DubboFeignClientProxy(Client delegate) { - this.delegate = delegate; - } - - @Override - public Response execute(Request request, Request.Options options) throws IOException { - - ReferenceBean referenceBean = referenceBeanCache.get(request.toString()); - - if (referenceBean != null) { - Object dubboClient = referenceBean.get(); - Method method = null; - Object[] params = null; - - try { - Object result = method.invoke(dubboClient, params); - // wrapper as a Response - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - - return delegate.execute(request, options); - } - - } - -} - - -// private Method getRegistrationMethod; -// -// @PostConstruct -// public void init() throws NoSuchMethodException { -// getRegistrationMethod = initGetRegistrationMethod(); -// } -// -// /** -// * Initializes {@link AbstractAutoServiceRegistration#getRegistration() getRegistration method} that is is protected. -// * -// * @return {@link Method} -// * @throws NoSuchMethodException -// */ -// private Method initGetRegistrationMethod() throws NoSuchMethodException { -// Method method = AbstractAutoServiceRegistration.class.getDeclaredMethod("getRegistration"); -// method.setAccessible(true); -// return method; -// } -// -// private Registration getRegistration(AbstractAutoServiceRegistration source) { -// return (Registration) ReflectionUtils.invokeMethod(getRegistrationMethod, source); -// } -// -// private void noop() { -// Map specifications = -// beanFactory.getBeansOfType(NamedContextFactory.Specification.class); -// // 1. Get all service names from Spring beans that was annotated by @FeignClient -// List serviceNames = new LinkedList<>(); -// -// specifications.forEach((beanName, specification) -> -// -// { -// String serviceName = beanName.substring(0, beanName.indexOf(".")); -// serviceNames.add(serviceName); -// -// // 2. Get all service instances by echo specified service name -// List serviceInstances = discoveryClient.getInstances(serviceName); -// if (!serviceInstances.isEmpty()) { -// ServiceInstance serviceInstance = serviceInstances.get(0); -// // 3. Get Rest metadata from service instance -// Map metadata = serviceInstance.getMetadata(); -// // 4. Resolve REST metadata from the @FeignClient instance -// String restMetadataJson = metadata.get("restMetadata"); -// /** -// * { -// * "providers:org.springframework.cloud.alibaba.dubbo.service.EchoService:1.0.0": [ -// * "{\"method\":\"POST\",\"url\":\"/plus?a={a}&b={b}\",\"headers\":{}}", -// * "{\"method\":\"GET\",\"url\":\"/echo?message={message}\",\"headers\":{}}" -// * ] -// * } -// */ -// try { -// Map> restMetadata = objectMapper.readValue(restMetadataJson, Map.class); -// -// restMetadata.forEach((dubboServiceName, restJsons) -> { -// restJsons.stream().map(feignRestMetadataResolver::resolveRequest).forEach(request -> { -// referenceBeanCache.put(request.toString(), buildReferenceBean(dubboServiceName)); -// }); -// }); -// -// } catch (IOException e) { -// throw new RuntimeException(e); -// } -// -// // -// } -// }); -// } -// -// private ReferenceBean buildReferenceBean(ServiceInstance serviceInstance) { -// -// ReferenceBean referenceBean = new ReferenceBean(); -// Map metadata = serviceInstance.getMetadata(); -// // 4. Resolve REST metadata from the @FeignClient instance -// String restMetadataJson = metadata.get("restMetadata"); -// -// try { -// Map> restMetadata = objectMapper.readValue(restMetadataJson, Map.class); -// -// restMetadata.forEach((dubboServiceName, restJsons) -> { -// restJsons.stream().map(feignRestMetadataResolver::resolveRequest).forEach(request -> { -// referenceBeanCache.put(request.toString(), buildReferenceBean(dubboServiceName)); -// }); -// }); -// -// } catch (IOException e) { -// throw new RuntimeException(e); -// } -// -// return referenceBean; -// } - -// /** -// * Handle on self instance registered. -// * -// * @param event {@link InstanceRegisteredEvent} -// */ -// @EventListener(InstanceRegisteredEvent.class) -// public void onSelfInstanceRegistered(InstanceRegisteredEvent event) throws Exception { -// -// Class targetClass = AbstractAutoServiceRegistration.class; -// -// Object source = event.getSource(); -// -// Assert.isInstanceOf(targetClass, source, -// format("The source of %s must implement %s", source, targetClass.getName())); -// -// Registration registration = getRegistration((AbstractAutoServiceRegistration) source); -// -// String serviceRestMetaDataConfig = -// restMetadataConfigService.getServiceRestMetadata(registration.getServiceId()); -// -// Set serviceRestMetadata = objectMapper.readValue(serviceRestMetaDataConfig, -// TypeFactory.defaultInstance().constructCollectionType(Set.class, ServiceRestMetadata.class)); -// -// } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestMetadataRegistrationAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestMetadataRegistrationAutoConfiguration.java index 1179cb0f..458b1ca1 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestMetadataRegistrationAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboRestMetadataRegistrationAutoConfiguration.java @@ -19,13 +19,13 @@ package org.springframework.cloud.alibaba.dubbo.autoconfigure; import com.alibaba.dubbo.config.spring.ServiceBean; import com.alibaba.dubbo.config.spring.context.event.ServiceBeanExportedEvent; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.alibaba.dubbo.rest.feign.FeignRestMetadataResolver; -import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataConfigService; -import org.springframework.cloud.alibaba.dubbo.rest.metadata.ServiceRestMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver; +import org.springframework.cloud.alibaba.dubbo.metadata.service.MetadataConfigService; import org.springframework.cloud.client.discovery.event.InstancePreRegisteredEvent; import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.context.annotation.Configuration; @@ -42,8 +42,14 @@ import java.util.Set; * @author Mercy */ @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) +@ConditionalOnMissingBean(value = { + MetadataResolver.class, + MetadataConfigService.class +}) @AutoConfigureAfter(value = { - DubboRestAutoConfiguration.class, DubboServiceRegistrationAutoConfiguration.class}) + DubboMetadataAutoConfiguration.class, + DubboServiceRegistrationAutoConfiguration.class +}) @Configuration public class DubboRestMetadataRegistrationAutoConfiguration { @@ -54,19 +60,15 @@ public class DubboRestMetadataRegistrationAutoConfiguration { private final Set serviceRestMetadata = new LinkedHashSet<>(); @Autowired - private ObjectMapper objectMapper; + private MetadataResolver metadataResolver; @Autowired - private FeignRestMetadataResolver feignRestMetadataResolver; - - @Autowired - private RestMetadataConfigService metadataConfigService; - + private MetadataConfigService metadataConfigService; @EventListener(ServiceBeanExportedEvent.class) public void recordRestMetadata(ServiceBeanExportedEvent event) throws JsonProcessingException { ServiceBean serviceBean = event.getServiceBean(); - serviceRestMetadata.addAll(feignRestMetadataResolver.resolveServiceRestMetadata(serviceBean)); + serviceRestMetadata.addAll(metadataResolver.resolveServiceRestMetadata(serviceBean)); } /** @@ -81,11 +83,7 @@ public class DubboRestMetadataRegistrationAutoConfiguration { @EventListener(InstancePreRegisteredEvent.class) public void registerRestMetadata(InstancePreRegisteredEvent event) throws Exception { Registration registration = event.getRegistration(); - - String restMetadataJson = objectMapper.writeValueAsString(serviceRestMetadata); - - metadataConfigService.publishServiceRestMetadata(registration.getServiceId(), restMetadataJson); - + metadataConfigService.publishServiceRestMetadata(registration.getServiceId(), serviceRestMetadata); } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodMetadata.java new file mode 100644 index 00000000..18abf0e9 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodMetadata.java @@ -0,0 +1,122 @@ +/* + * 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; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.apache.commons.lang3.ClassUtils; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +/** + * {@link Method} Metadata + * + * @author Mercy + */ +public class MethodMetadata { + + private String name; + + private String returnType; + + private List params; + + @JsonIgnore + private Method method; + + public MethodMetadata() { + this.params = new LinkedList<>(); + } + + public MethodMetadata(Method method) { + this.name = method.getName(); + this.returnType = ClassUtils.getName(method.getReturnType()); + this.params = initParameters(method); + this.method = method; + } + + private List initParameters(Method method) { + int parameterCount = method.getParameterCount(); + if (parameterCount < 1) { + return Collections.emptyList(); + } + List params = new ArrayList<>(parameterCount); + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameterCount; i++) { + Parameter parameter = parameters[i]; + MethodParameterMetadata param = toMethodParameterMetadata(i, parameter); + params.add(param); + } + return params; + } + + private MethodParameterMetadata toMethodParameterMetadata(int index, Parameter parameter) { + MethodParameterMetadata metadata = new MethodParameterMetadata(); + metadata.setIndex(index); + metadata.setName(parameter.getName()); + metadata.setType(parameter.getType().getTypeName()); + return metadata; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getReturnType() { + return returnType; + } + + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + + public Method getMethod() { + return method; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MethodMetadata that = (MethodMetadata) o; + return Objects.equals(name, that.name) && + Objects.equals(returnType, that.returnType) && + Objects.equals(params, that.params); + } + + @Override + public int hashCode() { + return Objects.hash(name, returnType, params); + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodParameterMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodParameterMetadata.java new file mode 100644 index 00000000..fbcaad00 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodParameterMetadata.java @@ -0,0 +1,73 @@ +/* + * 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; + +import java.lang.reflect.Method; +import java.util.Objects; + +/** + * {@link Method} Parameter Metadata + * + * @author Mercy + */ +public class MethodParameterMetadata { + + private int index; + + private String name; + + private String type; + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MethodParameterMetadata that = (MethodParameterMetadata) o; + return index == that.index && + Objects.equals(name, that.name) && + Objects.equals(type, that.type); + } + + @Override + public int hashCode() { + return Objects.hash(index, name, type); + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/metadata/MethodRestMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RequestMetadata.java similarity index 53% rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/metadata/MethodRestMetadata.java rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RequestMetadata.java index ad8d9db9..ae3d10dc 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/metadata/MethodRestMetadata.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RequestMetadata.java @@ -14,32 +14,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.alibaba.dubbo.rest.metadata; +package org.springframework.cloud.alibaba.dubbo.metadata; + +import feign.RequestTemplate; import java.util.Collection; import java.util.Map; +import java.util.Objects; /** - * TODO + * Request Metadata + * + * @author Mercy */ -public class MethodRestMetadata { - - private String configKey; +public class RequestMetadata { private String method; private String url; + private Map> queries; + private Map> headers; - private Map> indexToName; - - public String getConfigKey() { - return configKey; + public RequestMetadata() { } - public void setConfigKey(String configKey) { - this.configKey = configKey; + public RequestMetadata(RequestTemplate requestTemplate) { + this.method = requestTemplate.method(); + this.url = requestTemplate.url(); + this.queries = requestTemplate.queries(); + this.headers = requestTemplate.headers(); } public String getMethod() { @@ -66,35 +71,27 @@ public class MethodRestMetadata { this.headers = headers; } - public Map> getIndexToName() { - return indexToName; + public Map> getQueries() { + return queries; } - public void setIndexToName(Map> indexToName) { - this.indexToName = indexToName; + public void setQueries(Map> queries) { + this.queries = queries; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - - MethodRestMetadata that = (MethodRestMetadata) o; - - if (configKey != null ? !configKey.equals(that.configKey) : that.configKey != null) return false; - if (method != null ? !method.equals(that.method) : that.method != null) return false; - if (url != null ? !url.equals(that.url) : that.url != null) return false; - if (headers != null ? !headers.equals(that.headers) : that.headers != null) return false; - return indexToName != null ? indexToName.equals(that.indexToName) : that.indexToName == null; + RequestMetadata that = (RequestMetadata) o; + return Objects.equals(method, that.method) && + Objects.equals(url, that.url) && + Objects.equals(queries, that.queries) && + Objects.equals(headers, that.headers); } @Override public int hashCode() { - int result = configKey != null ? configKey.hashCode() : 0; - result = 31 * result + (method != null ? method.hashCode() : 0); - result = 31 * result + (url != null ? url.hashCode() : 0); - result = 31 * result + (headers != null ? headers.hashCode() : 0); - result = 31 * result + (indexToName != null ? indexToName.hashCode() : 0); - return result; + return Objects.hash(method, url, queries, headers); } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java new file mode 100644 index 00000000..5024fefa --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java @@ -0,0 +1,72 @@ +/* + * 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; + +import java.util.Collection; +import java.util.Map; +import java.util.Objects; + +/** + * Method Request Metadata + */ +public class RestMethodMetadata { + + private MethodMetadata method; + + private RequestMetadata request; + + private Map> indexToName; + + public MethodMetadata getMethod() { + return method; + } + + public void setMethod(MethodMetadata method) { + this.method = method; + } + + public RequestMetadata getRequest() { + return request; + } + + public void setRequest(RequestMetadata request) { + this.request = request; + } + + public Map> getIndexToName() { + return indexToName; + } + + public void setIndexToName(Map> indexToName) { + this.indexToName = indexToName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RestMethodMetadata that = (RestMethodMetadata) o; + return Objects.equals(method, that.method) && + Objects.equals(request, that.request) && + Objects.equals(indexToName, that.indexToName); + } + + @Override + public int hashCode() { + return Objects.hash(method, request, indexToName); + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/metadata/ServiceRestMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/ServiceRestMetadata.java similarity index 84% rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/metadata/ServiceRestMetadata.java rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/ServiceRestMetadata.java index 6b93302f..d5ba11f4 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/metadata/ServiceRestMetadata.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/ServiceRestMetadata.java @@ -14,18 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.cloud.alibaba.dubbo.rest.metadata; +package org.springframework.cloud.alibaba.dubbo.metadata; import java.util.Set; /** - * TODO + * Service Rest Metadata + * + * @author Mercy + * @see RestMethodMetadata */ public class ServiceRestMetadata { private String name; - private Set meta; + private Set meta; public String getName() { return name; @@ -35,11 +38,11 @@ public class ServiceRestMetadata { this.name = name; } - public Set getMeta() { + public Set getMeta() { return meta; } - public void setMeta(Set meta) { + public void setMeta(Set meta) { this.meta = meta; } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java new file mode 100644 index 00000000..57a0a133 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -0,0 +1,118 @@ +/* + * 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.repository; + +import com.alibaba.dubbo.config.spring.ReferenceBean; +import com.alibaba.dubbo.rpc.service.GenericService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.service.MetadataConfigService; +import org.springframework.stereotype.Repository; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceGroup; +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceInterface; +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceSegments; +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceVersion; + +/** + * Dubbo Service Metadata {@link Repository} + * + * @author Mercy + */ +@Repository +public class DubboServiceMetadataRepository { + + /** + * Key is application name + * Value is Map + */ + private Map> genericServicesRepository = new HashMap<>(); + + private Map> methodMetadataRepository = new HashMap<>(); + + @Autowired + private MetadataConfigService metadataConfigService; + + @Value("${dubbo.target.protocol:dubbo}") + private String targetProtocol; + + @Value("${dubbo.target.cluster:failover}") + private String targetCluster; + + public void updateMetadata(String serviceName) { + + Map genericServicesMap = genericServicesRepository.computeIfAbsent(serviceName, k -> new HashMap<>()); + + Map methodMetadataMap = methodMetadataRepository.computeIfAbsent(serviceName, k -> new HashMap<>()); + + Set serviceRestMetadataSet = metadataConfigService.getServiceRestMetadata(serviceName); + + for (ServiceRestMetadata serviceRestMetadata : serviceRestMetadataSet) { + + ReferenceBean referenceBean = adaptReferenceBean(serviceRestMetadata); + + serviceRestMetadata.getMeta().forEach(restMethodMetadata -> { + RequestMetadata requestMetadata = restMethodMetadata.getRequest(); + genericServicesMap.put(requestMetadata, referenceBean.get()); + methodMetadataMap.put(requestMetadata, restMethodMetadata.getMethod()); + }); + } + } + + public GenericService getGenericService(String serviceName, RequestMetadata requestMetadata) { + return getGenericServicesMap(serviceName).get(requestMetadata); + } + + public MethodMetadata getMethodMetadata(String serviceName, RequestMetadata requestMetadata) { + return getMethodMetadataMap(serviceName).get(requestMetadata); + } + + private ReferenceBean adaptReferenceBean(ServiceRestMetadata serviceRestMetadata) { + String dubboServiceName = serviceRestMetadata.getName(); + String[] segments = getServiceSegments(dubboServiceName); + String interfaceName = getServiceInterface(segments); + String version = getServiceVersion(segments); + String group = getServiceGroup(segments); + + ReferenceBean referenceBean = new ReferenceBean(); + referenceBean.setGeneric(true); + referenceBean.setInterface(interfaceName); + referenceBean.setVersion(version); + referenceBean.setGroup(group); + referenceBean.setProtocol(targetProtocol); + referenceBean.setCluster(targetCluster); + + return referenceBean; + } + + private Map getGenericServicesMap(String serviceName) { + return genericServicesRepository.getOrDefault(serviceName, Collections.emptyMap()); + } + + private Map getMethodMetadataMap(String serviceName) { + return methodMetadataRepository.getOrDefault(serviceName, Collections.emptyMap()); + } + +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/feign/FeignRestMetadataResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/FeignMetadataResolver.java similarity index 53% rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/feign/FeignRestMetadataResolver.java rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/FeignMetadataResolver.java index e2588c50..e7f80dd4 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/rest/feign/FeignRestMetadataResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/FeignMetadataResolver.java @@ -14,73 +14,60 @@ * 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.resolver; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.config.spring.ServiceBean; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import feign.Contract; +import feign.Feign; import feign.MethodMetadata; -import feign.Request; -import feign.RequestTemplate; -import feign.jaxrs2.JAXRS2Contract; -import org.apache.commons.lang3.StringUtils; +import feign.Util; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.SmartInitializingSingleton; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; import org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry; -import org.springframework.cloud.alibaba.dubbo.rest.metadata.MethodRestMetadata; -import org.springframework.cloud.alibaba.dubbo.rest.metadata.ServiceRestMetadata; -import org.springframework.cloud.openfeign.support.SpringMvcContract; import org.springframework.util.ClassUtils; -import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; /** - * The REST metadata resolver for Feign + * The metadata resolver for {@link Feign} * * @author Mercy */ -public class FeignRestMetadataResolver implements BeanClassLoaderAware, SmartInitializingSingleton { - - private static final String METHOD_PROPERTY_NAME = "method"; - private static final String URL_PROPERTY_NAME = "url"; - private static final String HEADERS_PROPERTY_NAME = "headers"; +public class FeignMetadataResolver implements BeanClassLoaderAware, SmartInitializingSingleton, MetadataResolver { private static final String[] CONTRACT_CLASS_NAMES = { "feign.jaxrs2.JAXRS2Contract", "org.springframework.cloud.openfeign.support.SpringMvcContract", }; - private final ObjectMapper objectMapper; + private final String currentApplicationName; private final ObjectProvider contract; + private ClassLoader classLoader; + /** * Feign Contracts */ private Collection contracts; - private ClassLoader classLoader; - - @Value("${spring.application.name}") - private String currentApplicationName; - - public FeignRestMetadataResolver(ObjectProvider objectMapper, ObjectProvider contract) { - this.objectMapper = objectMapper.getIfAvailable(); + public FeignMetadataResolver(String currentApplicationName, ObjectProvider contract) { + this.currentApplicationName = currentApplicationName; this.contract = contract; } @@ -113,17 +100,16 @@ public class FeignRestMetadataResolver implements BeanClassLoaderAware, SmartIni return ClassUtils.isPresent(className, classLoader); } + @Override public Set resolveServiceRestMetadata(ServiceBean serviceBean) { Object bean = serviceBean.getRef(); Class beanType = bean.getClass(); - Class interfaceClass = serviceBean.getInterfaceClass(); - Set serviceRestMetadata = new LinkedHashSet<>(); - Set methodRestMetadata = resolveMethodRestMetadata(beanType, interfaceClass); + Set methodRestMetadata = resolveMethodRestMetadata(beanType); List urls = serviceBean.getExportedUrls(); @@ -139,65 +125,61 @@ public class FeignRestMetadataResolver implements BeanClassLoaderAware, SmartIni return serviceRestMetadata; } - public Set resolveMethodRestMetadata(Class targetClass) { - return resolveMethodRestMetadata(targetClass, targetClass); - } - - protected Set resolveMethodRestMetadata(Class targetClass, Class revisedClass) { + @Override + public Set resolveMethodRestMetadata(Class targetType) { + List 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);