1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

Temporary commit

This commit is contained in:
小马哥 2019-01-19 23:21:24 +08:00
parent f34e1883e3
commit 5c2b118523
8 changed files with 203 additions and 51 deletions

View File

@ -58,7 +58,7 @@ public class DubboOpenFeignAutoConfiguration {
private ObjectProvider<FeignContext> feignContextObjectProvider;
@EventListener(ApplicationReadyEvent.class)
public void onContextRefreshed(ApplicationReadyEvent event) {
public void onApplicationReady(ApplicationReadyEvent event) {
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
// Resolve the subscribed service names for @FeignClient
Set<String> feignClientServiceNames = resolveFeignClientServiceNames(applicationContext);

View File

@ -17,10 +17,11 @@
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.Contract;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.alibaba.dubbo.rest.feign.FeignRestMetadataResolver;
import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataConfigService;
import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@ -35,14 +36,9 @@ import org.springframework.core.Ordered;
public class DubboRestAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
@Bean
public RestMetadataResolver metadataJsonResolver(ObjectMapper objectMapper) {
return new RestMetadataResolver(objectMapper);
public FeignRestMetadataResolver metadataJsonResolver(
ObjectProvider<ObjectMapper> objectMapper, ObjectProvider<Contract> contract) {
return new FeignRestMetadataResolver(objectMapper, contract);
}
@Bean

View File

@ -31,7 +31,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataConfigService;
import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataResolver;
import org.springframework.cloud.alibaba.dubbo.rest.feign.FeignRestMetadataResolver;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -63,7 +63,7 @@ public class DubboRestDiscoveryAutoConfiguration {
private DiscoveryClient discoveryClient;
@Autowired
private RestMetadataResolver restMetadataResolver;
private FeignRestMetadataResolver feignRestMetadataResolver;
@Autowired(required = false)
private ObjectMapper objectMapper = new ObjectMapper();
@ -206,7 +206,7 @@ public class DubboRestDiscoveryAutoConfiguration {
// Map<String, List<String>> restMetadata = objectMapper.readValue(restMetadataJson, Map.class);
//
// restMetadata.forEach((dubboServiceName, restJsons) -> {
// restJsons.stream().map(restMetadataResolver::resolveRequest).forEach(request -> {
// restJsons.stream().map(feignRestMetadataResolver::resolveRequest).forEach(request -> {
// referenceBeanCache.put(request.toString(), buildReferenceBean(dubboServiceName));
// });
// });
@ -231,7 +231,7 @@ public class DubboRestDiscoveryAutoConfiguration {
// Map<String, List<String>> restMetadata = objectMapper.readValue(restMetadataJson, Map.class);
//
// restMetadata.forEach((dubboServiceName, restJsons) -> {
// restJsons.stream().map(restMetadataResolver::resolveRequest).forEach(request -> {
// restJsons.stream().map(feignRestMetadataResolver::resolveRequest).forEach(request -> {
// referenceBeanCache.put(request.toString(), buildReferenceBean(dubboServiceName));
// });
// });

View File

@ -23,8 +23,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.alibaba.dubbo.rest.feign.FeignRestMetadataResolver;
import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataConfigService;
import org.springframework.cloud.alibaba.dubbo.rest.feign.RestMetadataResolver;
import org.springframework.cloud.alibaba.dubbo.rest.metadata.ServiceRestMetadata;
import org.springframework.cloud.client.discovery.event.InstancePreRegisteredEvent;
import org.springframework.cloud.client.serviceregistry.Registration;
@ -57,7 +57,7 @@ public class DubboRestMetadataRegistrationAutoConfiguration {
private ObjectMapper objectMapper;
@Autowired
private RestMetadataResolver restMetadataResolver;
private FeignRestMetadataResolver feignRestMetadataResolver;
@Autowired
private RestMetadataConfigService metadataConfigService;
@ -66,7 +66,7 @@ public class DubboRestMetadataRegistrationAutoConfiguration {
@EventListener(ServiceBeanExportedEvent.class)
public void recordRestMetadata(ServiceBeanExportedEvent event) throws JsonProcessingException {
ServiceBean serviceBean = event.getServiceBean();
serviceRestMetadata.addAll(restMetadataResolver.resolve(serviceBean));
serviceRestMetadata.addAll(feignRestMetadataResolver.resolveServiceRestMetadata(serviceBean));
}
/**

View File

@ -16,7 +16,10 @@
*/
package org.springframework.cloud.alibaba.dubbo.openfeign;
import feign.Feign;
import feign.*;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration;
@ -45,12 +48,132 @@ public class DubboFeignClientsConfiguration {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Feign.Builder) {
Feign.Builder builder = (Feign.Builder) bean;
Feign feign = builder.build();
BuilderWrapper wrapper = new BuilderWrapper(builder);
return wrapper;
}
return bean;
}
};
}
private static class BuilderWrapper extends Feign.Builder {
private final Feign.Builder delegate;
private BuilderWrapper(Feign.Builder delegate) {
this.delegate = delegate;
}
@Override
public Feign.Builder logLevel(Logger.Level logLevel) {
return delegate.logLevel(logLevel);
}
@Override
public Feign.Builder contract(Contract contract) {
delegate.contract(contract);
return this;
}
@Override
public Feign.Builder client(Client client) {
delegate.client(client);
return this;
}
@Override
public Feign.Builder retryer(Retryer retryer) {
delegate.retryer(retryer);
return this;
}
@Override
public Feign.Builder logger(Logger logger) {
delegate.logger(logger);
return this;
}
@Override
public Feign.Builder encoder(Encoder encoder) {
delegate.encoder(encoder);
return this;
}
@Override
public Feign.Builder decoder(Decoder decoder) {
delegate.decoder(decoder);
return this;
}
@Override
public Feign.Builder queryMapEncoder(QueryMapEncoder queryMapEncoder) {
delegate.queryMapEncoder(queryMapEncoder);
return this;
}
@Override
public Feign.Builder mapAndDecode(ResponseMapper mapper, Decoder decoder) {
delegate.mapAndDecode(mapper, decoder);
return this;
}
@Override
public Feign.Builder decode404() {
delegate.decode404();
return this;
}
@Override
public Feign.Builder errorDecoder(ErrorDecoder errorDecoder) {
delegate.errorDecoder(errorDecoder);
return this;
}
@Override
public Feign.Builder options(Request.Options options) {
delegate.options(options);
return this;
}
@Override
public Feign.Builder requestInterceptor(RequestInterceptor requestInterceptor) {
delegate.requestInterceptor(requestInterceptor);
return this;
}
@Override
public Feign.Builder requestInterceptors(Iterable<RequestInterceptor> requestInterceptors) {
delegate.requestInterceptors(requestInterceptors);
return this;
}
@Override
public Feign.Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory) {
delegate.invocationHandlerFactory(invocationHandlerFactory);
return this;
}
@Override
public Feign.Builder doNotCloseAfterDecode() {
delegate.doNotCloseAfterDecode();
return this;
}
@Override
public <T> T target(Class<T> apiType, String url) {
return delegate.target(apiType, url);
}
@Override
public <T> T target(Target<T> target) {
return delegate.target(target);
}
@Override
public Feign build() {
return delegate.build();
}
}
}

View File

@ -26,10 +26,12 @@ import feign.Request;
import feign.RequestTemplate;
import feign.jaxrs2.JAXRS2Contract;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry;
import org.springframework.cloud.alibaba.dubbo.rest.metadata.MethodRestMetadata;
import org.springframework.cloud.alibaba.dubbo.rest.metadata.ServiceRestMetadata;
@ -44,18 +46,29 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* The JSON resolver for {@link MethodMetadata}
* The REST metadata resolver for Feign
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class RestMetadataResolver implements BeanClassLoaderAware, SmartInitializingSingleton {
public class FeignRestMetadataResolver implements BeanClassLoaderAware, SmartInitializingSingleton {
private static final String METHOD_PROPERTY_NAME = "method";
private static final String URL_PROPERTY_NAME = "url";
private static final String HEADERS_PROPERTY_NAME = "headers";
private static final String[] CONTRACT_CLASS_NAMES = {
"feign.jaxrs2.JAXRS2Contract",
"org.springframework.cloud.openfeign.support.SpringMvcContract",
};
private final ObjectMapper objectMapper;
private final ObjectProvider<Contract> contract;
/**
* Feign Contracts
*/
@ -63,37 +76,44 @@ public class RestMetadataResolver implements BeanClassLoaderAware, SmartInitiali
private ClassLoader classLoader;
@Autowired
private ObjectProvider<Contract> contractObjectProvider;
@Value("${spring.application.name}")
private String currentApplicationName;
public RestMetadataResolver(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
public FeignRestMetadataResolver(ObjectProvider<ObjectMapper> objectMapper, ObjectProvider<Contract> contract) {
this.objectMapper = objectMapper.getIfAvailable();
this.contract = contract;
}
@Override
public void afterSingletonsInstantiated() {
Collection<Contract> contracts = new LinkedList<>();
LinkedList<Contract> contracts = new LinkedList<>();
// Add injected Contract , for example SpringMvcContract Bean under Spring Cloud Open Feign
Contract contract = contractObjectProvider.getIfAvailable();
if (contract != null) {
contracts.add(contract);
} else {
if (ClassUtils.isPresent("org.springframework.cloud.openfeign.support.SpringMvcContract", classLoader)) {
contracts.add(new SpringMvcContract());
}
}
// Add injected Contract if available, for example SpringMvcContract Bean under Spring Cloud Open Feign
contract.ifAvailable(contracts::add);
// Add JAXRS2Contract if it's present in Class Path
if (ClassUtils.isPresent("javax.ws.rs.Path", classLoader)) {
contracts.add(new JAXRS2Contract());
}
Stream.of(CONTRACT_CLASS_NAMES)
.filter(this::isClassPresent) // filter the existed classes
.map(this::loadContractClass) // load Contract Class
.map(this::createContract) // create instance by the specified class
.forEach(contracts::add); // add the Contract instance into contracts
this.contracts = Collections.unmodifiableCollection(contracts);
}
public Set<ServiceRestMetadata> resolve(ServiceBean serviceBean) {
private Contract createContract(Class<?> contractClassName) {
return (Contract) BeanUtils.instantiateClass(contractClassName);
}
private Class<?> loadContractClass(String contractClassName) {
return ClassUtils.resolveClassName(contractClassName, classLoader);
}
private boolean isClassPresent(String className) {
return ClassUtils.isPresent(className, classLoader);
}
public Set<ServiceRestMetadata> resolveServiceRestMetadata(ServiceBean serviceBean) {
Object bean = serviceBean.getRef();
@ -103,14 +123,7 @@ public class RestMetadataResolver implements BeanClassLoaderAware, SmartInitiali
Set<ServiceRestMetadata> serviceRestMetadata = new LinkedHashSet<>();
Set<MethodRestMetadata> methodRestMetadata = new LinkedHashSet<>();
contracts.stream()
.map(contract -> contract.parseAndValidatateMetadata(bean.getClass()))
.flatMap(v -> v.stream())
.forEach(methodMetadata -> {
methodRestMetadata.add(resolveMethodRestMetadata(methodMetadata, beanType, interfaceClass));
});
Set<MethodRestMetadata> methodRestMetadata = resolveMethodRestMetadata(beanType, interfaceClass);
List<URL> urls = serviceBean.getExportedUrls();
@ -126,6 +139,18 @@ public class RestMetadataResolver implements BeanClassLoaderAware, SmartInitiali
return serviceRestMetadata;
}
public Set<MethodRestMetadata> resolveMethodRestMetadata(Class<?> targetClass) {
return resolveMethodRestMetadata(targetClass, targetClass);
}
protected Set<MethodRestMetadata> resolveMethodRestMetadata(Class<?> targetClass, Class revisedClass) {
return contracts.stream()
.map(contract -> contract.parseAndValidatateMetadata(targetClass))
.flatMap(v -> v.stream())
.map(methodMetadata -> resolveMethodRestMetadata(methodMetadata, targetClass, revisedClass))
.collect(Collectors.toSet());
}
private String toJson(Object object) {
String jsonContent = null;
try {
@ -137,6 +162,9 @@ public class RestMetadataResolver implements BeanClassLoaderAware, SmartInitiali
}
private String regenerateConfigKey(String configKey, Class<?> beanType, Class<?> interfaceClass) {
if (beanType.equals(interfaceClass)) {
return configKey;
}
return StringUtils.replace(configKey, beanType.getSimpleName(), interfaceClass.getSimpleName());
}

View File

@ -27,6 +27,8 @@ import static com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP;
/**
* Rest Metadata Config Service
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class RestMetadataConfigService {
@ -45,7 +47,7 @@ public class RestMetadataConfigService {
* TODO JavaDoc
*/
private static String getServiceRestMetadataDataId(String serviceName) {
return serviceName + "-rest-metadata.json";
return "metadata:rest:" + serviceName + ".json";
}
public void publishServiceRestMetadata(String serviceName, String restMetadataJSON)

View File

@ -10,4 +10,7 @@ dubbo:
port: 9090
server: netty
registry:
address: spring-cloud://nacos
address: spring-cloud://nacos
server:
port: 8080