1
0
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#386 : supports Spring Cloud Netflix Eureka and Spring Cloud Zookeeper

This commit is contained in:
mercyblitz 2019-02-26 14:50:26 +08:00
parent 6daba36e35
commit b3c26c509e
22 changed files with 509 additions and 353 deletions

View File

@ -17,6 +17,8 @@
<dubbo.version>2.6.5</dubbo.version> <dubbo.version>2.6.5</dubbo.version>
<dubbo-spring-boot.version>0.2.1.RELEASE</dubbo-spring-boot.version> <dubbo-spring-boot.version>0.2.1.RELEASE</dubbo-spring-boot.version>
<dubbo-registry-nacos.version>0.0.2</dubbo-registry-nacos.version> <dubbo-registry-nacos.version>0.0.2</dubbo-registry-nacos.version>
<spring-cloud-zookeeper.version>2.1.0.RELEASE</spring-cloud-zookeeper.version>
<curator.version>4.0.1</curator.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -53,6 +55,54 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<!-- Eureka Service Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<optional>true</optional>
</dependency>
<!-- Zookeeper Service Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<version>${spring-cloud-zookeeper.version}</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.12</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
<optional>true</optional>
</dependency>
<!-- Nacos Service Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId> <artifactId>spring-boot-actuator-autoconfigure</artifactId>
@ -90,11 +140,6 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId> <artifactId>spring-cloud-starter-openfeign</artifactId>
@ -118,37 +163,6 @@
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
</dependency> </dependency>
<!-- REST support dependencies -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-netty4</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
</dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
@ -162,11 +176,6 @@
<version>9.7.0</version> <version>9.7.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- Testing --> <!-- Testing -->
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
@ -192,19 +201,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- Nacos Service Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<scope>test</scope>
</dependency>
<!-- Eureka Service Discovery -->
<!--<dependency>-->
<!--<groupId>org.springframework.cloud</groupId>-->
<!--<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
<!--<scope>test</scope>-->
<!--</dependency>-->
</dependencies> </dependencies>
</project> </project>

View File

@ -33,7 +33,6 @@ import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceM
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory; import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory; import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -55,8 +54,8 @@ import java.util.Map;
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a> * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/ */
@Configuration @Configuration
@ConditionalOnClass(RestTemplate.class) @ConditionalOnClass(name = {"org.springframework.web.client.RestTemplate"})
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class) @AutoConfigureAfter(name = {"org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration"})
public class DubboLoadBalancedRestTemplateAutoConfiguration implements BeanClassLoaderAware { public class DubboLoadBalancedRestTemplateAutoConfiguration implements BeanClassLoaderAware {
private static final Class<DubboTransported> DUBBO_TRANSPORTED_CLASS = DubboTransported.class; private static final Class<DubboTransported> DUBBO_TRANSPORTED_CLASS = DubboTransported.class;

View File

@ -66,6 +66,12 @@ public class DubboMetadataAutoConfiguration {
protocolConfig = iterator.hasNext() ? iterator.next() : null; protocolConfig = iterator.hasNext() ? iterator.next() : null;
} }
if (protocolConfig == null) {
protocolConfig = new ProtocolConfig();
protocolConfig.setName(DEFAULT_PROTOCOL);
protocolConfig.setPort(20880);
}
return protocolConfig; return protocolConfig;
} }

View File

@ -17,7 +17,6 @@
package org.springframework.cloud.alibaba.dubbo.autoconfigure; package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import feign.Contract; import feign.Contract;
import feign.Feign;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@ -28,7 +27,6 @@ import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolve
import org.springframework.cloud.alibaba.dubbo.openfeign.TargeterBeanPostProcessor; import org.springframework.cloud.alibaba.dubbo.openfeign.TargeterBeanPostProcessor;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory; import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory; import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
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.core.env.Environment; import org.springframework.core.env.Environment;
@ -39,8 +37,8 @@ import org.springframework.core.env.Environment;
* *
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a> * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/ */
@ConditionalOnClass(value = Feign.class) @ConditionalOnClass(name = {"feign.Feign"})
@AutoConfigureAfter(FeignAutoConfiguration.class) @AutoConfigureAfter(name = {"org.springframework.cloud.openfeign.FeignAutoConfiguration"})
@Configuration @Configuration
public class DubboOpenFeignAutoConfiguration { public class DubboOpenFeignAutoConfiguration {

View File

@ -84,7 +84,7 @@ public class DubboServiceBeanMetadataResolver implements BeanClassLoaderAware, S
Stream.of(CONTRACT_CLASS_NAMES) Stream.of(CONTRACT_CLASS_NAMES)
.filter(this::isClassPresent) // filter the existed classes .filter(this::isClassPresent) // filter the existed classes
.map(this::loadContractClass) // load Contract Class .map(this::loadContractClass) // load Contract Class
.map(this::createContract) // create instance by the specified class .map(this::createContract) // createServiceInstance instance by the specified class
.forEach(contracts::add); // add the Contract instance into contracts .forEach(contracts::add); // add the Contract instance into contracts
this.contracts = Collections.unmodifiableCollection(contracts); this.contracts = Collections.unmodifiableCollection(contracts);

View File

@ -26,6 +26,7 @@ import org.springframework.core.env.Environment;
import static java.lang.reflect.Proxy.newProxyInstance; import static java.lang.reflect.Proxy.newProxyInstance;
import static org.springframework.util.ClassUtils.getUserClass; import static org.springframework.util.ClassUtils.getUserClass;
import static org.springframework.util.ClassUtils.isPresent;
import static org.springframework.util.ClassUtils.resolveClassName; import static org.springframework.util.ClassUtils.resolveClassName;
/** /**
@ -64,6 +65,7 @@ public class TargeterBeanPostProcessor implements BeanPostProcessor, BeanClassLo
@Override @Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
if (isPresent(TARGETER_CLASS_NAME, classLoader)) {
Class<?> beanClass = getUserClass(bean.getClass()); Class<?> beanClass = getUserClass(bean.getClass());
Class<?> targetClass = resolveClassName(TARGETER_CLASS_NAME, classLoader); Class<?> targetClass = resolveClassName(TARGETER_CLASS_NAME, classLoader);
if (targetClass.isAssignableFrom(beanClass)) { if (targetClass.isAssignableFrom(beanClass)) {
@ -71,6 +73,7 @@ public class TargeterBeanPostProcessor implements BeanPostProcessor, BeanClassLo
new TargeterInvocationHandler(bean, environment, dubboServiceMetadataRepository, new TargeterInvocationHandler(bean, environment, dubboServiceMetadataRepository,
dubboGenericServiceFactory, contextFactory)); dubboGenericServiceFactory, contextFactory));
} }
}
return bean; return bean;
} }

View File

@ -0,0 +1,49 @@
/*
* 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.registry;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.NetUtils;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import java.util.LinkedHashMap;
/**
* Abstract {@link RegistrationFactory} implementation
* <p>
*
* @param <T> The subclass of {@link Registration}
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public abstract class AbstractRegistrationFactory<T extends Registration> implements RegistrationFactory<T> {
protected ServiceInstance createServiceInstance(String serviceName, URL url) {
// Append default category if absent
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
URL newURL = url.addParameter(Constants.CATEGORY_KEY, category);
newURL = newURL.addParameter(Constants.PROTOCOL_KEY, url.getProtocol());
String ip = NetUtils.getLocalHost();
int port = newURL.getParameter(Constants.BIND_PORT_KEY, url.getPort());
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(url.toIdentityString(), serviceName, ip, port, false);
serviceInstance.getMetadata().putAll(new LinkedHashMap<>(newURL.getParameters()));
return serviceInstance;
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.registry;
import com.alibaba.dubbo.common.URL;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
/**
* Default {@link RegistrationFactory}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class DefaultRegistrationFactory extends AbstractRegistrationFactory<Registration> {
@Override
public Registration create(String serviceName, URL url, ApplicationContext applicationContext) {
return new DelegatingRegistration(createServiceInstance(serviceName, url));
}
}

View File

@ -27,11 +27,11 @@ import java.util.Map;
* *
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a> * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/ */
class DubboRegistration implements Registration { class DelegatingRegistration implements Registration {
private final ServiceInstance delegate; private final ServiceInstance delegate;
public DubboRegistration(ServiceInstance delegate) { public DelegatingRegistration(ServiceInstance delegate) {
this.delegate = delegate; this.delegate = delegate;
} }

View File

@ -0,0 +1,42 @@
/*
* 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.registry;
import com.alibaba.dubbo.common.URL;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.context.ApplicationContext;
/**
* {@link Registration} Factory to createServiceInstance a instance of {@link Registration}
*
* @param <T> The subclass of {@link Registration}
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public interface RegistrationFactory<T extends Registration> {
/**
* Create a instance of {@link T}
*
* @param serviceName The service name of Dubbo service interface
* @param url The Dubbo's URL
* @param applicationContext {@link ApplicationContext}
* @return a instance of {@link T}
*/
T create(String serviceName, URL url, ApplicationContext applicationContext);
}

View File

@ -18,7 +18,7 @@ package org.springframework.cloud.alibaba.dubbo.registry;
import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.NetUtils; import com.alibaba.dubbo.common.utils.NamedThreadFactory;
import com.alibaba.dubbo.common.utils.UrlUtils; import com.alibaba.dubbo.common.utils.UrlUtils;
import com.alibaba.dubbo.registry.NotifyListener; import com.alibaba.dubbo.registry.NotifyListener;
import com.alibaba.dubbo.registry.RegistryFactory; import com.alibaba.dubbo.registry.RegistryFactory;
@ -26,11 +26,12 @@ import com.alibaba.dubbo.registry.support.FailbackRegistry;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
@ -38,11 +39,9 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -50,6 +49,13 @@ 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.CONSUMERS_CATEGORY;
import static com.alibaba.dubbo.common.Constants.PROVIDERS_CATEGORY; import static com.alibaba.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static com.alibaba.dubbo.common.Constants.ROUTERS_CATEGORY; import static com.alibaba.dubbo.common.Constants.ROUTERS_CATEGORY;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.springframework.beans.BeanUtils.instantiateClass;
import static org.springframework.core.ResolvableType.forInstance;
import static org.springframework.core.ResolvableType.forType;
import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames;
import static org.springframework.util.ClassUtils.isPresent;
import static org.springframework.util.ClassUtils.resolveClassName;
/** /**
* Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose protocol is "spring-cloud" * Dubbo {@link RegistryFactory} uses Spring Cloud Service Registration abstraction, whose protocol is "spring-cloud"
@ -70,10 +76,6 @@ public class SpringCloudRegistry extends FailbackRegistry {
private static final int CATEGORY_INDEX = 0; private static final int CATEGORY_INDEX = 0;
// private static final int PROTOCOL_INDEX = CATEGORY_INDEX + 1;
// private static final int SERVICE_INTERFACE_INDEX = PROTOCOL_INDEX + 1;
private static final int SERVICE_INTERFACE_INDEX = CATEGORY_INDEX + 1; private static final int SERVICE_INTERFACE_INDEX = CATEGORY_INDEX + 1;
private static final int SERVICE_VERSION_INDEX = SERVICE_INTERFACE_INDEX + 1; private static final int SERVICE_VERSION_INDEX = SERVICE_INTERFACE_INDEX + 1;
@ -82,34 +84,122 @@ public class SpringCloudRegistry extends FailbackRegistry {
private static final String WILDCARD = "*"; private static final String WILDCARD = "*";
private final Logger logger = LoggerFactory.getLogger(getClass());
/** /**
* The separator for service name * The separator for service name
*/ */
private static final String SERVICE_NAME_SEPARATOR = ":"; private static final String SERVICE_NAME_SEPARATOR = ":";
private final ApplicationContext applicationContext;
private final ServiceRegistry<Registration> serviceRegistry; private final ServiceRegistry<Registration> serviceRegistry;
private final DiscoveryClient discoveryClient; private final DiscoveryClient discoveryClient;
private final Logger logger = LoggerFactory.getLogger(getClass()); private final RegistrationFactory registrationFactory;
/** /**
* {@link ScheduledExecutorService} lookup service names(only for Dubbo-OPS) * The {@link ScheduledExecutorService Scheduler} to lookup the registered services
*/ */
private volatile ScheduledExecutorService scheduledExecutorService; private final ScheduledExecutorService registeredServicesLookupScheduler;
/**
* The {@link ScheduledExecutorService Scheduler} to lookup all services (only for Dubbo-OPS)
*/
private volatile ScheduledExecutorService allServicesLookupScheduler;
/** /**
* The interval in second of lookup service names(only for Dubbo-OPS) * The interval in second of lookup service names(only for Dubbo-OPS)
*/ */
private static final long LOOKUP_INTERVAL = Long.getLong("dubbo.service.names.lookup.interval", 30); private static final long ALL_SERVICES_LOOKUP_INTERVAL = Long.getLong("dubbo.all.services.lookup.interval", 30);
public SpringCloudRegistry(URL url, ServiceRegistry<Registration> serviceRegistry, /**
DiscoveryClient discoveryClient) { * The interval in second of lookup regigered service instances
*/
private static final long REGISTERED_SERVICES_LOOKUP_INTERVAL = Long.getLong("dubbo.registered.services.lookup.interval", 30);
public SpringCloudRegistry(URL url, ApplicationContext applicationContext) {
super(url); super(url);
this.serviceRegistry = serviceRegistry; this.applicationContext = applicationContext;
this.discoveryClient = discoveryClient; this.serviceRegistry = applicationContext.getBean(ServiceRegistry.class);
this.registrationFactory = buildRegistrationFactory(serviceRegistry, applicationContext.getClassLoader());
this.discoveryClient = applicationContext.getBean(DiscoveryClient.class);
applicationContext.getClassLoader();
this.registeredServicesLookupScheduler = newSingleThreadScheduledExecutor(new NamedThreadFactory("dubbo-registered-services-lookup-"));
} }
private RegistrationFactory buildRegistrationFactory(ServiceRegistry<Registration> serviceRegistry,
ClassLoader classLoader) {
RegistrationFactory registrationFactory = null;
List<String> factoryClassNames = loadFactoryNames(RegistrationFactory.class, classLoader);
ResolvableType serviceRegistryType = forInstance(serviceRegistry);
// Get first generic Class
Class<?> registrationClass = resolveGenericClass(serviceRegistryType, ServiceRegistry.class, 0);
for (String factoryClassName : factoryClassNames) {
if (isPresent(factoryClassName, classLoader)) { // ignore compilation issue
Class<?> factoryClass = resolveClassName(factoryClassName, classLoader);
ResolvableType registrationFactoryType = forType(factoryClass);
Class<?> actualRegistrationClass = resolveGenericClass(registrationFactoryType, RegistrationFactory.class, 0);
if (actualRegistrationClass.equals(registrationClass)) {
registrationFactory = (RegistrationFactory) instantiateClass(registrationFactoryType.getRawClass());
break;
}
}
}
if (registrationFactory == null) {
if (logger.isWarnEnabled()) {
logger.warn("{} implementation can't be resolved by ServiceRegistry[{}]",
registrationClass.getSimpleName(), serviceRegistry.getClass().getName());
}
registrationFactory = new DefaultRegistrationFactory();
} else {
if (logger.isInfoEnabled()) {
logger.info("{} has been resolved by ServiceRegistry[{}]",
registrationFactory.getClass().getName(), serviceRegistry.getClass().getName());
}
}
return registrationFactory;
}
private Class<?> resolveGenericClass(ResolvableType implementedType, Class<?> interfaceClass, int index) {
ResolvableType resolvableType = implementedType;
OUTER:
while (true) {
ResolvableType[] interfaceTypes = resolvableType.getInterfaces();
for (ResolvableType interfaceType : interfaceTypes) {
if (interfaceType.resolve().equals(interfaceClass)) {
resolvableType = interfaceType;
break OUTER;
}
}
ResolvableType superType = resolvableType.getSuperType();
Class<?> superClass = superType.resolve();
if (Object.class.equals(superClass)) {
break;
}
resolvableType = superType;
}
return resolvableType.resolveGeneric(index);
}
@Override @Override
protected void doRegister(URL url) { protected void doRegister(URL url) {
final String serviceName = getServiceName(url); final String serviceName = getServiceName(url);
@ -128,6 +218,12 @@ public class SpringCloudRegistry extends FailbackRegistry {
protected void doSubscribe(URL url, NotifyListener listener) { protected void doSubscribe(URL url, NotifyListener listener) {
List<String> serviceNames = getServiceNames(url, listener); List<String> serviceNames = getServiceNames(url, listener);
doSubscribe(url, listener, serviceNames); doSubscribe(url, listener, serviceNames);
this.registeredServicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
doSubscribe(url, listener, serviceNames);
}
}, REGISTERED_SERVICES_LOOKUP_INTERVAL, REGISTERED_SERVICES_LOOKUP_INTERVAL, TimeUnit.SECONDS);
} }
@Override @Override
@ -135,6 +231,10 @@ public class SpringCloudRegistry extends FailbackRegistry {
if (isAdminProtocol(url)) { if (isAdminProtocol(url)) {
shutdownServiceNamesLookup(); shutdownServiceNamesLookup();
} }
if (registeredServicesLookupScheduler != null) {
registeredServicesLookupScheduler.shutdown();
}
} }
@Override @Override
@ -143,25 +243,13 @@ public class SpringCloudRegistry extends FailbackRegistry {
} }
private void shutdownServiceNamesLookup() { private void shutdownServiceNamesLookup() {
if (scheduledExecutorService != null) { if (allServicesLookupScheduler != null) {
scheduledExecutorService.shutdown(); allServicesLookupScheduler.shutdown();
} }
} }
private Registration createRegistration(String serviceName, URL url) { private Registration createRegistration(String serviceName, URL url) {
return new DubboRegistration(createServiceInstance(serviceName, url)); return registrationFactory.create(serviceName, url, applicationContext);
}
private ServiceInstance createServiceInstance(String serviceName, URL url) {
// Append default category if absent
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
URL newURL = url.addParameter(Constants.CATEGORY_KEY, category);
newURL = newURL.addParameter(Constants.PROTOCOL_KEY, url.getProtocol());
String ip = NetUtils.getLocalHost();
int port = newURL.getParameter(Constants.BIND_PORT_KEY, url.getPort());
DefaultServiceInstance serviceInstance = new DefaultServiceInstance(serviceName, ip, port, false);
serviceInstance.getMetadata().putAll(new LinkedHashMap<>(newURL.getParameters()));
return serviceInstance;
} }
public static String getServiceName(URL url) { public static String getServiceName(URL url) {
@ -248,10 +336,6 @@ public class SpringCloudRegistry extends FailbackRegistry {
return segments[CATEGORY_INDEX]; return segments[CATEGORY_INDEX];
} }
// public static String getProtocol(String[] segments) {
// return segments[PROTOCOL_INDEX];
// }
public static String getServiceInterface(String[] segments) { public static String getServiceInterface(String[] segments) {
return segments[SERVICE_INTERFACE_INDEX]; return segments[SERVICE_INTERFACE_INDEX];
} }
@ -288,7 +372,7 @@ public class SpringCloudRegistry extends FailbackRegistry {
*/ */
private List<String> getServiceNames(URL url, NotifyListener listener) { private List<String> getServiceNames(URL url, NotifyListener listener) {
if (isAdminProtocol(url)) { if (isAdminProtocol(url)) {
scheduleServiceNamesLookup(url, listener); initAllServicesLookupScheduler(url, listener);
return getServiceNamesForOps(url); return getServiceNamesForOps(url);
} else { } else {
return doGetServiceNames(url); return doGetServiceNames(url);
@ -300,10 +384,10 @@ public class SpringCloudRegistry extends FailbackRegistry {
return Constants.ADMIN_PROTOCOL.equals(url.getProtocol()); return Constants.ADMIN_PROTOCOL.equals(url.getProtocol());
} }
private void scheduleServiceNamesLookup(final URL url, final NotifyListener listener) { private void initAllServicesLookupScheduler(final URL url, final NotifyListener listener) {
if (scheduledExecutorService == null) { if (allServicesLookupScheduler == null) {
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); allServicesLookupScheduler = newSingleThreadScheduledExecutor(new NamedThreadFactory("dubbo-all-services-lookup-"));
scheduledExecutorService.scheduleAtFixedRate(new Runnable() { allServicesLookupScheduler.scheduleAtFixedRate(new Runnable() {
@Override @Override
public void run() { public void run() {
List<String> serviceNames = getAllServiceNames(); List<String> serviceNames = getAllServiceNames();
@ -323,7 +407,7 @@ public class SpringCloudRegistry extends FailbackRegistry {
}); });
doSubscribe(url, listener, serviceNames); doSubscribe(url, listener, serviceNames);
} }
}, LOOKUP_INTERVAL, LOOKUP_INTERVAL, TimeUnit.SECONDS); }, ALL_SERVICES_LOOKUP_INTERVAL, ALL_SERVICES_LOOKUP_INTERVAL, TimeUnit.SECONDS);
} }
} }
@ -331,7 +415,6 @@ public class SpringCloudRegistry extends FailbackRegistry {
for (String serviceName : serviceNames) { for (String serviceName : serviceNames) {
List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName); List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);
notifySubscriber(url, listener, serviceInstances); notifySubscriber(url, listener, serviceInstances);
// TODO Support Update notification event
} }
} }

View File

@ -20,9 +20,6 @@ import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.registry.Registry; import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.registry.RegistryFactory; import com.alibaba.dubbo.registry.RegistryFactory;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
/** /**
@ -38,9 +35,7 @@ public class SpringCloudRegistryFactory implements RegistryFactory {
@Override @Override
public Registry getRegistry(URL url) { public Registry getRegistry(URL url) {
ServiceRegistry<Registration> serviceRegistry = applicationContext.getBean(ServiceRegistry.class); return new SpringCloudRegistry(url, applicationContext);
DiscoveryClient discoveryClient = applicationContext.getBean(DiscoveryClient.class);
return new SpringCloudRegistry(url, serviceRegistry, discoveryClient);
} }
public static void setApplicationContext(ApplicationContext applicationContext) { public static void setApplicationContext(ApplicationContext applicationContext) {

View File

@ -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.registry.apache.zookeeper;
import com.alibaba.dubbo.common.URL;
import org.springframework.cloud.alibaba.dubbo.registry.AbstractRegistrationFactory;
import org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.zookeeper.discovery.ZookeeperInstance;
import org.springframework.cloud.zookeeper.serviceregistry.ServiceInstanceRegistration;
import org.springframework.cloud.zookeeper.serviceregistry.ZookeeperRegistration;
import org.springframework.context.ApplicationContext;
/**
* Zookeeper {@link RegistrationFactory}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class ZookeeperRegistrationFactory extends AbstractRegistrationFactory<ZookeeperRegistration> {
@Override
public ZookeeperRegistration create(String serviceName, URL url, ApplicationContext applicationContext) {
ServiceInstance serviceInstance = createServiceInstance(serviceName, url);
ZookeeperInstance zookeeperInstance = new ZookeeperInstance(serviceInstance.getInstanceId(),
serviceInstance.getServiceId(), serviceInstance.getMetadata());
ZookeeperRegistration registration = ServiceInstanceRegistration
.builder()
.address(serviceInstance.getHost())
.name(serviceInstance.getServiceId())
.payload(zookeeperInstance)
.port(serviceInstance.getPort())
.build();
return registration;
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.registry.netflix.eureka;
import com.alibaba.dubbo.common.URL;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.discovery.EurekaClientConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.alibaba.dubbo.registry.AbstractRegistrationFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.netflix.eureka.CloudEurekaInstanceConfig;
import org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration;
import org.springframework.context.ApplicationContext;
/**
* {@link EurekaRegistration} Factory
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class EurekaRegistrationFactory extends AbstractRegistrationFactory<EurekaRegistration> {
@Override
public EurekaRegistration create(String serviceName, URL url, ApplicationContext applicationContext) {
ServiceInstance serviceInstance = createServiceInstance(serviceName, url);
CloudEurekaInstanceConfig cloudEurekaInstanceConfig = applicationContext.getBean(CloudEurekaInstanceConfig.class);
ObjectProvider<HealthCheckHandler> healthCheckHandler = applicationContext.getBeanProvider(HealthCheckHandler.class);
EurekaClientConfig eurekaClientConfig = applicationContext.getBean(EurekaClientConfig.class);
InetUtils inetUtils = applicationContext.getBean(InetUtils.class);
EurekaInstanceConfigBean eurekaInstanceConfigBean = new EurekaInstanceConfigBean(inetUtils);
BeanUtils.copyProperties(cloudEurekaInstanceConfig, eurekaInstanceConfigBean);
String serviceId = serviceInstance.getServiceId();
eurekaInstanceConfigBean.setInstanceId(serviceInstance.getInstanceId());
eurekaInstanceConfigBean.setVirtualHostName(serviceId);
eurekaInstanceConfigBean.setSecureVirtualHostName(serviceId);
eurekaInstanceConfigBean.setAppname(serviceId);
eurekaInstanceConfigBean.setHostname(serviceInstance.getHost());
eurekaInstanceConfigBean.setMetadataMap(serviceInstance.getMetadata());
return EurekaRegistration.builder(eurekaInstanceConfigBean)
.with(healthCheckHandler)
.with(eurekaClientConfig, applicationContext)
.build();
}
}

View File

@ -7,3 +7,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.context.ApplicationContextInitializer=\ org.springframework.context.ApplicationContextInitializer=\
org.springframework.cloud.alibaba.dubbo.context.DubboServiceRegistrationApplicationContextInitializer org.springframework.cloud.alibaba.dubbo.context.DubboServiceRegistrationApplicationContextInitializer
org.springframework.cloud.alibaba.dubbo.registry.RegistrationFactory=\
org.springframework.cloud.alibaba.dubbo.registry.DefaultRegistrationFactory,\
org.springframework.cloud.alibaba.dubbo.registry.netflix.eureka.EurekaRegistrationFactory,\
org.springframework.cloud.alibaba.dubbo.registry.apache.zookeeper.ZookeeperRegistrationFactory

View File

@ -1,222 +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.bootstrap;
import com.alibaba.dubbo.config.annotation.Reference;
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.annotation.DubboTransported;
import org.springframework.cloud.alibaba.dubbo.service.RestService;
import org.springframework.cloud.alibaba.dubbo.service.User;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.util.HashMap;
import java.util.Map;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;
/**
* Dubbo Spring Cloud Bootstrap
*/
@EnableDiscoveryClient
@EnableAutoConfiguration
@EnableFeignClients
@RestController
public class DubboSpringCloudBootstrap {
@Reference(version = "1.0.0")
private RestService restService;
@Autowired
@Lazy
private FeignRestService feignRestService;
@Autowired
@Lazy
private DubboFeignRestService dubboFeignRestService;
@Autowired
@LoadBalanced
private RestTemplate restTemplate;
@FeignClient("spring-cloud-alibaba-dubbo")
public interface FeignRestService {
@GetMapping(value = "/param")
String param(@RequestParam("param") String param);
@PostMapping("/params")
public String params(@RequestParam("b") String b, @RequestParam("a") int a);
@PostMapping(value = "/request/body/map", produces = APPLICATION_JSON_UTF8_VALUE)
User requestBody(@RequestParam("param") String param, @RequestBody Map<String, Object> data);
@GetMapping("/headers")
@Path("/headers")
@GET
public String headers(@RequestHeader("h2") String header2,
@RequestHeader("h") String header,
@RequestParam("v") Integer value);
@GetMapping("/path-variables/{p1}/{p2}")
public String pathVariables(@PathVariable("p2") String path2,
@PathVariable("p1") String path1,
@RequestParam("v") String param);
}
@FeignClient("spring-cloud-alibaba-dubbo")
@DubboTransported
public interface DubboFeignRestService {
@GetMapping(value = "/param")
String param(@RequestParam("param") String param);
@PostMapping("/params")
String params(@RequestParam("b") String paramB, @RequestParam("a") int paramA);
@PostMapping(value = "/request/body/map", produces = APPLICATION_JSON_UTF8_VALUE)
User requestBody(@RequestParam("param") String param, @RequestBody Map<String, Object> data);
@GetMapping("/headers")
@Path("/headers")
@GET
public String headers(@RequestHeader("h2") String header2,
@RequestParam("v") Integer value,
@RequestHeader("h") String header);
@GetMapping("/path-variables/{p1}/{p2}")
public String pathVariables(@RequestParam("v") String param,
@PathVariable("p2") String path2,
@PathVariable("p1") String path1);
}
@Bean
public ApplicationRunner paramRunner() {
return arguments -> {
// To call /path-variables
callPathVariables();
// To call /headers
callHeaders();
// To call /param
callParam();
// To call /params
callParams();
// To call /request/body/map
callRequestBodyMap();
};
}
private void callPathVariables() {
// Dubbo Service call
System.out.println(restService.pathVariables("a", "b", "c"));
// Spring Cloud Open Feign REST Call (Dubbo Transported)
System.out.println(dubboFeignRestService.pathVariables("c", "b", "a"));
// Spring Cloud Open Feign REST Call
System.out.println(feignRestService.pathVariables("b", "a", "c"));
// RestTemplate call
System.out.println(restTemplate.getForEntity("http://spring-cloud-alibaba-dubbo//path-variables/{p1}/{p2}?v=c", String.class, "a", "b"));
}
private void callHeaders() {
// Dubbo Service call
System.out.println(restService.headers("a", "b", 10));
// Spring Cloud Open Feign REST Call (Dubbo Transported)
System.out.println(dubboFeignRestService.headers("b", 10, "a"));
// Spring Cloud Open Feign REST Call
System.out.println(feignRestService.headers("b", "a", 10));
}
private void callParam() {
// Dubbo Service call
System.out.println(restService.param("mercyblitz"));
// Spring Cloud Open Feign REST Call (Dubbo Transported)
System.out.println(dubboFeignRestService.param("mercyblitz"));
// Spring Cloud Open Feign REST Call
System.out.println(feignRestService.param("mercyblitz"));
}
private void callParams() {
// Dubbo Service call
System.out.println(restService.params(1, "1"));
// Spring Cloud Open Feign REST Call (Dubbo Transported)
System.out.println(dubboFeignRestService.params("1", 1));
// Spring Cloud Open Feign REST Call
System.out.println(feignRestService.params("1", 1));
// RestTemplate call
System.out.println(restTemplate.getForEntity("http://spring-cloud-alibaba-dubbo/param?param=小马哥", String.class));
}
private void callRequestBodyMap() {
Map<String, Object> data = new HashMap<>();
data.put("id", 1);
data.put("name", "小马哥");
data.put("age", 33);
// Dubbo Service call
System.out.println(restService.requestBodyMap(data, "Hello,World"));
// Spring Cloud Open Feign REST Call (Dubbo Transported)
// System.out.println(dubboFeignRestService.requestBody("Hello,World", data));
// Spring Cloud Open Feign REST Call
System.out.println(feignRestService.requestBody("Hello,World", data));
// RestTemplate call
System.out.println(restTemplate.postForObject("http://spring-cloud-alibaba-dubbo/request/body/map?param=小马哥", data, User.class));
}
@Bean
@LoadBalanced
@DubboTransported
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
new SpringApplicationBuilder(DubboSpringCloudBootstrap.class)
.run(args);
}
}

View File

@ -7,7 +7,7 @@ dubbo:
port: 12345 port: 12345
rest: rest:
name: rest name: rest
port: 9090 port: 8081
server: netty server: netty
registry: registry:
address: spring-cloud://nacos address: spring-cloud://nacos

View File

@ -7,6 +7,9 @@ spring:
server-addr: 127.0.0.1:8848 server-addr: 127.0.0.1:8848
config: config:
server-addr: 127.0.0.1:8848 server-addr: 127.0.0.1:8848
zookeeper:
enabled: false
main: main:
allow-bean-definition-overriding: true allow-bean-definition-overriding: true
@ -27,4 +30,18 @@ eureka:
client: client:
enabled: true enabled: true
service-url: service-url:
defaultZone: http://127.0.0.1:8761/eureka/ defaultZone: http://localhost:9090/eureka/
---
spring:
profiles: zookeeper
cloud:
nacos:
discovery:
enabled: false
register-enabled: false
zookeeper:
enabled: true
connect-string: localhost:2181

View File

@ -0,0 +1,37 @@
/*
* 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.bootstrap;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* Dubbo Spring Cloud Provider Bootstrap
*/
@EnableDiscoveryClient
@EnableAutoConfiguration
public class DubboSpringCloudProviderBootstrap {
public static void main(String[] args) {
new SpringApplicationBuilder(DubboSpringCloudProviderBootstrap.class)
.run(args);
}
}

View File

@ -20,6 +20,7 @@ import com.alibaba.dubbo.rpc.RpcContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -40,7 +41,6 @@ import javax.ws.rs.QueryParam;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;
import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE; import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
/** /**
@ -109,7 +109,7 @@ public class StandardRestService implements RestService {
} }
@Override @Override
@PostMapping(value = "/request/body/map", produces = APPLICATION_JSON_UTF8_VALUE) @PostMapping(value = "/request/body/map", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Path("/request/body/map") @Path("/request/body/map")
@POST @POST
@Produces(APPLICATION_JSON_VALUE) @Produces(APPLICATION_JSON_VALUE)
@ -122,11 +122,11 @@ public class StandardRestService implements RestService {
return user; return user;
} }
@PostMapping(value = "/request/body/user", consumes = APPLICATION_JSON_UTF8_VALUE) @PostMapping(value = "/request/body/user", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Path("/request/body/user") @Path("/request/body/user")
@POST @POST
@Override @Override
@Consumes(APPLICATION_JSON_UTF8_VALUE) @Consumes(MediaType.APPLICATION_JSON_UTF8_VALUE)
public Map<String, Object> requestBodyUser(@RequestBody User user) { public Map<String, Object> requestBodyUser(@RequestBody User user) {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("id", user.getId()); map.put("id", user.getId());

View File

@ -19,7 +19,7 @@ package org.springframework.cloud.alibaba.dubbo.service;
import java.util.Map; import java.util.Map;
/** /**
* Echo Service * Rest Service
* *
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a> * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/ */
@ -38,5 +38,4 @@ public interface RestService {
User requestBodyMap(Map<String, Object> data, String param); User requestBodyMap(Map<String, Object> data, String param);
Map<String, Object> requestBodyUser(User user); Map<String, Object> requestBodyUser(User user);
} }

View File

@ -16,21 +16,19 @@
*/ */
package org.springframework.cloud.alibaba.dubbo.service; package org.springframework.cloud.alibaba.dubbo.service;
import javax.ws.rs.FormParam;
import java.io.Serializable; import java.io.Serializable;
/** /**
* User Entity * User Entity
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/ */
public class User implements Serializable { public class User implements Serializable {
@FormParam("id")
private Long id; private Long id;
@FormParam("name")
private String name; private String name;
@FormParam("age")
private Integer age; private Integer age;
public Long getId() { public Long getId() {