diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceAutoConfiguration.java index f1fd1e42..f3f9a81f 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceAutoConfiguration.java @@ -19,7 +19,7 @@ package org.springframework.cloud.alibaba.dubbo.autoconfigure; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory; import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory; -import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestBodyServerParameterResolver; +import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestBodyServiceParameterResolver; import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestParamServiceParameterResolver; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -43,7 +43,7 @@ public class DubboServiceAutoConfiguration { @Import(value = { DubboGenericServiceExecutionContextFactory.class, RequestParamServiceParameterResolver.class, - RequestBodyServerParameterResolver.class, + RequestBodyServiceParameterResolver.class, }) static class ParameterResolversConfiguration { } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java index 7e709d1f..6e7c2c4b 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java @@ -19,7 +19,7 @@ package org.springframework.cloud.alibaba.dubbo.client.loadbalancer; import com.alibaba.dubbo.rpc.service.GenericException; import com.alibaba.dubbo.rpc.service.GenericService; -import org.springframework.cloud.alibaba.dubbo.http.DefaultServerHttpRequest; +import org.springframework.cloud.alibaba.dubbo.http.DefaultHttpServerRequest; import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; @@ -35,12 +35,13 @@ import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; import java.io.IOException; import java.net.URI; import java.util.List; +import static org.springframework.web.util.UriComponentsBuilder.fromUri; + /** * Dubbo {@link ClientHttpRequestInterceptor} implementation to adapt {@link LoadBalancerInterceptor} * @@ -81,13 +82,11 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt URI originalUri = request.getURI(); - UriComponents uriComponents = UriComponentsBuilder.fromUri(originalUri).build(true); - String serviceName = originalUri.getHost(); repository.initialize(serviceName); - RequestMetadata clientMetadata = buildRequestMetadata(request, uriComponents); + RequestMetadata clientMetadata = buildRequestMetadata(request); DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, clientMetadata); @@ -95,12 +94,12 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt return loadBalancerInterceptor.intercept(request, body, execution); } - RestMethodMetadata restMethodMetadata = dubboServiceMetadata.getRestMethodMetadata(); + RestMethodMetadata dubboRestMethodMetadata = dubboServiceMetadata.getRestMethodMetadata(); GenericService genericService = serviceFactory.create(dubboServiceMetadata, dubboTransportedMetadata); - DubboGenericServiceExecutionContext context = contextFactory.create(restMethodMetadata, - new DefaultServerHttpRequest(request, body)); + DubboGenericServiceExecutionContext context = contextFactory.create(dubboRestMethodMetadata, + new DefaultHttpServerRequest(request, body)); Object result = null; GenericException exception = null; @@ -111,10 +110,11 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt exception = e; } - return clientHttpResponseFactory.build(result, exception, clientMetadata, restMethodMetadata); + return clientHttpResponseFactory.build(result, exception, clientMetadata, dubboRestMethodMetadata); } - public static RequestMetadata buildRequestMetadata(HttpRequest request, UriComponents uriComponents) { + public static RequestMetadata buildRequestMetadata(HttpRequest request) { + UriComponents uriComponents = fromUri(request.getURI()).build(true); RequestMetadata requestMetadata = new RequestMetadata(); requestMetadata.setPath(uriComponents.getPath()); requestMetadata.setMethod(request.getMethod().name()); diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/DefaultServerHttpRequest.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/DefaultHttpServerRequest.java similarity index 65% rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/DefaultServerHttpRequest.java rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/DefaultHttpServerRequest.java index 4adc8131..69db5848 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/DefaultServerHttpRequest.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/DefaultHttpServerRequest.java @@ -16,41 +16,50 @@ */ package org.springframework.cloud.alibaba.dubbo.http; - +import org.springframework.http.HttpCookie; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; -import org.springframework.http.server.ServerHttpAsyncRequestControl; -import org.springframework.http.server.ServerHttpRequest; -import org.springframework.http.server.ServerHttpResponse; +import org.springframework.util.MultiValueMap; import java.io.IOException; import java.io.InputStream; -import java.net.InetSocketAddress; import java.net.URI; -import java.security.Principal; + +import static org.springframework.cloud.alibaba.dubbo.http.util.HttpUtils.getParameters; +import static org.springframework.cloud.alibaba.dubbo.http.util.HttpUtils.parseCookies; +import static org.springframework.http.HttpHeaders.readOnlyHttpHeaders; /** - * Default {@link ServerHttpRequest} implementation + * Default {@link HttpServerRequest} implementation * * @author Mercy */ -public class DefaultServerHttpRequest implements ServerHttpRequest { +public class DefaultHttpServerRequest implements HttpServerRequest { private final HttpMethod httpMethod; private final URI uri; + private final String path; + + private final MultiValueMap queryParams; + private final HttpHeaders httpHeaders; + private final MultiValueMap cookies; + private final HttpInputMessage httpInputMessage; - public DefaultServerHttpRequest(HttpRequest httpRequest, byte[] body) { + public DefaultHttpServerRequest(HttpRequest httpRequest, byte[] body) { this.httpMethod = httpRequest.getMethod(); this.uri = httpRequest.getURI(); - this.httpHeaders = httpRequest.getHeaders(); + this.path = uri.getPath(); + this.httpHeaders = readOnlyHttpHeaders(httpRequest.getHeaders()); + this.queryParams = getParameters(httpRequest); this.httpInputMessage = new ByteArrayHttpInputMessage(body); + this.cookies = parseCookies(httpHeaders); } @Override @@ -79,22 +88,17 @@ public class DefaultServerHttpRequest implements ServerHttpRequest { } @Override - public Principal getPrincipal() { - throw new UnsupportedOperationException(); + public String getPath() { + return path; } @Override - public InetSocketAddress getLocalAddress() { - throw new UnsupportedOperationException(); + public MultiValueMap getQueryParams() { + return queryParams; } @Override - public InetSocketAddress getRemoteAddress() { - throw new UnsupportedOperationException(); - } - - @Override - public ServerHttpAsyncRequestControl getAsyncRequestControl(ServerHttpResponse response) { - throw new UnsupportedOperationException(); + public MultiValueMap getCookies() { + return cookies; } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/HttpServerRequest.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/HttpServerRequest.java new file mode 100644 index 00000000..7bb6dbff --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/HttpServerRequest.java @@ -0,0 +1,48 @@ +/* + * 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; + +import org.springframework.http.HttpCookie; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpRequest; +import org.springframework.util.MultiValueMap; + +/** + * HTTP Server Request + * + * @author Mercy + */ +public interface HttpServerRequest extends HttpRequest, HttpInputMessage { + + /** + * Return a path of current HTTP request + * + * @return + */ + String getPath(); + + /** + * Return a read-only map with parsed and decoded query parameter values. + */ + MultiValueMap getQueryParams(); + + /** + * Return a read-only map of cookies sent by the client. + */ + MultiValueMap getCookies(); + +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/util/HttpUtils.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/util/HttpUtils.java index 41dc0de6..81722ccc 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/util/HttpUtils.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/http/util/HttpUtils.java @@ -16,6 +16,8 @@ */ package org.springframework.cloud.alibaba.dubbo.http.util; +import org.springframework.http.HttpCookie; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -31,8 +33,11 @@ import java.util.List; import java.util.Map; import java.util.Set; +import static org.springframework.http.HttpHeaders.COOKIE; +import static org.springframework.util.CollectionUtils.unmodifiableMultiValueMap; import static org.springframework.util.StringUtils.delimitedListToStringArray; import static org.springframework.util.StringUtils.trimAllWhitespace; +import static org.springframework.util.StringUtils.trimWhitespace; /** * Http Utilities class @@ -47,6 +52,8 @@ public abstract class HttpUtils { private static final String AND = "&"; + private static final String SEMICOLON = ";"; + /** * The empty value */ @@ -71,7 +78,6 @@ public abstract class HttpUtils { * @return The query parameters */ public static MultiValueMap getParameters(String queryString) { - MultiValueMap parameters = new LinkedMultiValueMap<>(); return getParameters(delimitedListToStringArray(queryString, AND)); } @@ -93,7 +99,7 @@ public abstract class HttpUtils { addParam(parameters, name, value); } } - return parameters; + return unmodifiableMultiValueMap(parameters); } /** @@ -107,6 +113,31 @@ public abstract class HttpUtils { return getParameters(Arrays.asList(pairs)); } + /** + * Parse a read-only {@link MultiValueMap} of {@link HttpCookie} from {@link HttpHeaders} + * + * @param httpHeaders {@link HttpHeaders} + * @return non-null, the key is a cookie name , the value is {@link HttpCookie} + */ + public static MultiValueMap parseCookies(HttpHeaders httpHeaders) { + + String cookie = httpHeaders.getFirst(COOKIE); + + String[] cookieNameAndValues = StringUtils.delimitedListToStringArray(cookie, SEMICOLON); + + MultiValueMap cookies = new LinkedMultiValueMap<>(cookieNameAndValues.length); + + for (String cookeNameAndValue : cookieNameAndValues) { + String[] nameAndValue = delimitedListToStringArray(trimWhitespace(cookeNameAndValue), EQUAL); + String name = nameAndValue[0]; + String value = nameAndValue.length < 2 ? null : nameAndValue[1]; + HttpCookie httpCookie = new HttpCookie(name, value); + cookies.add(name, httpCookie); + } + + return unmodifiableMultiValueMap(cookies); + } + /** * To the name and value line sets * diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodMetadata.java index ec62c8a5..8648f7c1 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodMetadata.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodMetadata.java @@ -123,4 +123,14 @@ public class MethodMetadata { public int hashCode() { return Objects.hash(name, returnType, params); } + + @Override + public String toString() { + return "MethodMetadata{" + + "name='" + name + '\'' + + ", returnType='" + returnType + '\'' + + ", params=" + params + + ", method=" + method + + '}'; + } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodParameterMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodParameterMetadata.java index a7f58e46..0abf2b0e 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodParameterMetadata.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/MethodParameterMetadata.java @@ -73,4 +73,13 @@ public class MethodParameterMetadata { public int hashCode() { return Objects.hash(index, name, type); } + + @Override + public String toString() { + return "MethodParameterMetadata{" + + "index=" + index + + ", name='" + name + '\'' + + ", type='" + type + '\'' + + '}'; + } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java index ba01e527..edbcf46a 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java @@ -41,7 +41,7 @@ public class RestMethodMetadata { @JsonProperty("url-index") private Integer urlIndex; - @JsonProperty("body-index") + @JsonProperty("setBody-index") private Integer bodyIndex; @JsonProperty("header-map-index") @@ -56,7 +56,7 @@ public class RestMethodMetadata { @JsonProperty("return-type") private String returnType; - @JsonProperty("body-type") + @JsonProperty("setBody-type") private String bodyType; @JsonProperty("index-to-name") @@ -214,4 +214,21 @@ public class RestMethodMetadata { return resolvableType.resolve().getName(); } + @Override + public String toString() { + return "RestMethodMetadata{" + + "method=" + method + + ", request=" + request + + ", urlIndex=" + urlIndex + + ", bodyIndex=" + bodyIndex + + ", headerMapIndex=" + headerMapIndex + + ", queryMapIndex=" + queryMapIndex + + ", queryMapEncoded=" + queryMapEncoded + + ", returnType='" + returnType + '\'' + + ", bodyType='" + bodyType + '\'' + + ", indexToName=" + indexToName + + ", formParams=" + formParams + + ", indexToEncoded=" + indexToEncoded + + '}'; + } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java index 4e30381c..30345161 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -68,7 +68,7 @@ public class DubboServiceMetadataRepository { if (isEmpty(serviceRestMetadataSet)) { if (logger.isWarnEnabled()) { - logger.warn("The Spring Cloud application[name : {}] does not expose The REST metadata in the Dubbo services." + logger.warn("The Spring application[name : {}] does not expose The REST metadata in the Dubbo services." , serviceName); } return; @@ -85,6 +85,10 @@ public class DubboServiceMetadataRepository { metadataMap.put(matcher, metadata); }); } + + if (logger.isInfoEnabled()) { + logger.info("The REST metadata in the dubbo services has been loaded in the Spring application[name : {}]", serviceName); + } } /** @@ -98,31 +102,42 @@ public class DubboServiceMetadataRepository { return match(repository, serviceName, requestMetadata); } - private static T match(Map> repository, String serviceName, - RequestMetadata requestMetadata) { - Map map = repository.get(serviceName); - if (isEmpty(map)) { - return null; - } - RequestMetadataMatcher matcher = new RequestMetadataMatcher(requestMetadata); - T object = map.get(matcher); - if (object == null) { // Can't match exactly - // Require to match one by one - for (Map.Entry entry : map.entrySet()) { - RequestMetadataMatcher possibleMatcher = entry.getKey(); - HttpRequest request = builder() - .method(requestMetadata.getMethod()) - .path(requestMetadata.getPath()) - .params(requestMetadata.getParams()) - .headers(requestMetadata.getHeaders()) - .build(); + private T match(Map> repository, String serviceName, + RequestMetadata requestMetadata) { - if (possibleMatcher.match(request)) { - object = entry.getValue(); - break; + Map map = repository.get(serviceName); + + T object = null; + + if (!isEmpty(map)) { + RequestMetadataMatcher matcher = new RequestMetadataMatcher(requestMetadata); + object = map.get(matcher); + if (object == null) { // Can't match exactly + // Require to match one by one + for (Map.Entry entry : map.entrySet()) { + RequestMetadataMatcher possibleMatcher = entry.getKey(); + HttpRequest request = builder() + .method(requestMetadata.getMethod()) + .path(requestMetadata.getPath()) + .params(requestMetadata.getParams()) + .headers(requestMetadata.getHeaders()) + .build(); + + if (possibleMatcher.match(request)) { + object = entry.getValue(); + break; + } } } } + + if (object == null) { + if (logger.isWarnEnabled()) { + logger.warn("DubboServiceMetadata can't be found in the Spring application [%s] and %s", + serviceName, requestMetadata); + } + } + return object; } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboTransportedMethodMetadataResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboTransportedMethodMetadataResolver.java index 1d0d4557..d1aa6389 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboTransportedMethodMetadataResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/DubboTransportedMethodMetadataResolver.java @@ -20,7 +20,7 @@ import feign.Contract; import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported; import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata; -import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.env.PropertyResolver; @@ -51,14 +51,17 @@ public class DubboTransportedMethodMetadataResolver { this.contract = contract; } - public Map resolve(Class targetType) { + public Map resolve(Class targetType) { Set dubboTransportedMethodMetadataSet = resolveDubboTransportedMethodMetadataSet(targetType); - Map requestMetadataMap = resolveRequestMetadataMap(targetType); + Map restMethodMetadataMap = resolveRestRequestMetadataMap(targetType); return dubboTransportedMethodMetadataSet .stream() - .collect(Collectors.toMap(methodMetadata -> methodMetadata, methodMetadata -> - requestMetadataMap.get(configKey(targetType, methodMetadata.getMethod())) + .collect(Collectors.toMap(methodMetadata -> methodMetadata, methodMetadata -> { + RestMethodMetadata restMethodMetadata = restMethodMetadataMap.get(configKey(targetType, methodMetadata.getMethod())); + restMethodMetadata.setMethod(methodMetadata.getMethodMetadata()); + return restMethodMetadata; + } )); } @@ -79,13 +82,13 @@ public class DubboTransportedMethodMetadataResolver { } - private Map resolveRequestMetadataMap(Class targetType) { + private Map resolveRestRequestMetadataMap(Class targetType) { return contract.parseAndValidatateMetadata(targetType) - .stream().collect(Collectors.toMap(feign.MethodMetadata::configKey, this::requestMetadata)); + .stream().collect(Collectors.toMap(feign.MethodMetadata::configKey, this::restMethodMetadata)); } - private RequestMetadata requestMetadata(feign.MethodMetadata methodMetadata) { - return new RequestMetadata(methodMetadata.template()); + private RestMethodMetadata restMethodMetadata(feign.MethodMetadata methodMetadata) { + return new RestMethodMetadata(methodMetadata); } private DubboTransportedMethodMetadata createDubboTransportedMethodMetadata(Method method, diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/MetadataResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/MetadataResolver.java index 4956e387..922ce6d3 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/MetadataResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/resolver/MetadataResolver.java @@ -17,6 +17,7 @@ package org.springframework.cloud.alibaba.dubbo.metadata.resolver; import com.alibaba.dubbo.config.spring.ServiceBean; + import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandler.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandler.java index 1c1b8eb5..95dd73c0 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandler.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/DubboInvocationHandler.java @@ -33,41 +33,39 @@ import java.util.Map; */ public class DubboInvocationHandler implements InvocationHandler { - private final Map genericServicesMap; - - private final Map restMethodMetadataMap; + private final Map feignMethodMetadataMap; private final InvocationHandler defaultInvocationHandler; private final DubboGenericServiceExecutionContextFactory contextFactory; - public DubboInvocationHandler(Map genericServicesMap, - Map restMethodMetadataMap, + public DubboInvocationHandler(Map feignMethodMetadataMap, InvocationHandler defaultInvocationHandler, DubboGenericServiceExecutionContextFactory contextFactory) { - this.genericServicesMap = genericServicesMap; - this.restMethodMetadataMap = restMethodMetadataMap; + this.feignMethodMetadataMap = feignMethodMetadataMap; this.defaultInvocationHandler = defaultInvocationHandler; this.contextFactory = contextFactory; } @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + public Object invoke(Object proxy, Method feignMethod, Object[] args) throws Throwable { - GenericService genericService = genericServicesMap.get(method); + FeignMethodMetadata feignMethodMetadata = feignMethodMetadataMap.get(feignMethod); - RestMethodMetadata restMethodMetadata = restMethodMetadataMap.get(method); - - if (genericService == null || restMethodMetadata == null) { - return defaultInvocationHandler.invoke(proxy, method, args); + if (feignMethodMetadata == null) { + return defaultInvocationHandler.invoke(proxy, feignMethod, args); } - DubboGenericServiceExecutionContext context = contextFactory.create(restMethodMetadata, args); + GenericService dubboGenericService = feignMethodMetadata.getDubboGenericService(); + RestMethodMetadata dubboRestMethodMetadata = feignMethodMetadata.getDubboRestMethodMetadata(); + RestMethodMetadata feignRestMethodMetadata = feignMethodMetadata.getFeignMethodMetadata(); + + DubboGenericServiceExecutionContext context = contextFactory.create(dubboRestMethodMetadata, feignRestMethodMetadata, args); String methodName = context.getMethodName(); String[] parameterTypes = context.getParameterTypes(); Object[] parameters = context.getParameters(); - return genericService.$invoke(methodName, parameterTypes, parameters); + return dubboGenericService.$invoke(methodName, parameterTypes, parameters); } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/FeignMethodMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/FeignMethodMetadata.java new file mode 100644 index 00000000..0eda4d1b --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/FeignMethodMetadata.java @@ -0,0 +1,57 @@ +/* + * 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.openfeign; + +import com.alibaba.dubbo.rpc.service.GenericService; + +import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; + +import java.lang.reflect.Method; + +/** + * Feign {@link Method} Metadata + * + * @author Mercy + */ +class FeignMethodMetadata { + + private final GenericService dubboGenericService; + + private final RestMethodMetadata dubboRestMethodMetadata; + + private final RestMethodMetadata feignMethodMetadata; + + + FeignMethodMetadata(GenericService dubboGenericService, RestMethodMetadata dubboRestMethodMetadata, + RestMethodMetadata feignMethodMetadata) { + this.dubboGenericService = dubboGenericService; + this.dubboRestMethodMetadata = dubboRestMethodMetadata; + this.feignMethodMetadata = feignMethodMetadata; + } + + GenericService getDubboGenericService() { + return dubboGenericService; + } + + RestMethodMetadata getDubboRestMethodMetadata() { + return dubboRestMethodMetadata; + } + + RestMethodMetadata getFeignMethodMetadata() { + return feignMethodMetadata; + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java index 1b1863e7..c665c245 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java @@ -21,9 +21,13 @@ import com.alibaba.dubbo.rpc.service.GenericService; import feign.Contract; import feign.Target; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported; import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMethodMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; @@ -48,6 +52,8 @@ import static java.lang.reflect.Proxy.newProxyInstance; */ class TargeterInvocationHandler implements InvocationHandler { + private final Logger logger = LoggerFactory.getLogger(getClass()); + private final Object bean; private final Environment environment; @@ -111,37 +117,54 @@ class TargeterInvocationHandler implements InvocationHandler { DubboTransportedMethodMetadataResolver resolver = new DubboTransportedMethodMetadataResolver(environment, contract); - Map methodRequestMetadataMap = resolver.resolve(targetType); + Map feignRestMethodMetadataMap = resolver.resolve(targetType); - if (methodRequestMetadataMap.isEmpty()) { // @DubboTransported method was not found + if (feignRestMethodMetadataMap.isEmpty()) { // @DubboTransported method was not found from the Client interface + if (logger.isDebugEnabled()) { + logger.debug("@{} method was not found in the Feign target type[{}]", + DubboTransported.class.getSimpleName(), targetType.getName()); + } return null; } // Update Metadata repository.initialize(serviceName); - Map restMethodMetadataMap = new HashMap<>(); - - Map genericServicesMap = new HashMap<>(); - - methodRequestMetadataMap.forEach((dubboTransportedMethodMetadata, requestMetadata) -> { - DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, requestMetadata); - RestMethodMetadata restMethodMetadata = dubboServiceMetadata.getRestMethodMetadata(); - DubboTransportedMetadata dubboTransportedMetadata = dubboTransportedMethodMetadata.getDubboTransportedMetadata(); - GenericService genericService = dubboGenericServiceFactory.create(dubboServiceMetadata, dubboTransportedMetadata); - Method method = dubboTransportedMethodMetadata.getMethod(); - genericServicesMap.put(method, genericService); - restMethodMetadataMap.put(method, restMethodMetadata); - }); + Map feignMethodMetadataMap = getFeignMethodMetadataMap(serviceName, feignRestMethodMetadataMap); InvocationHandler defaultFeignClientInvocationHandler = Proxy.getInvocationHandler(defaultFeignClientProxy); - DubboInvocationHandler dubboInvocationHandler = new DubboInvocationHandler(genericServicesMap, restMethodMetadataMap, + DubboInvocationHandler dubboInvocationHandler = new DubboInvocationHandler(feignMethodMetadataMap, defaultFeignClientInvocationHandler, contextFactory); return dubboInvocationHandler; } + private Map getFeignMethodMetadataMap(String serviceName, + Map + feignRestMethodMetadataMap) { + Map feignMethodMetadataMap = new HashMap<>(); + + for (Map.Entry entry : feignRestMethodMetadataMap.entrySet()) { + RestMethodMetadata feignRestMethodMetadata = entry.getValue(); + RequestMetadata feignRequestMetadata = feignRestMethodMetadata.getRequest(); + DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, feignRequestMetadata); + if (dubboServiceMetadata != null) { + DubboTransportedMethodMetadata dubboTransportedMethodMetadata = entry.getKey(); + DubboTransportedMetadata dubboTransportedMetadata = dubboTransportedMethodMetadata.getDubboTransportedMetadata(); + Method method = dubboTransportedMethodMetadata.getMethod(); + GenericService dubboGenericService = dubboGenericServiceFactory.create(dubboServiceMetadata, dubboTransportedMetadata); + RestMethodMetadata dubboRestMethodMetadata = dubboServiceMetadata.getRestMethodMetadata(); + MethodMetadata methodMetadata = dubboTransportedMethodMetadata.getMethodMetadata(); + FeignMethodMetadata feignMethodMetadata = new FeignMethodMetadata(dubboGenericService, + dubboRestMethodMetadata, feignRestMethodMetadata); + feignMethodMetadataMap.put(method, feignMethodMetadata); + } + } + + return feignMethodMetadataMap; + } + private static T cast(Object object) { return (T) object; } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceExecutionContextFactory.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceExecutionContextFactory.java index a9a9e2b9..625173d3 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceExecutionContextFactory.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/DubboGenericServiceExecutionContextFactory.java @@ -17,17 +17,18 @@ package org.springframework.cloud.alibaba.dubbo.service; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.alibaba.dubbo.http.HttpServerRequest; import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.MethodParameterMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.cloud.alibaba.dubbo.service.parameter.DubboGenericServiceParameterResolver; import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.http.server.ServerHttpRequest; import javax.annotation.PostConstruct; -import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; /** * {@link DubboGenericServiceExecutionContext} Factory @@ -45,33 +46,41 @@ public class DubboGenericServiceExecutionContextFactory { AnnotationAwareOrderComparator.sort(resolvers); } - public DubboGenericServiceExecutionContext create(RestMethodMetadata restMethodMetadata, Object[] arguments) { + public DubboGenericServiceExecutionContext create(RestMethodMetadata dubboRestMethodMetadata, + RestMethodMetadata clientMethodMetadata, Object[] arguments) { - MethodMetadata methodMetadata = restMethodMetadata.getMethod(); + MethodMetadata dubboMethodMetadata = dubboRestMethodMetadata.getMethod(); - String methodName = methodMetadata.getName(); + String methodName = dubboMethodMetadata.getName(); - String[] parameterTypes = resolveParameterTypes(methodMetadata); + String[] parameterTypes = resolveParameterTypes(dubboMethodMetadata); - Object[] parameters = Arrays.copyOf(arguments, parameterTypes.length); + Object[] parameters = resolveParameters(dubboRestMethodMetadata, clientMethodMetadata, arguments); return new DubboGenericServiceExecutionContext(methodName, parameterTypes, parameters); } - - public DubboGenericServiceExecutionContext create(RestMethodMetadata restMethodMetadata, - ServerHttpRequest request) { - MethodMetadata methodMetadata = restMethodMetadata.getMethod(); + public DubboGenericServiceExecutionContext create(RestMethodMetadata dubboRestMethodMetadata, + HttpServerRequest request) { + MethodMetadata methodMetadata = dubboRestMethodMetadata.getMethod(); String methodName = methodMetadata.getName(); String[] parameterTypes = resolveParameterTypes(methodMetadata); - Object[] parameters = resolveParameters(restMethodMetadata, request); + Object[] parameters = resolveParameters(dubboRestMethodMetadata, request); return new DubboGenericServiceExecutionContext(methodName, parameterTypes, parameters); } + private Map buildParamNameToIndex(List params) { + Map paramNameToIndex = new LinkedHashMap<>(); + for (MethodParameterMetadata param : params) { + paramNameToIndex.put(param.getName(), param.getIndex()); + } + return paramNameToIndex; + } + protected String[] resolveParameterTypes(MethodMetadata methodMetadata) { List params = methodMetadata.getParams(); @@ -87,11 +96,11 @@ public class DubboGenericServiceExecutionContextFactory { return parameterTypes; } - protected Object[] resolveParameters(RestMethodMetadata restMethodMetadata, ServerHttpRequest request) { + protected Object[] resolveParameters(RestMethodMetadata dubboRestMethodMetadata, HttpServerRequest request) { - MethodMetadata methodMetadata = restMethodMetadata.getMethod(); + MethodMetadata dubboMethodMetadata = dubboRestMethodMetadata.getMethod(); - List params = methodMetadata.getParams(); + List params = dubboMethodMetadata.getParams(); Object[] parameters = new Object[params.size()]; @@ -100,8 +109,34 @@ public class DubboGenericServiceExecutionContextFactory { int index = parameterMetadata.getIndex(); for (DubboGenericServiceParameterResolver resolver : resolvers) { - if (resolver.supportParameter(restMethodMetadata, parameterMetadata)) { - parameters[index] = resolver.resolveParameter(restMethodMetadata, parameterMetadata, request); + Object parameter = resolver.resolve(dubboRestMethodMetadata, parameterMetadata, request); + if (parameter != null) { + parameters[index] = parameter; + break; + } + } + } + + return parameters; + } + + protected Object[] resolveParameters(RestMethodMetadata dubboRestMethodMetadata, + RestMethodMetadata clientRestMethodMetadata, Object[] arguments) { + + MethodMetadata dubboMethodMetadata = dubboRestMethodMetadata.getMethod(); + + List params = dubboMethodMetadata.getParams(); + + Object[] parameters = new Object[params.size()]; + + for (MethodParameterMetadata parameterMetadata : params) { + + int index = parameterMetadata.getIndex(); + + for (DubboGenericServiceParameterResolver resolver : resolvers) { + Object parameter = resolver.resolve(dubboRestMethodMetadata, parameterMetadata, clientRestMethodMetadata, arguments); + if (parameter != null) { + parameters[index] = parameter; break; } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/AbstractDubboGenericServiceParameterResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/AbstractDubboGenericServiceParameterResolver.java index ebcae398..5ad1be1b 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/AbstractDubboGenericServiceParameterResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/AbstractDubboGenericServiceParameterResolver.java @@ -30,7 +30,8 @@ import static org.springframework.util.ClassUtils.resolveClassName; * * @author Mercy */ -public abstract class AbstractDubboGenericServiceParameterResolver implements DubboGenericServiceParameterResolver, BeanClassLoaderAware { +public abstract class AbstractDubboGenericServiceParameterResolver implements DubboGenericServiceParameterResolver, + BeanClassLoaderAware { private int order; diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/DubboGenericServiceParameterResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/DubboGenericServiceParameterResolver.java index 1c302b59..58ed2263 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/DubboGenericServiceParameterResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/DubboGenericServiceParameterResolver.java @@ -18,11 +18,10 @@ package org.springframework.cloud.alibaba.dubbo.service.parameter; import com.alibaba.dubbo.rpc.service.GenericService; -import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; +import org.springframework.cloud.alibaba.dubbo.http.HttpServerRequest; import org.springframework.cloud.alibaba.dubbo.metadata.MethodParameterMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.core.Ordered; -import org.springframework.http.server.ServerHttpRequest; /** * Dubbo {@link GenericService} Parameter Resolver @@ -31,20 +30,14 @@ import org.springframework.http.server.ServerHttpRequest; */ public interface DubboGenericServiceParameterResolver extends Ordered { - /** - * Whether the given {@linkplain DubboServiceMetadata Dubbo Service Metadata} is - * supported by this resolver. - * - * @return {@code true} if this resolver supports the supplied parameter; - * {@code false} otherwise - */ - boolean supportParameter(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata); - /** * Resolves a method parameter into an argument value from a given request. * * @return */ - Object resolveParameter(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, - ServerHttpRequest request); + Object resolve(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, + HttpServerRequest request); + + Object resolve(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, + RestMethodMetadata clientRestMethodMetadata, Object[] arguments); } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestBodyServerParameterResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestBodyServiceParameterResolver.java similarity index 80% rename from spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestBodyServerParameterResolver.java rename to spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestBodyServiceParameterResolver.java index da156fe4..cf48dd9a 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestBodyServerParameterResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestBodyServiceParameterResolver.java @@ -19,13 +19,13 @@ package org.springframework.cloud.alibaba.dubbo.service.parameter; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.cloud.alibaba.dubbo.http.HttpServerRequest; import org.springframework.cloud.alibaba.dubbo.http.converter.HttpMessageConverterHolder; import org.springframework.cloud.alibaba.dubbo.http.util.HttpMessageConverterResolver; import org.springframework.cloud.alibaba.dubbo.metadata.MethodParameterMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.http.server.ServerHttpRequest; import javax.annotation.PostConstruct; import java.io.IOException; @@ -37,7 +37,7 @@ import java.util.Objects; * * @author Mercy */ -public class RequestBodyServerParameterResolver extends AbstractDubboGenericServiceParameterResolver { +public class RequestBodyServiceParameterResolver extends AbstractDubboGenericServiceParameterResolver { public static final int DEFAULT_ORDER = 7; @@ -46,7 +46,7 @@ public class RequestBodyServerParameterResolver extends AbstractDubboGenericServ private HttpMessageConverterResolver httpMessageConverterResolver; - public RequestBodyServerParameterResolver() { + public RequestBodyServiceParameterResolver() { super(); setOrder(DEFAULT_ORDER); } @@ -60,8 +60,7 @@ public class RequestBodyServerParameterResolver extends AbstractDubboGenericServ getClassLoader()); } - @Override - public boolean supportParameter(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata) { + private boolean supportParameter(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata) { Integer index = methodParameterMetadata.getIndex(); @@ -79,8 +78,12 @@ public class RequestBodyServerParameterResolver extends AbstractDubboGenericServ } @Override - public Object resolveParameter(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, - ServerHttpRequest request) { + public Object resolve(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, + HttpServerRequest request) { + + if (!supportParameter(restMethodMetadata, methodParameterMetadata)) { + return null; + } Object result = null; @@ -99,4 +102,10 @@ public class RequestBodyServerParameterResolver extends AbstractDubboGenericServ return result; } + + @Override + public Object resolve(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, + RestMethodMetadata clientRestMethodMetadata, Object[] arguments) { + return null; + } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestParamServiceParameterResolver.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestParamServiceParameterResolver.java index a031d5fc..12010da8 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestParamServiceParameterResolver.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/service/parameter/RequestParamServiceParameterResolver.java @@ -16,18 +16,17 @@ */ package org.springframework.cloud.alibaba.dubbo.service.parameter; +import org.springframework.cloud.alibaba.dubbo.http.HttpServerRequest; import org.springframework.cloud.alibaba.dubbo.metadata.MethodParameterMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; -import org.springframework.http.server.ServerHttpRequest; import org.springframework.util.CollectionUtils; import org.springframework.util.MultiValueMap; -import org.springframework.web.util.UriComponents; -import java.net.URI; import java.util.Collection; +import java.util.Collections; import java.util.Map; -import static org.springframework.web.util.UriComponentsBuilder.fromUri; +import static org.springframework.util.ObjectUtils.isEmpty; /** * HTTP Request Parameter {@link DubboGenericServiceParameterResolver Dubbo GenericService Parameter Resolver} @@ -44,44 +43,80 @@ public class RequestParamServiceParameterResolver extends AbstractDubboGenericSe } @Override - public boolean supportParameter(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata) { + public Object resolve(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, + HttpServerRequest request) { + + Collection paramNames = getParamNames(restMethodMetadata, methodParameterMetadata); + + if (isEmpty(paramNames)) { // index can't match + return null; + } + + MultiValueMap queryParams = request.getQueryParams(); + + String targetParamName = null; + + for (String paramName : paramNames) { + if (queryParams.containsKey(paramName)) { + targetParamName = paramName; + break; + } + } + + if (targetParamName == null) { // request parameter is abstract + return null; + } + + Class parameterType = resolveClass(methodParameterMetadata.getType()); + + Object paramValue = null; + + if (parameterType.isArray()) { // Array type + paramValue = queryParams.get(targetParamName); + } else { + paramValue = queryParams.getFirst(targetParamName); + } + + return resolveValue(paramValue, parameterType); + } + + @Override + public Object resolve(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata, + RestMethodMetadata clientRestMethodMetadata, Object[] arguments) { + + Collection paramNames = getParamNames(restMethodMetadata, methodParameterMetadata); + + if (isEmpty(paramNames)) { // index can't match + return null; + } + + Integer index = null; + + Map> clientIndexToName = clientRestMethodMetadata.getIndexToName(); + + for (Map.Entry> entry : clientIndexToName.entrySet()) { + + Collection clientParamNames = entry.getValue(); + + if (CollectionUtils.containsAny(paramNames, clientParamNames)) { + index = entry.getKey(); + break; + } + } + + return index > -1 ? arguments[index] : null; + } + + + private Collection getParamNames(RestMethodMetadata restMethodMetadata, MethodParameterMetadata methodParameterMetadata) { + Map> indexToName = restMethodMetadata.getIndexToName(); int index = methodParameterMetadata.getIndex(); Collection paramNames = indexToName.get(index); - if (CollectionUtils.isEmpty(paramNames)) { - return false; - } - - String paramName = methodParameterMetadata.getName(); - - return paramNames.contains(paramName); + return paramNames == null ? Collections.emptyList() : paramNames; } - @Override - public Object resolveParameter(RestMethodMetadata restMethodMetadata, MethodParameterMetadata parameterMetadata, - ServerHttpRequest request) { - - URI uri = request.getURI(); - - UriComponents uriComponents = fromUri(uri).build(true); - - MultiValueMap params = uriComponents.getQueryParams(); - - String paramName = parameterMetadata.getName(); - - Class parameterType = resolveClass(parameterMetadata.getType()); - - Object paramValue = null; - - if (parameterType.isArray()) { // Array type - paramValue = params.get(paramName); - } else { - paramValue = params.getFirst(paramName); - } - - return resolveValue(paramValue, parameterType); - } } diff --git a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java index 1516b8f3..b6aaf379 100644 --- a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java +++ b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudBootstrap.java @@ -87,7 +87,7 @@ public class DubboSpringCloudBootstrap { String param(@RequestParam("param") String param); @PostMapping("/params") - public int params(@RequestParam int a, @RequestParam int b); + public String params(@RequestParam("b") String b, @RequestParam("a") int a); } @@ -99,9 +99,10 @@ public class DubboSpringCloudBootstrap { String param(@RequestParam("param") String param); @PostMapping("/params") - public int params(@RequestParam int a, @RequestParam int b); + public String params(@RequestParam("b") String paramB, @RequestParam("a") int paramA); } + @Bean public ApplicationRunner paramRunner() { return arguments -> { @@ -116,11 +117,11 @@ public class DubboSpringCloudBootstrap { // To call /params // Dubbo Service call - System.out.println(restService.params(1, 1)); + System.out.println(restService.params(1, "1")); // Spring Cloud Open Feign REST Call (Dubbo Transported) - System.out.println(dubboFeignRestService.params(1, 1)); + System.out.println(dubboFeignRestService.params("1", 1)); // Spring Cloud Open Feign REST Call - System.out.println(feignRestService.params(1, 1)); + System.out.println(feignRestService.params("1", 1)); }; } @@ -135,11 +136,11 @@ public class DubboSpringCloudBootstrap { data.put("id", 1); data.put("name", "小马哥"); data.put("age", 33); - User user = restTemplate.postForObject("http://spring-cloud-alibaba-dubbo/request/body/map", data, User.class); + User user = restTemplate.postForObject("http://spring-cloud-alibaba-dubbo/request/setBody/map", data, User.class); - System.out.println(restTemplate.postForObject("http://spring-cloud-alibaba-dubbo/request/body/map", data, String.class)); + System.out.println(restTemplate.postForObject("http://spring-cloud-alibaba-dubbo/request/setBody/map", data, String.class)); - Map map = restTemplate.postForObject("http://spring-cloud-alibaba-dubbo/request/body/user", user, Map.class); + Map map = restTemplate.postForObject("http://spring-cloud-alibaba-dubbo/request/setBody/user", user, Map.class); System.out.println(map); }; } diff --git a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/RestService.java b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/RestService.java index b2842811..e0bc2c2d 100644 --- a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/RestService.java +++ b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/RestService.java @@ -27,7 +27,7 @@ public interface RestService { String param(String message); - int params(int a, int b); + String params(int a, String b); User requestBody(Map data); diff --git a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/StandardRestService.java b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/StandardRestService.java index a4f3ee67..decc8168 100644 --- a/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/StandardRestService.java +++ b/spring-cloud-alibaba-dubbo/src/test/java/org/springframework/cloud/alibaba/dubbo/service/StandardRestService.java @@ -68,7 +68,7 @@ public class StandardRestService implements RestService { @PostMapping("/params") @Path("/params") @POST - public int params(@RequestParam @QueryParam("a") int a, @RequestParam @QueryParam("b") int b) { + public String params(@RequestParam @QueryParam("a") int a, @RequestParam @QueryParam("b") String b) { log("/params", a + b); return a + b; } @@ -91,7 +91,7 @@ public class StandardRestService implements RestService { @Override @PostMapping(value = "/request/body/map", produces = APPLICATION_JSON_UTF8_VALUE) - @Path("/request/body/map") + @Path("/request/setBody/map") @POST @Produces(APPLICATION_JSON_VALUE) public User requestBody(@RequestBody Map data) { @@ -103,7 +103,7 @@ public class StandardRestService implements RestService { } @PostMapping(value = "/request/body/user", consumes = APPLICATION_JSON_UTF8_VALUE) - @Path("/request/body/user") + @Path("/request/setBody/user") @POST @Override @Consumes(APPLICATION_JSON_UTF8_VALUE)