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#348 : @DubboTransported supports RestTemplate (part 2)
This commit is contained in:
parent
0b31eccbf0
commit
4b1c3c6454
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -50,7 +51,7 @@ import java.util.Map;
|
||||
@Configuration
|
||||
@ConditionalOnClass(RestTemplate.class)
|
||||
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
|
||||
public class DubboLoadBalancedRestTemplateAutoConfiguration {
|
||||
public class DubboLoadBalancedRestTemplateAutoConfiguration implements BeanClassLoaderAware {
|
||||
|
||||
private static final Class<DubboTransported> DUBBO_TRANSPORTED_CLASS = DubboTransported.class;
|
||||
|
||||
@ -69,6 +70,8 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration {
|
||||
@Autowired(required = false)
|
||||
private Map<String, RestTemplate> restTemplates = Collections.emptyMap();
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Adapt the {@link RestTemplate} beans that are annotated {@link LoadBalanced @LoadBalanced} and
|
||||
* {@link LoadBalanced @LoadBalanced} when Spring Boot application started
|
||||
@ -117,10 +120,14 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration {
|
||||
|
||||
if (index > -1) {
|
||||
interceptors.set(index, new DubboAdapterLoadBalancerInterceptor(repository, loadBalancerInterceptor,
|
||||
restTemplate.getMessageConverters()));
|
||||
restTemplate.getMessageConverters(),classLoader));
|
||||
}
|
||||
|
||||
restTemplate.setInterceptors(interceptors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.alibaba.dubbo.client.loadbalancer;
|
||||
|
||||
import com.alibaba.dubbo.config.spring.ReferenceBean;
|
||||
import com.alibaba.dubbo.rpc.service.GenericException;
|
||||
import com.alibaba.dubbo.rpc.service.GenericService;
|
||||
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata;
|
||||
@ -53,12 +54,16 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt
|
||||
|
||||
private final List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
private final DubboClientHttpResponseFactory clientHttpResponseFactory;
|
||||
|
||||
public DubboAdapterLoadBalancerInterceptor(DubboServiceMetadataRepository dubboServiceMetadataRepository,
|
||||
LoadBalancerInterceptor loadBalancerInterceptor,
|
||||
List<HttpMessageConverter<?>> messageConverters) {
|
||||
List<HttpMessageConverter<?>> messageConverters,
|
||||
ClassLoader classLoader) {
|
||||
this.repository = dubboServiceMetadataRepository;
|
||||
this.loadBalancerInterceptor = loadBalancerInterceptor;
|
||||
this.messageConverters = messageConverters;
|
||||
this.clientHttpResponseFactory = new DubboClientHttpResponseFactory(messageConverters, classLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -72,30 +77,44 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt
|
||||
|
||||
repository.initialize(serviceName);
|
||||
|
||||
RequestMetadata requestMetadata = buildRequestMetadata(request, uriComponents);
|
||||
RequestMetadata clientMetadata = buildRequestMetadata(request, uriComponents);
|
||||
|
||||
ReferenceBean<GenericService> referenceBean =
|
||||
repository.getReferenceBean(serviceName, requestMetadata);
|
||||
RestMethodMetadata restMethodMetadata = repository.getRestMethodMetadata(serviceName, clientMetadata);
|
||||
|
||||
RestMethodMetadata restMethodMetadata = repository.getRestMethodMetadata(serviceName, requestMetadata);
|
||||
ReferenceBean<GenericService> referenceBean = repository.getReferenceBean(serviceName, clientMetadata);
|
||||
|
||||
if (referenceBean == null || restMethodMetadata == null) {
|
||||
return loadBalancerInterceptor.intercept(request, body, execution);
|
||||
}
|
||||
|
||||
Object result = null;
|
||||
GenericException exception = null;
|
||||
|
||||
try {
|
||||
result = invokeService(restMethodMetadata, referenceBean, clientMetadata);
|
||||
} catch (GenericException e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
return clientHttpResponseFactory.build(result, exception, clientMetadata, restMethodMetadata);
|
||||
}
|
||||
|
||||
private Object invokeService(RestMethodMetadata restMethodMetadata, ReferenceBean<GenericService> referenceBean,
|
||||
RequestMetadata clientMetadata) throws GenericException {
|
||||
|
||||
MethodMetadata methodMetadata = restMethodMetadata.getMethod();
|
||||
|
||||
String methodName = methodMetadata.getName();
|
||||
|
||||
String[] parameterTypes = parameterResolver.resolveParameterTypes(methodMetadata);
|
||||
|
||||
Object[] parameters = parameterResolver.resolveParameters(restMethodMetadata, request, uriComponents);
|
||||
Object[] parameters = parameterResolver.resolveParameters(restMethodMetadata, clientMetadata);
|
||||
|
||||
GenericService genericService = referenceBean.get();
|
||||
|
||||
Object result = genericService.$invoke(methodName, parameterTypes, parameters);
|
||||
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static RequestMetadata buildRequestMetadata(HttpRequest request, UriComponents uriComponents) {
|
||||
|
@ -33,21 +33,19 @@ import java.io.InputStream;
|
||||
*/
|
||||
class DubboClientHttpResponse implements ClientHttpResponse {
|
||||
|
||||
private final Object result;
|
||||
|
||||
private final GenericException exception;
|
||||
|
||||
private final HttpStatus httpStatus;
|
||||
|
||||
private final String statusText;
|
||||
|
||||
private final HttpHeaders httpHeaders = new HttpHeaders();
|
||||
|
||||
public DubboClientHttpResponse(Object result, GenericException exception) {
|
||||
this.result = result;
|
||||
this.exception = exception;
|
||||
private final DubboHttpOutputMessage httpOutputMessage;
|
||||
|
||||
public DubboClientHttpResponse(DubboHttpOutputMessage httpOutputMessage, GenericException exception) {
|
||||
this.httpStatus = exception != null ? HttpStatus.INTERNAL_SERVER_ERROR : HttpStatus.OK;
|
||||
this.statusText = exception != null ? exception.getExceptionMessage() : httpStatus.getReasonPhrase();
|
||||
this.httpOutputMessage = httpOutputMessage;
|
||||
this.httpHeaders.putAll(httpOutputMessage.getHeaders());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -67,12 +65,11 @@ class DubboClientHttpResponse implements ClientHttpResponse {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() throws IOException {
|
||||
return null;
|
||||
return httpOutputMessage.getBody().getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.client.loadbalancer;
|
||||
|
||||
import com.alibaba.dubbo.rpc.service.GenericException;
|
||||
|
||||
import org.springframework.cloud.alibaba.dubbo.http.converter.HttpMessageConverterHolder;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.HttpMessageConverterResolver;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Dubbo {@link ClientHttpResponse} Factory
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
class DubboClientHttpResponseFactory {
|
||||
|
||||
private final HttpMessageConverterResolver httpMessageConverterResolver;
|
||||
|
||||
public DubboClientHttpResponseFactory(List<HttpMessageConverter<?>> messageConverters, ClassLoader classLoader) {
|
||||
this.httpMessageConverterResolver = new HttpMessageConverterResolver(messageConverters, classLoader);
|
||||
}
|
||||
|
||||
public ClientHttpResponse build(Object result, GenericException exception,
|
||||
RequestMetadata requestMetadata, RestMethodMetadata restMethodMetadata) {
|
||||
|
||||
DubboHttpOutputMessage httpOutputMessage = new DubboHttpOutputMessage();
|
||||
|
||||
HttpMessageConverterHolder httpMessageConverterHolder = httpMessageConverterResolver.resolve(requestMetadata, restMethodMetadata);
|
||||
|
||||
if (httpMessageConverterHolder != null) {
|
||||
MediaType mediaType = httpMessageConverterHolder.getMediaType();
|
||||
HttpMessageConverter converter = httpMessageConverterHolder.getConverter();
|
||||
try {
|
||||
converter.write(result, mediaType, httpOutputMessage);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return new DubboClientHttpResponse(httpOutputMessage, exception);
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@ import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.util.FastByteArrayOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Dubbo {@link HttpOutputMessage} implementation
|
||||
@ -31,7 +30,7 @@ import java.io.OutputStream;
|
||||
class DubboHttpOutputMessage implements HttpOutputMessage {
|
||||
|
||||
@Override
|
||||
public OutputStream getBody() throws IOException {
|
||||
public FastByteArrayOutputStream getBody() throws IOException {
|
||||
return new FastByteArrayOutputStream();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.http.converter;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
|
||||
/**
|
||||
* {@link HttpMessageConverter} Holder with {@link MediaType}.
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public class HttpMessageConverterHolder {
|
||||
|
||||
private final MediaType mediaType;
|
||||
|
||||
private final HttpMessageConverter<?> converter;
|
||||
|
||||
public HttpMessageConverterHolder(MediaType mediaType, HttpMessageConverter<?> converter) {
|
||||
this.mediaType = mediaType;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public MediaType getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
public HttpMessageConverter<?> getConverter() {
|
||||
return converter;
|
||||
}
|
||||
}
|
@ -21,12 +21,14 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import feign.RequestTemplate;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -54,9 +56,9 @@ public class RequestMetadata {
|
||||
@JsonProperty("headers")
|
||||
private HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
private List<String> consumes = new LinkedList<>();
|
||||
private Set<String> consumes = new LinkedHashSet<>();
|
||||
|
||||
private List<String> produces = new LinkedList<>();
|
||||
private Set<String> produces = new LinkedHashSet<>();
|
||||
|
||||
public RequestMetadata() {
|
||||
}
|
||||
@ -100,19 +102,19 @@ public class RequestMetadata {
|
||||
headers(headers);
|
||||
}
|
||||
|
||||
public List<String> getConsumes() {
|
||||
public Set<String> getConsumes() {
|
||||
return consumes;
|
||||
}
|
||||
|
||||
public void setConsumes(List<String> consumes) {
|
||||
public void setConsumes(Set<String> consumes) {
|
||||
this.consumes = consumes;
|
||||
}
|
||||
|
||||
public List<String> getProduces() {
|
||||
public Set<String> getProduces() {
|
||||
return produces;
|
||||
}
|
||||
|
||||
public void setProduces(List<String> produces) {
|
||||
public void setProduces(Set<String> produces) {
|
||||
this.produces = produces;
|
||||
}
|
||||
|
||||
@ -137,6 +139,14 @@ public class RequestMetadata {
|
||||
return toMediaTypes(produces);
|
||||
}
|
||||
|
||||
public String getParameter(String name) {
|
||||
return this.params.getFirst(name);
|
||||
}
|
||||
|
||||
public String getHeader(String name) {
|
||||
return this.headers.getFirst(name);
|
||||
}
|
||||
|
||||
public RequestMetadata addParam(String name, String value) {
|
||||
add(name, value, this.params);
|
||||
return this;
|
||||
@ -153,6 +163,7 @@ public class RequestMetadata {
|
||||
}
|
||||
|
||||
private <T extends Collection<String>> RequestMetadata headers(Map<String, T> headers) {
|
||||
if (!CollectionUtils.isEmpty(headers)) {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
// Add all headers
|
||||
addAll(headers, httpHeaders);
|
||||
@ -160,6 +171,7 @@ public class RequestMetadata {
|
||||
mediaTypes(httpHeaders, HttpHeaders.CONTENT_TYPE, this.consumes);
|
||||
mediaTypes(httpHeaders, HttpHeaders.ACCEPT, this.produces);
|
||||
this.headers.putAll(httpHeaders);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -199,7 +211,7 @@ public class RequestMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
private static void mediaTypes(HttpHeaders httpHeaders, String headerName, List<String> destination) {
|
||||
private static void mediaTypes(HttpHeaders httpHeaders, String headerName, Collection<String> destination) {
|
||||
List<String> value = httpHeaders.get(headerName);
|
||||
List<MediaType> mediaTypes = parseMediaTypes(value);
|
||||
destination.addAll(toMediaTypeValues(mediaTypes));
|
||||
@ -213,11 +225,11 @@ public class RequestMetadata {
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<MediaType> toMediaTypes(List<String> mediaTypeValues) {
|
||||
private static List<MediaType> toMediaTypes(Collection<String> mediaTypeValues) {
|
||||
if (mediaTypeValues.isEmpty()) {
|
||||
return Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
return parseMediaTypes(mediaTypeValues);
|
||||
return parseMediaTypes(new LinkedList<>(mediaTypeValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.alibaba.dubbo.metadata.resolver;
|
||||
|
||||
import org.springframework.cloud.alibaba.dubbo.http.converter.HttpMessageConverterHolder;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link HttpMessageConverter} Resolver
|
||||
*
|
||||
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
|
||||
*/
|
||||
public class HttpMessageConverterResolver {
|
||||
|
||||
private static final MediaType MEDIA_TYPE_APPLICATION = new MediaType("application");
|
||||
|
||||
private final List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
private final List<MediaType> allSupportedMediaTypes;
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public HttpMessageConverterResolver(List<HttpMessageConverter<?>> messageConverters, ClassLoader classLoader) {
|
||||
this.messageConverters = messageConverters;
|
||||
this.allSupportedMediaTypes = getAllSupportedMediaTypes(messageConverters);
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the most match {@link HttpMessageConverter} from {@link RequestMetadata}
|
||||
*
|
||||
* @param requestMetadata {@link RequestMetadata}
|
||||
* @param restMethodMetadata {@link RestMethodMetadata}
|
||||
* @return
|
||||
*/
|
||||
public HttpMessageConverterHolder resolve(RequestMetadata requestMetadata, RestMethodMetadata restMethodMetadata) {
|
||||
|
||||
HttpMessageConverterHolder httpMessageConverterHolder = null;
|
||||
|
||||
Class<?> returnValueClass = resolveReturnValueClass(restMethodMetadata);
|
||||
|
||||
/**
|
||||
* @see AbstractMessageConverterMethodProcessor#writeWithMessageConverters(Object, MethodParameter, ServletServerHttpRequest, ServletServerHttpResponse)
|
||||
*/
|
||||
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(requestMetadata);
|
||||
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(restMethodMetadata, returnValueClass);
|
||||
|
||||
Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();
|
||||
for (MediaType requestedType : requestedMediaTypes) {
|
||||
for (MediaType producibleType : producibleMediaTypes) {
|
||||
if (requestedType.isCompatibleWith(producibleType)) {
|
||||
compatibleMediaTypes.add(getMostSpecificMediaType(requestedType, producibleType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (compatibleMediaTypes.isEmpty()) {
|
||||
return httpMessageConverterHolder;
|
||||
}
|
||||
|
||||
List<MediaType> mediaTypes = new ArrayList<>(compatibleMediaTypes);
|
||||
|
||||
MediaType.sortBySpecificityAndQuality(mediaTypes);
|
||||
|
||||
MediaType selectedMediaType = null;
|
||||
for (MediaType mediaType : mediaTypes) {
|
||||
if (mediaType.isConcrete()) {
|
||||
selectedMediaType = mediaType;
|
||||
break;
|
||||
} else if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) {
|
||||
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedMediaType != null) {
|
||||
selectedMediaType = selectedMediaType.removeQualityValue();
|
||||
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
|
||||
if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
|
||||
httpMessageConverterHolder = new HttpMessageConverterHolder(selectedMediaType, messageConverter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return httpMessageConverterHolder;
|
||||
}
|
||||
|
||||
private Class<?> resolveReturnValueClass(RestMethodMetadata restMethodMetadata) {
|
||||
String returnClassName = restMethodMetadata.getMethod().getReturnType();
|
||||
return ClassUtils.resolveClassName(returnClassName, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the {@link MediaType media-types}
|
||||
*
|
||||
* @param requestMetadata {@link RequestMetadata} from client side
|
||||
* @return non-null {@link List}
|
||||
*/
|
||||
private List<MediaType> getAcceptableMediaTypes(RequestMetadata requestMetadata) {
|
||||
return requestMetadata.getProduceMediaTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns
|
||||
* the media types that can be produced: <ul> <li>The producible media types specified in the request mappings, or
|
||||
* <li>Media types of configured converters that can write the specific return value, or <li>{@link MediaType#ALL}
|
||||
* </ul>
|
||||
*
|
||||
* @param restMethodMetadata {@link RestMethodMetadata} from server side
|
||||
* @param returnValueClass the class of return value
|
||||
* @return non-null {@link List}
|
||||
*/
|
||||
private List<MediaType> getProducibleMediaTypes(RestMethodMetadata restMethodMetadata, Class<?> returnValueClass) {
|
||||
RequestMetadata serverRequestMetadata = restMethodMetadata.getRequest();
|
||||
List<MediaType> mediaTypes = serverRequestMetadata.getProduceMediaTypes();
|
||||
if (!CollectionUtils.isEmpty(mediaTypes)) { // Empty
|
||||
return mediaTypes;
|
||||
} else if (!this.allSupportedMediaTypes.isEmpty()) {
|
||||
List<MediaType> result = new ArrayList<>();
|
||||
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||
if (converter.canWrite(returnValueClass, null)) {
|
||||
result.addAll(converter.getSupportedMediaTypes());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return Collections.singletonList(MediaType.ALL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the media types
|
||||
* supported by all provided message converters sorted by specificity via {@link
|
||||
* MediaType#sortBySpecificity(List)}.
|
||||
*
|
||||
* @param messageConverters
|
||||
* @return
|
||||
*/
|
||||
private List<MediaType> getAllSupportedMediaTypes(List<HttpMessageConverter<?>> messageConverters) {
|
||||
Set<MediaType> allSupportedMediaTypes = new LinkedHashSet<MediaType>();
|
||||
for (HttpMessageConverter<?> messageConverter : messageConverters) {
|
||||
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
|
||||
}
|
||||
List<MediaType> result = new ArrayList<MediaType>(allSupportedMediaTypes);
|
||||
MediaType.sortBySpecificity(result);
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the more specific of the acceptable and the producible media types
|
||||
* with the q-value of the former.
|
||||
*/
|
||||
private MediaType getMostSpecificMediaType(MediaType acceptType, MediaType produceType) {
|
||||
MediaType produceTypeToUse = produceType.copyQualityValue(acceptType);
|
||||
return (MediaType.SPECIFICITY_COMPARATOR.compare(acceptType, produceTypeToUse) <= 0 ? acceptType : produceTypeToUse);
|
||||
}
|
||||
}
|
@ -20,9 +20,7 @@ import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.MethodParameterMetadata;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata;
|
||||
import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@ -37,8 +35,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class ParameterResolver {
|
||||
|
||||
|
||||
public Object[] resolveParameters(RestMethodMetadata restMethodMetadata, HttpRequest request, UriComponents uriComponents) {
|
||||
public Object[] resolveParameters(RestMethodMetadata restMethodMetadata, RequestMetadata clientMetadata) {
|
||||
|
||||
MethodMetadata methodMetadata = restMethodMetadata.getMethod();
|
||||
|
||||
@ -56,26 +53,24 @@ public class ParameterResolver {
|
||||
|
||||
String name = getName(indexToName, index);
|
||||
|
||||
parameters[index] = getValue(requestMetadata, request, uriComponents, name);
|
||||
parameters[index] = getValue(requestMetadata, clientMetadata, name);
|
||||
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private String getValue(RequestMetadata requestMetadata, HttpRequest request, UriComponents uriComponents, String name) {
|
||||
|
||||
private String getValue(RequestMetadata serverMetadata, RequestMetadata clientMetadata, String name) {
|
||||
String value = null;
|
||||
Set<String> paramNames = requestMetadata.getParamNames();
|
||||
Set<String> headerNames = requestMetadata.getHeaderNames();
|
||||
|
||||
Set<String> paramNames = serverMetadata.getParamNames();
|
||||
Set<String> headerNames = serverMetadata.getHeaderNames();
|
||||
if (paramNames.contains(name)) {
|
||||
value = uriComponents.getQueryParams().getFirst(name);
|
||||
value = clientMetadata.getParameter(name);
|
||||
} else if (headerNames.contains(name)) {
|
||||
value = request.getHeaders().getFirst(name);
|
||||
value = clientMetadata.getHeader(name);
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
private String getName(Map<Integer, Collection<String>> indexToName, int index) {
|
||||
|
@ -30,14 +30,12 @@ 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.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
@ -111,12 +109,15 @@ public class DubboSpringCloudBootstrap {
|
||||
@Bean
|
||||
public ApplicationRunner restTemplateRunner() {
|
||||
return arguments -> {
|
||||
System.out.println(restTemplate.getForEntity("http://spring-cloud-alibaba-dubbo/echo?message=小马哥", String.class));
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("name", "小马哥");
|
||||
data.put("age", 33);
|
||||
data.put("height", 173);
|
||||
System.out.println(restTemplate.postForEntity("http://spring-cloud-alibaba-dubbo/toString", data, String.class));
|
||||
ResponseEntity<String> entity = restTemplate.getForEntity("http://spring-cloud-alibaba-dubbo/echo?message=小马哥", String.class);
|
||||
System.out.println(entity.getHeaders());
|
||||
System.out.println(entity.getBody());
|
||||
// Still issue
|
||||
// Map<String, Object> data = new HashMap<>();
|
||||
// data.put("name", "小马哥");
|
||||
// data.put("age", 33);
|
||||
// data.put("height", 173);
|
||||
// System.out.println(restTemplate.postForEntity("http://spring-cloud-alibaba-dubbo/toString", data, String.class));
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user