mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Polish spring-cloud-incubator/spring-cloud-alibaba#376 : Dubbo Metadata Configuration replaces Nacos 's implementation
This commit is contained in:
parent
80252f8278
commit
918e052cd6
@ -16,15 +16,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
|
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.metadata.repository.DubboServiceMetadataRepository;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.MetadataConfigService;
|
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
|
||||||
import org.springframework.cloud.alibaba.dubbo.service.NacosMetadataConfigService;
|
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceProxy;
|
||||||
import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
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
|
* Spring Boot Auto-Configuration class for Dubbo Metadata
|
||||||
*
|
*
|
||||||
@ -32,12 +39,39 @@ import org.springframework.context.annotation.Import;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(DubboServiceMetadataRepository.class)
|
@Import(DubboServiceMetadataRepository.class)
|
||||||
|
@DubboComponentScan(basePackages = "org.springframework.cloud.alibaba.dubbo.service")
|
||||||
public class DubboMetadataAutoConfiguration {
|
public class DubboMetadataAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
public static final String METADATA_PROTOCOL_BEAN_NAME = "metadata";
|
||||||
@ConditionalOnBean(NacosConfigProperties.class)
|
|
||||||
public MetadataConfigService metadataConfigService() {
|
/**
|
||||||
return new NacosMetadataConfigService();
|
* 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<ProtocolConfig> 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<ProtocolConfig> iterator = protocols.iterator();
|
||||||
|
protocolConfig = iterator.hasNext() ? iterator.next() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return protocolConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy(DubboGenericServiceFactory factory) {
|
||||||
|
return new DubboMetadataConfigServiceProxy(factory);
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,17 +24,12 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
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.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.cloud.client.serviceregistry.Registration;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Auto-Configuration class for Dubbo REST metadata registration,
|
* The Auto-Configuration class for Dubbo REST metadata registration,
|
||||||
* REST metadata that is a part of {@link Registration#getMetadata() Spring Cloud service instances' metadata}
|
* 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)
|
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
|
||||||
@ConditionalOnBean(value = {
|
@ConditionalOnBean(value = {
|
||||||
MetadataResolver.class,
|
MetadataResolver.class
|
||||||
MetadataConfigService.class
|
|
||||||
})
|
})
|
||||||
@AutoConfigureAfter(value = {DubboMetadataAutoConfiguration.class})
|
@AutoConfigureAfter(value = {DubboMetadataAutoConfiguration.class})
|
||||||
@Configuration
|
@Configuration
|
||||||
public class DubboRestMetadataRegistrationAutoConfiguration {
|
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> serviceRestMetadata = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MetadataResolver metadataResolver;
|
private MetadataResolver metadataResolver;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MetadataConfigService metadataConfigService;
|
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
|
||||||
|
|
||||||
@Value("${spring.application.name:application}")
|
@Value("${spring.application.name:application}")
|
||||||
private String currentApplicationName;
|
private String currentApplicationName;
|
||||||
@ -69,15 +57,6 @@ public class DubboRestMetadataRegistrationAutoConfiguration {
|
|||||||
@EventListener(ServiceBeanExportedEvent.class)
|
@EventListener(ServiceBeanExportedEvent.class)
|
||||||
public void recordRestMetadata(ServiceBeanExportedEvent event) {
|
public void recordRestMetadata(ServiceBeanExportedEvent event) {
|
||||||
ServiceBean serviceBean = event.getServiceBean();
|
ServiceBean serviceBean = event.getServiceBean();
|
||||||
serviceRestMetadata.addAll(metadataResolver.resolveServiceRestMetadata(serviceBean));
|
dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Publish <code>serviceRestMetadata</code> 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.cloud.alibaba.dubbo.metadata.repository;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.DubboServiceMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||||
import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
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.http.HttpRequest;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -44,6 +49,8 @@ public class DubboServiceMetadataRepository {
|
|||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key is application name
|
* Key is application name
|
||||||
* Value is Map<RequestMetadata, DubboServiceMetadata>
|
* Value is Map<RequestMetadata, DubboServiceMetadata>
|
||||||
@ -51,7 +58,7 @@ public class DubboServiceMetadataRepository {
|
|||||||
private Map<String, Map<RequestMetadataMatcher, DubboServiceMetadata>> repository = newHashMap();
|
private Map<String, Map<RequestMetadataMatcher, DubboServiceMetadata>> repository = newHashMap();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MetadataConfigService metadataConfigService;
|
private DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the specified service's Dubbo Service Metadata
|
* Initialize the specified service's Dubbo Service Metadata
|
||||||
@ -64,7 +71,7 @@ public class DubboServiceMetadataRepository {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ServiceRestMetadata> serviceRestMetadataSet = metadataConfigService.getServiceRestMetadata(serviceName);
|
Set<ServiceRestMetadata> serviceRestMetadataSet = getServiceRestMetadataSet(serviceName);
|
||||||
|
|
||||||
if (isEmpty(serviceRestMetadataSet)) {
|
if (isEmpty(serviceRestMetadataSet)) {
|
||||||
if (logger.isWarnEnabled()) {
|
if (logger.isWarnEnabled()) {
|
||||||
@ -145,6 +152,23 @@ public class DubboServiceMetadataRepository {
|
|||||||
return getMap(repository, serviceName);
|
return getMap(repository, serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<ServiceRestMetadata> getServiceRestMetadataSet(String serviceName) {
|
||||||
|
DubboMetadataConfigService dubboMetadataConfigService = dubboMetadataConfigServiceProxy.newProxy(serviceName);
|
||||||
|
String serviceRestMetadataJsonConfig = dubboMetadataConfigService.getServiceRestMetadata();
|
||||||
|
|
||||||
|
Set<ServiceRestMetadata> 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 <K, V> Map<K, V> getMap(Map<String, Map<K, V>> repository, String key) {
|
private static <K, V> Map<K, V> getMap(Map<String, Map<K, V>> repository, String key) {
|
||||||
return getOrDefault(repository, key, newHashMap());
|
return getOrDefault(repository, key, newHashMap());
|
||||||
}
|
}
|
||||||
@ -161,4 +185,5 @@ public class DubboServiceMetadataRepository {
|
|||||||
private static <K, V> Map<K, V> newHashMap() {
|
private static <K, V> Map<K, V> newHashMap() {
|
||||||
return new LinkedHashMap<>();
|
return new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -127,12 +127,22 @@ public class DubboServiceBeanMetadataResolver implements BeanClassLoaderAware, S
|
|||||||
public Set<RestMethodMetadata> resolveMethodRestMetadata(Class<?> targetType) {
|
public Set<RestMethodMetadata> resolveMethodRestMetadata(Class<?> targetType) {
|
||||||
List<Method> feignContractMethods = selectFeignContractMethods(targetType);
|
List<Method> feignContractMethods = selectFeignContractMethods(targetType);
|
||||||
return contracts.stream()
|
return contracts.stream()
|
||||||
.map(contract -> contract.parseAndValidatateMetadata(targetType))
|
.map(contract -> parseAndValidateMetadata(contract, targetType))
|
||||||
.flatMap(v -> v.stream())
|
.flatMap(v -> v.stream())
|
||||||
.map(methodMetadata -> resolveMethodRestMetadata(methodMetadata, targetType, feignContractMethods))
|
.map(methodMetadata -> resolveMethodRestMetadata(methodMetadata, targetType, feignContractMethods))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<MethodMetadata> parseAndValidateMetadata(Contract contract, Class<?> targetType) {
|
||||||
|
List<MethodMetadata> methodMetadataList = Collections.emptyList();
|
||||||
|
try {
|
||||||
|
methodMetadataList = contract.parseAndValidatateMetadata(targetType);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return methodMetadataList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select feign contract methods
|
* Select feign contract methods
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -50,18 +50,18 @@ public class DubboGenericServiceFactory {
|
|||||||
public GenericService create(DubboServiceMetadata dubboServiceMetadata,
|
public GenericService create(DubboServiceMetadata dubboServiceMetadata,
|
||||||
DubboTransportedMetadata dubboTransportedMetadata) {
|
DubboTransportedMetadata dubboTransportedMetadata) {
|
||||||
|
|
||||||
Integer key = Objects.hash(dubboServiceMetadata, dubboTransportedMetadata);
|
ReferenceBean<GenericService> referenceBean = build(dubboServiceMetadata.getServiceRestMetadata(), dubboTransportedMetadata);
|
||||||
|
|
||||||
ReferenceBean<GenericService> referenceBean = cache.get(key);
|
|
||||||
|
|
||||||
if (referenceBean == null) {
|
|
||||||
referenceBean = build(dubboServiceMetadata.getServiceRestMetadata(), dubboTransportedMetadata);
|
|
||||||
cache.putIfAbsent(key, referenceBean);
|
|
||||||
}
|
|
||||||
|
|
||||||
return referenceBean == null ? null : referenceBean.get();
|
return referenceBean == null ? null : referenceBean.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GenericService create(String serviceName, Class<?> serviceClass) {
|
||||||
|
String interfaceName = serviceClass.getName();
|
||||||
|
ReferenceBean<GenericService> referenceBean = build(interfaceName, serviceName, null,
|
||||||
|
"dubbo", "failover");
|
||||||
|
return referenceBean.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private ReferenceBean<GenericService> build(ServiceRestMetadata serviceRestMetadata,
|
private ReferenceBean<GenericService> build(ServiceRestMetadata serviceRestMetadata,
|
||||||
DubboTransportedMetadata dubboTransportedMetadata) {
|
DubboTransportedMetadata dubboTransportedMetadata) {
|
||||||
@ -70,14 +70,28 @@ public class DubboGenericServiceFactory {
|
|||||||
String interfaceName = getServiceInterface(segments);
|
String interfaceName = getServiceInterface(segments);
|
||||||
String version = getServiceVersion(segments);
|
String version = getServiceVersion(segments);
|
||||||
String group = getServiceGroup(segments);
|
String group = getServiceGroup(segments);
|
||||||
|
String protocol = dubboTransportedMetadata.getProtocol();
|
||||||
|
String cluster = dubboTransportedMetadata.getCluster();
|
||||||
|
|
||||||
ReferenceBean<GenericService> referenceBean = new ReferenceBean<GenericService>();
|
return build(interfaceName, version, group, protocol, cluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReferenceBean<GenericService> build(String interfaceName, String version, String group, String protocol,
|
||||||
|
String cluster) {
|
||||||
|
|
||||||
|
Integer key = Objects.hash(interfaceName, version, group, protocol, cluster);
|
||||||
|
|
||||||
|
ReferenceBean<GenericService> referenceBean = cache.get(key);
|
||||||
|
|
||||||
|
if (referenceBean == null) {
|
||||||
|
referenceBean = new ReferenceBean<>();
|
||||||
referenceBean.setGeneric(true);
|
referenceBean.setGeneric(true);
|
||||||
referenceBean.setInterface(interfaceName);
|
referenceBean.setInterface(interfaceName);
|
||||||
referenceBean.setVersion(version);
|
referenceBean.setVersion(version);
|
||||||
referenceBean.setGroup(group);
|
referenceBean.setGroup(group);
|
||||||
referenceBean.setProtocol(dubboTransportedMetadata.getProtocol());
|
referenceBean.setProtocol(protocol);
|
||||||
referenceBean.setCluster(dubboTransportedMetadata.getCluster());
|
referenceBean.setCluster(cluster);
|
||||||
|
}
|
||||||
|
|
||||||
return referenceBean;
|
return referenceBean;
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,16 @@ import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config Service for Metadata
|
* Dubbo Metadata Configuration Service
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
*/
|
*/
|
||||||
public interface MetadataConfigService {
|
public interface DubboMetadataConfigService {
|
||||||
|
|
||||||
void publishServiceRestMetadata(String serviceName, Set<ServiceRestMetadata> serviceRestMetadata);
|
/**
|
||||||
|
* Get The json content of {@link ServiceRestMetadata} {@link Set}
|
||||||
Set<ServiceRestMetadata> getServiceRestMetadata(String serviceName);
|
*
|
||||||
|
* @return the non-null String
|
||||||
|
*/
|
||||||
|
String getServiceRestMetadata();
|
||||||
}
|
}
|
@ -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 <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
|
||||||
*/
|
|
||||||
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> 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<ServiceRestMetadata> getServiceRestMetadata(String serviceName) {
|
|
||||||
Set<ServiceRestMetadata> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||||
|
*/
|
||||||
|
@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> 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<ServiceRestMetadata> 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user