diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java index 2d04d468..89a50578 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java @@ -16,15 +16,22 @@ */ package org.springframework.cloud.alibaba.dubbo.autoconfigure; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import com.alibaba.dubbo.config.ProtocolConfig; +import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; -import org.springframework.cloud.alibaba.dubbo.service.MetadataConfigService; -import org.springframework.cloud.alibaba.dubbo.service.NacosMetadataConfigService; -import org.springframework.cloud.alibaba.nacos.NacosConfigProperties; +import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory; +import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceProxy; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import java.util.Collection; +import java.util.Iterator; + +import static com.alibaba.dubbo.common.Constants.DEFAULT_PROTOCOL; + /** * Spring Boot Auto-Configuration class for Dubbo Metadata * @@ -32,12 +39,39 @@ import org.springframework.context.annotation.Import; */ @Configuration @Import(DubboServiceMetadataRepository.class) +@DubboComponentScan(basePackages = "org.springframework.cloud.alibaba.dubbo.service") public class DubboMetadataAutoConfiguration { - @Bean - @ConditionalOnBean(NacosConfigProperties.class) - public MetadataConfigService metadataConfigService() { - return new NacosMetadataConfigService(); + public static final String METADATA_PROTOCOL_BEAN_NAME = "metadata"; + + /** + * Build an alias Bean for {@link ProtocolConfig} + * + * @param protocols {@link ProtocolConfig} Beans + * @return {@link ProtocolConfig} bean + */ + @Bean(name = METADATA_PROTOCOL_BEAN_NAME) + public ProtocolConfig protocolConfig(Collection protocols) { + ProtocolConfig protocolConfig = null; + for (ProtocolConfig protocol : protocols) { + String protocolName = protocol.getName(); + if (DEFAULT_PROTOCOL.equals(protocolName)) { + protocolConfig = protocol; + break; + } + } + + if (protocolConfig == null) { // If The ProtocolConfig bean named "dubbo" is absent, take first one of them + Iterator iterator = protocols.iterator(); + protocolConfig = iterator.hasNext() ? iterator.next() : null; + } + + return protocolConfig; } + @Bean + @ConditionalOnMissingBean + public DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy(DubboGenericServiceFactory factory) { + return new DubboMetadataConfigServiceProxy(factory); + } } \ No newline at end of file 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 8eed7a65..be821e17 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 @@ -24,17 +24,12 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.event.ApplicationStartedEvent; -import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver; -import org.springframework.cloud.alibaba.dubbo.service.MetadataConfigService; +import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService; import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.EventListener; -import java.util.LinkedHashSet; -import java.util.Set; - /** * The Auto-Configuration class for Dubbo REST metadata registration, * REST metadata that is a part of {@link Registration#getMetadata() Spring Cloud service instances' metadata} @@ -44,24 +39,17 @@ import java.util.Set; */ @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) @ConditionalOnBean(value = { - MetadataResolver.class, - MetadataConfigService.class + MetadataResolver.class }) @AutoConfigureAfter(value = {DubboMetadataAutoConfiguration.class}) @Configuration public class DubboRestMetadataRegistrationAutoConfiguration { - /** - * A Map to store REST metadata temporary, its' key is the special service name for a Dubbo service, - * the value is a JSON content of JAX-RS or Spring MVC REST metadata from the annotated methods. - */ - private final Set serviceRestMetadata = new LinkedHashSet<>(); - @Autowired private MetadataResolver metadataResolver; @Autowired - private MetadataConfigService metadataConfigService; + private PublishingDubboMetadataConfigService dubboMetadataConfigService; @Value("${spring.application.name:application}") private String currentApplicationName; @@ -69,15 +57,6 @@ public class DubboRestMetadataRegistrationAutoConfiguration { @EventListener(ServiceBeanExportedEvent.class) public void recordRestMetadata(ServiceBeanExportedEvent event) { ServiceBean serviceBean = event.getServiceBean(); - serviceRestMetadata.addAll(metadataResolver.resolveServiceRestMetadata(serviceBean)); - } - - /** - * Publish serviceRestMetadata with the JSON format into - * {@link Registration#getMetadata() service instances' metadata} when The Spring Application is started. - */ - @EventListener(ApplicationStartedEvent.class) - public void registerRestMetadata() { - metadataConfigService.publishServiceRestMetadata(currentApplicationName, serviceRestMetadata); + dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean)); } } 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 index a8b0054b..e8d21a31 100644 --- 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 @@ -16,6 +16,8 @@ */ package org.springframework.cloud.alibaba.dubbo.metadata.repository; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -23,11 +25,14 @@ import org.springframework.cloud.alibaba.dubbo.http.matcher.RequestMetadataMatch import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; -import org.springframework.cloud.alibaba.dubbo.service.MetadataConfigService; +import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigService; +import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceProxy; import org.springframework.http.HttpRequest; import org.springframework.stereotype.Repository; +import java.util.Collections; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -44,6 +49,8 @@ public class DubboServiceMetadataRepository { private final Logger logger = LoggerFactory.getLogger(getClass()); + private final ObjectMapper objectMapper = new ObjectMapper(); + /** * Key is application name * Value is Map @@ -51,7 +58,7 @@ public class DubboServiceMetadataRepository { private Map> repository = newHashMap(); @Autowired - private MetadataConfigService metadataConfigService; + private DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy; /** * Initialize the specified service's Dubbo Service Metadata @@ -64,7 +71,7 @@ public class DubboServiceMetadataRepository { return; } - Set serviceRestMetadataSet = metadataConfigService.getServiceRestMetadata(serviceName); + Set serviceRestMetadataSet = getServiceRestMetadataSet(serviceName); if (isEmpty(serviceRestMetadataSet)) { if (logger.isWarnEnabled()) { @@ -145,6 +152,23 @@ public class DubboServiceMetadataRepository { return getMap(repository, serviceName); } + private Set getServiceRestMetadataSet(String serviceName) { + DubboMetadataConfigService dubboMetadataConfigService = dubboMetadataConfigServiceProxy.newProxy(serviceName); + String serviceRestMetadataJsonConfig = dubboMetadataConfigService.getServiceRestMetadata(); + + Set metadata; + try { + metadata = objectMapper.readValue(serviceRestMetadataJsonConfig, + TypeFactory.defaultInstance().constructCollectionType(LinkedHashSet.class, ServiceRestMetadata.class)); + } catch (Exception e) { + if (logger.isErrorEnabled()) { + logger.error(e.getMessage(), e); + } + metadata = Collections.emptySet(); + } + return metadata; + } + private static Map getMap(Map> repository, String key) { return getOrDefault(repository, key, newHashMap()); } @@ -161,4 +185,5 @@ public class DubboServiceMetadataRepository { private static Map newHashMap() { return new LinkedHashMap<>(); } + } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboServiceBeanMetadataResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboServiceBeanMetadataResolver.java index 33c44716..45d53305 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboServiceBeanMetadataResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboServiceBeanMetadataResolver.java @@ -127,12 +127,22 @@ public class DubboServiceBeanMetadataResolver implements BeanClassLoaderAware, S public Set resolveMethodRestMetadata(Class targetType) { List feignContractMethods = selectFeignContractMethods(targetType); return contracts.stream() - .map(contract -> contract.parseAndValidatateMetadata(targetType)) + .map(contract -> parseAndValidateMetadata(contract, targetType)) .flatMap(v -> v.stream()) .map(methodMetadata -> resolveMethodRestMetadata(methodMetadata, targetType, feignContractMethods)) .collect(Collectors.toSet()); } + private List parseAndValidateMetadata(Contract contract, Class targetType) { + List methodMetadataList = Collections.emptyList(); + try { + methodMetadataList = contract.parseAndValidatateMetadata(targetType); + } catch (Throwable ignored) { + // ignore + } + return methodMetadataList; + } + /** * Select feign contract methods *

diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceFactory.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceFactory.java index 0c6dfc77..d5a383aa 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceFactory.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceFactory.java @@ -50,18 +50,18 @@ public class DubboGenericServiceFactory { public GenericService create(DubboServiceMetadata dubboServiceMetadata, DubboTransportedMetadata dubboTransportedMetadata) { - Integer key = Objects.hash(dubboServiceMetadata, dubboTransportedMetadata); - - ReferenceBean referenceBean = cache.get(key); - - if (referenceBean == null) { - referenceBean = build(dubboServiceMetadata.getServiceRestMetadata(), dubboTransportedMetadata); - cache.putIfAbsent(key, referenceBean); - } + ReferenceBean referenceBean = build(dubboServiceMetadata.getServiceRestMetadata(), dubboTransportedMetadata); return referenceBean == null ? null : referenceBean.get(); } + public GenericService create(String serviceName, Class serviceClass) { + String interfaceName = serviceClass.getName(); + ReferenceBean referenceBean = build(interfaceName, serviceName, null, + "dubbo", "failover"); + return referenceBean.get(); + } + private ReferenceBean build(ServiceRestMetadata serviceRestMetadata, DubboTransportedMetadata dubboTransportedMetadata) { @@ -70,14 +70,28 @@ public class DubboGenericServiceFactory { String interfaceName = getServiceInterface(segments); String version = getServiceVersion(segments); String group = getServiceGroup(segments); + String protocol = dubboTransportedMetadata.getProtocol(); + String cluster = dubboTransportedMetadata.getCluster(); - ReferenceBean referenceBean = new ReferenceBean(); - referenceBean.setGeneric(true); - referenceBean.setInterface(interfaceName); - referenceBean.setVersion(version); - referenceBean.setGroup(group); - referenceBean.setProtocol(dubboTransportedMetadata.getProtocol()); - referenceBean.setCluster(dubboTransportedMetadata.getCluster()); + return build(interfaceName, version, group, protocol, cluster); + } + + private ReferenceBean build(String interfaceName, String version, String group, String protocol, + String cluster) { + + Integer key = Objects.hash(interfaceName, version, group, protocol, cluster); + + ReferenceBean referenceBean = cache.get(key); + + if (referenceBean == null) { + referenceBean = new ReferenceBean<>(); + referenceBean.setGeneric(true); + referenceBean.setInterface(interfaceName); + referenceBean.setVersion(version); + referenceBean.setGroup(group); + referenceBean.setProtocol(protocol); + referenceBean.setCluster(cluster); + } return referenceBean; } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/MetadataConfigService.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigService.java similarity index 80% rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/MetadataConfigService.java rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigService.java index 734050a2..b8443fb0 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/MetadataConfigService.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigService.java @@ -21,13 +21,16 @@ import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; import java.util.Set; /** - * Config Service for Metadata + * Dubbo Metadata Configuration Service * * @author Mercy */ -public interface MetadataConfigService { +public interface DubboMetadataConfigService { - void publishServiceRestMetadata(String serviceName, Set serviceRestMetadata); - - Set getServiceRestMetadata(String serviceName); + /** + * Get The json content of {@link ServiceRestMetadata} {@link Set} + * + * @return the non-null String + */ + String getServiceRestMetadata(); } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigServiceInvocationHandler.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigServiceInvocationHandler.java new file mode 100644 index 00000000..94014d77 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigServiceInvocationHandler.java @@ -0,0 +1,54 @@ +/* + * 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.service; + +import com.alibaba.dubbo.rpc.service.GenericService; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * {@link DubboMetadataConfigService} {@link InvocationHandler} + * + * @author Mercy + */ +class DubboMetadataConfigServiceInvocationHandler implements InvocationHandler { + + /** + * The method name of {@link DubboMetadataConfigService#getServiceRestMetadata()} + */ + private static final String METHOD_NAME = "getServiceRestMetadata"; + + private static final String[] PARAMETER_TYPES = new String[0]; + + private static final String[] PARAMETER_VALUES = new String[0]; + + private final GenericService genericService; + + public DubboMetadataConfigServiceInvocationHandler(String serviceName, DubboGenericServiceFactory dubboGenericServiceFactory) { + this.genericService = dubboGenericServiceFactory.create(serviceName, DubboMetadataConfigService.class); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String methodName = method.getName(); + if (METHOD_NAME.equals(methodName)) { + return genericService.$invoke(methodName, PARAMETER_TYPES, PARAMETER_VALUES); + } + return method.invoke(proxy, args); + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigServiceProxy.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigServiceProxy.java new file mode 100644 index 00000000..8db49572 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboMetadataConfigServiceProxy.java @@ -0,0 +1,51 @@ +/* + * 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.service; + +import org.springframework.beans.factory.BeanClassLoaderAware; + +import static java.lang.reflect.Proxy.newProxyInstance; + +/** + * The proxy of {@link DubboMetadataConfigService} + */ +public class DubboMetadataConfigServiceProxy implements BeanClassLoaderAware { + + private final DubboGenericServiceFactory dubboGenericServiceFactory; + + private ClassLoader classLoader; + + public DubboMetadataConfigServiceProxy(DubboGenericServiceFactory dubboGenericServiceFactory) { + this.dubboGenericServiceFactory = dubboGenericServiceFactory; + } + + /** + * New proxy instance of {@link DubboMetadataConfigService} via the specified service name + * + * @param serviceName the service name + * @return a {@link DubboMetadataConfigService} proxy + */ + public DubboMetadataConfigService newProxy(String serviceName) { + return (DubboMetadataConfigService) newProxyInstance(classLoader, new Class[]{DubboMetadataConfigService.class}, + new DubboMetadataConfigServiceInvocationHandler(serviceName, dubboGenericServiceFactory)); + } + + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/NacosMetadataConfigService.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/NacosMetadataConfigService.java deleted file mode 100644 index 13baee0d..00000000 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/NacosMetadataConfigService.java +++ /dev/null @@ -1,98 +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.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; - -/** - * Nacos {@link MetadataConfigService} - * - * @author Mercy - */ -public class NacosMetadataConfigService implements MetadataConfigService { - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Autowired - private NacosConfigProperties nacosConfigProperties; - - private ConfigService configService; - - @PostConstruct - public void init() { - this.configService = nacosConfigProperties.configServiceInstance(); - this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT); - } - - /** - * Get the data Id of service rest metadata - */ - private static String getServiceRestMetadataDataId(String serviceName) { - return "metadata:rest:" + serviceName + ".json"; - } - - @Override - public void publishServiceRestMetadata(String serviceName, Set serviceRestMetadata) { - String dataId = getServiceRestMetadataDataId(serviceName); - String json = writeValueAsString(serviceRestMetadata); - try { - configService.publishConfig(dataId, DEFAULT_GROUP, json); - } catch (NacosException e) { - throw new RuntimeException(e); - } - } - - @Override - public Set getServiceRestMetadata(String serviceName) { - Set metadata = Collections.emptySet(); - String dataId = getServiceRestMetadataDataId(serviceName); - 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/service/PublishingDubboMetadataConfigService.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/PublishingDubboMetadataConfigService.java new file mode 100644 index 00000000..799e7caa --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/PublishingDubboMetadataConfigService.java @@ -0,0 +1,78 @@ +/* + * 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.service; + +import com.alibaba.dubbo.config.annotation.Service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PostConstruct; +import java.util.LinkedHashSet; +import java.util.Set; + +import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration.METADATA_PROTOCOL_BEAN_NAME; + +/** + * Publishing {@link DubboMetadataConfigService} implementation + * + * @author Mercy + */ +@Service(version = "${spring.application.name}", protocol = METADATA_PROTOCOL_BEAN_NAME) +// Use current Spring application name as the Dubbo Service version +public class PublishingDubboMetadataConfigService implements DubboMetadataConfigService { + + /** + * A Map to store REST metadata temporary, its' key is the special service name for a Dubbo service, + * the value is a JSON content of JAX-RS or Spring MVC REST metadata from the annotated methods. + */ + private final Set serviceRestMetadata = new LinkedHashSet<>(); + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @PostConstruct + public void init() { + this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + } + + /** + * Publish the {@link Set} of {@link ServiceRestMetadata} + * + * @param serviceRestMetadataSet the {@link Set} of {@link ServiceRestMetadata} + */ + public void publishServiceRestMetadata(Set serviceRestMetadataSet) { + for (ServiceRestMetadata serviceRestMetadata : serviceRestMetadataSet) { + if (!CollectionUtils.isEmpty(serviceRestMetadata.getMeta())) { + this.serviceRestMetadata.add(serviceRestMetadata); + } + } + } + + @Override + public String getServiceRestMetadata() { + String serviceRestMetadataJsonConfig = null; + try { + serviceRestMetadataJsonConfig = objectMapper.writeValueAsString(serviceRestMetadata); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + return serviceRestMetadataJsonConfig; + } +}