diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java index 615911e93c..7efb70a145 100644 --- a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java @@ -362,9 +362,9 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest } } - private void processAnnotatedMethodParameter(Parameter parameter, int parameterIndex, Method serviceMethod, - Class serviceType, Class serviceInterfaceClass, - RestMethodMetadata metadata) { + protected void processAnnotatedMethodParameter(Parameter parameter, int parameterIndex, Method serviceMethod, + Class serviceType, Class serviceInterfaceClass, + RestMethodMetadata metadata) { Annotation[] annotations = parameter.getAnnotations(); if (annotations == null || annotations.length == 0) { diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ArgInfo.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ArgInfo.java index e4f9693083..a93b2e90e8 100644 --- a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ArgInfo.java +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ArgInfo.java @@ -20,7 +20,7 @@ package org.apache.dubbo.metadata.rest; import java.lang.reflect.Parameter; /** - * description of service method args info + * description of service method args info */ public class ArgInfo { /** diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ParamType.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ParamType.java index 457da7ebd4..0ffbf935b6 100644 --- a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ParamType.java +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/ParamType.java @@ -17,6 +17,7 @@ package org.apache.dubbo.metadata.rest; import org.apache.dubbo.metadata.rest.tag.BodyTag; +import org.apache.dubbo.metadata.rest.tag.NoAnnotationTag; import org.apache.dubbo.metadata.rest.tag.ParamTag; import java.util.ArrayList; @@ -40,9 +41,11 @@ public enum ParamType { SpringMvcClassConstants.REQUEST_BODY_ANNOTATION_CLASS)), PROVIDER_BODY(addSupportTypes( - JAXRSClassConstants.REST_EASY_BODY_ANNOTATION_CLASS,JAXRSClassConstants.FORM_PARAM_ANNOTATION_CLASS, + JAXRSClassConstants.REST_EASY_BODY_ANNOTATION_CLASS, JAXRSClassConstants.FORM_PARAM_ANNOTATION_CLASS, SpringMvcClassConstants.REQUEST_BODY_ANNOTATION_CLASS, BodyTag.class)), + PROVIDER_NO_ANNOTATION(addSupportTypes(NoAnnotationTag.class)), + EMPTY(addSupportTypes()); private List annotationClasses; diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java index 0abc5ebd22..59ebdec63f 100644 --- a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java @@ -17,6 +17,8 @@ package org.apache.dubbo.metadata.rest; import org.apache.dubbo.metadata.definition.model.MethodDefinition; +import org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver; +import org.apache.dubbo.metadata.rest.tag.NoAnnotationTag; import java.io.Serializable; import java.lang.reflect.Method; @@ -62,7 +64,7 @@ public class RestMethodMetadata implements Serializable { private Method reflectMethod; /** - * make a distinction between mvc & resteasy + * make a distinction between mvc & resteasy */ private Class codeStyle; @@ -175,6 +177,9 @@ public class RestMethodMetadata implements Serializable { } public void addArgInfo(ArgInfo argInfo) { + if (currentCodeStyleIsNoAnnotationMode()) { + argInfo.setParamAnnotationType(NoAnnotationTag.class); + } getArgInfos().add(argInfo); } @@ -195,6 +200,10 @@ public class RestMethodMetadata implements Serializable { this.codeStyle = codeStyle; } + public boolean currentCodeStyleIsNoAnnotationMode() { + return NoAnnotationServiceRestMetadataResolver.class.equals(getCodeStyle()); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolver.java index 1e107edc22..fc74647232 100644 --- a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolver.java +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolver.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.metadata.rest.jaxrs; +import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.metadata.rest.AbstractServiceRestMetadataResolver; import org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -40,6 +41,7 @@ import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.PRODUC * * @since 2.7.6 */ +@Activate(order = 100) public class JAXRSServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver { public JAXRSServiceRestMetadataResolver(ApplicationModel applicationModel) { super(applicationModel); diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/noannotaion/NoAnnotationServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/noannotaion/NoAnnotationServiceRestMetadataResolver.java new file mode 100644 index 0000000000..43b6754add --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/noannotaion/NoAnnotationServiceRestMetadataResolver.java @@ -0,0 +1,88 @@ +/* + * 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.apache.dubbo.metadata.rest.noannotaion; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.metadata.rest.AbstractServiceRestMetadataResolver; +import org.apache.dubbo.metadata.rest.ArgInfo; +import org.apache.dubbo.metadata.rest.RestMethodMetadata; +import org.apache.dubbo.metadata.rest.media.MediaType; +import org.apache.dubbo.rpc.model.ApplicationModel; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Set; + +import static org.apache.dubbo.common.utils.PathUtils.buildPath; + +/** + * NoAnnotationServiceRestMetadataResolver + * + * @since 3.3 + */ +@Activate(order = Integer.MAX_VALUE) +public class NoAnnotationServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver { + + private static final String CONTENT_TYPE = MediaType.APPLICATION_JSON_VALUE.value; + private static final String REQUEST_METHOD = "POST"; + + public NoAnnotationServiceRestMetadataResolver(ApplicationModel applicationModel) { + super(applicationModel); + } + + @Override + protected boolean supports0(Class serviceType) { + // class @Controller or @RequestMapping + return true; + } + + @Override + protected boolean isRestCapableMethod(Method serviceMethod, Class serviceType, Class serviceInterfaceClass) { + // method only match @RequestMapping + return true; + } + + @Override + protected String resolveRequestMethod(Method serviceMethod, Class serviceType, Class serviceInterfaceClass) { + + return REQUEST_METHOD; + } + + @Override + protected String resolveRequestPath(Method serviceMethod, Class serviceType, Class serviceInterfaceClass) { + + // use serviceInterfaceClass class name + return buildPath(serviceInterfaceClass.getName(), serviceMethod.getName()); + } + + @Override + protected void processProduces(Method serviceMethod, Class serviceType, Class serviceInterfaceClass, Set produces) { + produces.add(CONTENT_TYPE); + } + + @Override + protected void processConsumes(Method serviceMethod, Class serviceType, Class serviceInterfaceClass, Set consumes) { + consumes.add(CONTENT_TYPE); + } + + @Override + protected void processAnnotatedMethodParameter(Parameter parameter, int parameterIndex, Method serviceMethod, Class serviceType, Class serviceInterfaceClass, RestMethodMetadata metadata) { + ArgInfo argInfo = ArgInfo.build(parameterIndex, parameter); + metadata.addArgInfo(argInfo); + + } +} diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java index f7e89540c4..765b230855 100644 --- a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.metadata.rest.springmvc; +import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.metadata.rest.AbstractServiceRestMetadataResolver; import org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -45,6 +46,7 @@ import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.RE * * @since 2.7.6 */ +@Activate(order = 100) public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver { private static final int FIRST_ELEMENT_INDEX = 0; diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/tag/NoAnnotationTag.java b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/tag/NoAnnotationTag.java new file mode 100644 index 0000000000..067a8d594c --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/java/org/apache/dubbo/metadata/rest/tag/NoAnnotationTag.java @@ -0,0 +1,23 @@ +/* + * 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.apache.dubbo.metadata.rest.tag; + +/** + * for no annotation mode param + */ +public interface NoAnnotationTag { +} diff --git a/dubbo-metadata/dubbo-metadata-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver b/dubbo-metadata/dubbo-metadata-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver index 5b0873bf69..ac37a96c5e 100644 --- a/dubbo-metadata/dubbo-metadata-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver +++ b/dubbo-metadata/dubbo-metadata-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver @@ -1,3 +1,4 @@ default = jax-rs = org.apache.dubbo.metadata.rest.jaxrs.JAXRSServiceRestMetadataResolver -spring-webmvc = org.apache.dubbo.metadata.rest.springmvc.SpringMvcServiceRestMetadataResolver \ No newline at end of file +spring-webmvc = org.apache.dubbo.metadata.rest.springmvc.SpringMvcServiceRestMetadataResolver +no-annotation = org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver diff --git a/dubbo-metadata/dubbo-metadata-rest/src/test/java/org/apache/dubbo/metadata/rest/noannotation/NoAnnotationServiceRestMetadataResolverTest.java b/dubbo-metadata/dubbo-metadata-rest/src/test/java/org/apache/dubbo/metadata/rest/noannotation/NoAnnotationServiceRestMetadataResolverTest.java new file mode 100644 index 0000000000..7d556fe15f --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-rest/src/test/java/org/apache/dubbo/metadata/rest/noannotation/NoAnnotationServiceRestMetadataResolverTest.java @@ -0,0 +1,92 @@ +/* + * 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.apache.dubbo.metadata.rest.noannotation; + +import org.apache.dubbo.common.utils.JsonUtils; +import org.apache.dubbo.metadata.rest.DefaultRestService; +import org.apache.dubbo.metadata.rest.RestMethodMetadata; +import org.apache.dubbo.metadata.rest.ServiceRestMetadata; +import org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class NoAnnotationServiceRestMetadataResolverTest { + private NoAnnotationServiceRestMetadataResolver instance = new NoAnnotationServiceRestMetadataResolver(ApplicationModel.defaultModel()); + + + @Test + void testResolve() { + + List jsons = Arrays.asList( + "{\"argInfos\":[{\"annotationNameAttribute\":\"form\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"form\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"form\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/form\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"header\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"header\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0},{\"annotationNameAttribute\":\"header2\",\"formContentType\":false,\"index\":1,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"header2\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0},{\"annotationNameAttribute\":\"param\",\"formContentType\":false,\"index\":2,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"param\",\"paramType\":\"java.lang.Integer\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"header\"],1:[\"header2\"],2:[\"param\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/headers\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"user\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"user\",\"paramType\":\"org.apache.dubbo.metadata.rest.User\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"user\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/noAnnotationFormBody\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"user\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"user\",\"paramType\":\"org.apache.dubbo.metadata.rest.User\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"user\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/noAnnotationJsonBody\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"text\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"text\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"text\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/noAnnotationParam\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"param\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"param\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"param\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/param\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"a\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"a\",\"paramType\":\"int\",\"urlSplitIndex\":0},{\"annotationNameAttribute\":\"b\",\"formContentType\":false,\"index\":1,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"b\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"a\"],1:[\"b\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/params\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"path1\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"path1\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0},{\"annotationNameAttribute\":\"path2\",\"formContentType\":false,\"index\":1,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"path2\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0},{\"annotationNameAttribute\":\"param\",\"formContentType\":false,\"index\":2,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"param\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"path1\"],1:[\"path2\"],2:[\"param\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/pathVariables\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"data\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"data\",\"paramType\":\"java.util.Map\",\"urlSplitIndex\":0},{\"annotationNameAttribute\":\"param\",\"formContentType\":false,\"index\":1,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"param\",\"paramType\":\"java.lang.String\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"data\"],1:[\"param\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/requestBodyMap\",\"produces\":[\"application/json\"]}}", + "{\"argInfos\":[{\"annotationNameAttribute\":\"user\",\"formContentType\":false,\"index\":0,\"paramAnnotationType\":\"org.apache.dubbo.metadata.rest.tag.NoAnnotationTag\",\"paramName\":\"user\",\"paramType\":\"org.apache.dubbo.metadata.rest.User\",\"urlSplitIndex\":0}],\"codeStyle\":\"org.apache.dubbo.metadata.rest.noannotaion.NoAnnotationServiceRestMetadataResolver\",\"indexToName\":{0:[\"user\"]},\"method\":{\"annotations\":[],\"parameters\":[]},\"request\":{\"consumes\":[\"application/json\"],\"headerNames\":[],\"headers\":{},\"method\":\"POST\",\"paramNames\":[],\"params\":{},\"path\":\"/org.apache.dubbo.metadata.rest.RestService/requestBodyUser\",\"produces\":[\"application/json\"]}}" + + ); + + boolean supports = instance.supports(DefaultRestService.class); + + + Assertions.assertEquals(true, supports); + + + ServiceRestMetadata serviceRestMetadata = instance.resolve(DefaultRestService.class); + + + + + List jsonsTmp = new ArrayList<>(); + for (RestMethodMetadata restMethodMetadata : serviceRestMetadata.getMeta()) { + restMethodMetadata.setReflectMethod(null); + restMethodMetadata.setMethod(null); + jsonsTmp.add(JsonUtils.toJson(restMethodMetadata)); + + } + + + Comparator comparator = new Comparator() { + @Override + public int compare(String o1, String o2) { + return o1.length() - o2.length(); + } + }; + jsons.sort(comparator); + jsonsTmp.sort(comparator); + + + for (int i = 0; i < jsons.size(); i++) { + assertEquals(jsons.get(i), jsonsTmp.get(i)); + } + + + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java index e736a39292..c944107e44 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestRPCInvocationUtil.java @@ -32,6 +32,7 @@ import org.apache.dubbo.rpc.protocol.rest.exception.ParamParseException; import org.apache.dubbo.rpc.protocol.rest.pair.InvokerAndRestMethodMetadataPair; import org.apache.dubbo.rpc.protocol.rest.request.RequestFacade; import org.apache.dubbo.rpc.protocol.rest.util.HttpHeaderUtil; +import org.apache.dubbo.rpc.protocol.rest.util.NoAnnotationBodyParseUtil; import java.lang.reflect.Method; @@ -91,11 +92,16 @@ public class RestRPCInvocationUtil { ProviderParseContext parseContext = new ProviderParseContext(request); parseContext.setResponse(originResponse); parseContext.setRequest(originRequest); - + parseContext.setNoAnnotationMode(restMethodMetadata.currentCodeStyleIsNoAnnotationMode()); Object[] objects = new Object[restMethodMetadata.getArgInfos().size()]; parseContext.setArgs(Arrays.asList(objects)); parseContext.setArgInfos(restMethodMetadata.getArgInfos()); + // parse object arrays body + if (restMethodMetadata.currentCodeStyleIsNoAnnotationMode()) { + parseContext.setArrayArgs(NoAnnotationBodyParseUtil.doParse(parseContext)); + } + return parseContext; } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/BaseParseContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/BaseParseContext.java index e2fdc252ef..7a3bb2fd7b 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/BaseParseContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/BaseParseContext.java @@ -28,6 +28,8 @@ public class BaseParseContext { protected List argInfos; + boolean isNoAnnotationMode; + public List getArgs() { return args; @@ -48,4 +50,12 @@ public class BaseParseContext { public ArgInfo getArgInfoByIndex(int index) { return getArgInfos().get(index); } + + public boolean isNoAnnotationMode() { + return isNoAnnotationMode; + } + + public void setNoAnnotationMode(boolean noAnnotationMode) { + isNoAnnotationMode = noAnnotationMode; + } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java index 5c0dbaa236..90bea5b9ee 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/ParamParserManager.java @@ -51,7 +51,11 @@ public class ParamParserManager { List args = parseContext.getArgInfos(); for (int i = 0; i < args.size(); i++) { - for (ParamParser paramParser : providerParamParsers) { + for (BaseProviderParamParser paramParser : providerParamParsers) { + + if (!paramParser.matchParseType(args.get(i).getParamAnnotationType())) { + continue; + } paramParser.parse(parseContext, args.get(i)); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/HttpConnectionCreateContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/HttpConnectionCreateContext.java index 584b831835..494c94fa54 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/HttpConnectionCreateContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/HttpConnectionCreateContext.java @@ -74,4 +74,8 @@ public class HttpConnectionCreateContext { public void setServiceRestMetadata(ServiceRestMetadata serviceRestMetadata) { this.serviceRestMetadata = serviceRestMetadata; } + + public boolean isNoAnnotationMode() { + return restMethodMetadata.currentCodeStyleIsNoAnnotationMode(); + } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/inercept/ParamParseIntercept.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/inercept/ParamParseIntercept.java index 951d19476b..52a31f293a 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/inercept/ParamParseIntercept.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/consumer/inercept/ParamParseIntercept.java @@ -17,6 +17,7 @@ package org.apache.dubbo.rpc.protocol.rest.annotation.consumer.inercept; import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.remoting.http.RequestTemplate; import org.apache.dubbo.rpc.protocol.rest.annotation.ParamParserManager; import org.apache.dubbo.rpc.protocol.rest.annotation.consumer.HttpConnectionCreateContext; import org.apache.dubbo.rpc.protocol.rest.annotation.consumer.HttpConnectionPreBuildIntercept; @@ -25,17 +26,27 @@ import org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.consumer.Consum import java.util.Arrays; /** - * resolve method args by args info + * resolve method args by args info */ -@Activate(value = "paramparse",order = 5) +@Activate(value = "paramparse", order = 5) public class ParamParseIntercept implements HttpConnectionPreBuildIntercept { @Override public void intercept(HttpConnectionCreateContext connectionCreateContext) { - ConsumerParseContext consumerParseContext = new ConsumerParseContext(connectionCreateContext.getRequestTemplate()); - consumerParseContext.setArgInfos(connectionCreateContext.getRestMethodMetadata().getArgInfos()); - consumerParseContext.setArgs(Arrays.asList(connectionCreateContext.getInvocation().getArguments())); - ParamParserManager.consumerParamParse(consumerParseContext); + + RequestTemplate requestTemplate = connectionCreateContext.getRequestTemplate(); + Object[] arguments = connectionCreateContext.getInvocation().getArguments(); + + // no annotation mode set array body + if (connectionCreateContext.isNoAnnotationMode()) { + requestTemplate.body(arguments, Object[].class); + } else { + ConsumerParseContext consumerParseContext = new ConsumerParseContext(requestTemplate); + consumerParseContext.setArgInfos(connectionCreateContext.getRestMethodMetadata().getArgInfos()); + consumerParseContext.setArgs(Arrays.asList(arguments)); + ParamParserManager.consumerParamParse(consumerParseContext); + + } } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/metadata/MetadataResolver.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/metadata/MetadataResolver.java index f1521476a1..6433af7dce 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/metadata/MetadataResolver.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/metadata/MetadataResolver.java @@ -38,7 +38,7 @@ public class MetadataResolver { public static ServiceRestMetadata resolveConsumerServiceMetadata(Class targetClass, URL url, String contextPathFromUrl) { ExtensionLoader extensionLoader = url.getOrDefaultApplicationModel().getExtensionLoader(ServiceRestMetadataResolver.class); - for (ServiceRestMetadataResolver serviceRestMetadataResolver : extensionLoader.getSupportedExtensionInstances()) { + for (ServiceRestMetadataResolver serviceRestMetadataResolver : extensionLoader.getActivateExtensions()) { if (serviceRestMetadataResolver.supports(targetClass, true)) { ServiceRestMetadata serviceRestMetadata = new ServiceRestMetadata(url.getServiceInterface(), url.getVersion(), url.getGroup(), true); serviceRestMetadata.setContextPathFromUrl(contextPathFromUrl); @@ -55,7 +55,7 @@ public class MetadataResolver { public static ServiceRestMetadata resolveProviderServiceMetadata(Class serviceImpl, URL url, String contextPathFromUrl) { ExtensionLoader extensionLoader = url.getOrDefaultApplicationModel().getExtensionLoader(ServiceRestMetadataResolver.class); - for (ServiceRestMetadataResolver serviceRestMetadataResolver : extensionLoader.getSupportedExtensionInstances()) { + for (ServiceRestMetadataResolver serviceRestMetadataResolver : extensionLoader.getActivateExtensions()) { boolean supports = serviceRestMetadataResolver.supports(serviceImpl); if (supports) { ServiceRestMetadata serviceRestMetadata = new ServiceRestMetadata(url.getServiceInterface(), url.getVersion(), url.getGroup(), false); diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BaseProviderParamParser.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BaseProviderParamParser.java index 343efbbf62..58ca9abcbb 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BaseProviderParamParser.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BaseProviderParamParser.java @@ -19,9 +19,19 @@ package org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider; import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.metadata.rest.ParamType; import org.apache.dubbo.rpc.protocol.rest.annotation.ParamParser; @SPI(scope = ExtensionScope.FRAMEWORK) public interface BaseProviderParamParser extends ParamParser { + + default boolean matchParseType(Class paramAnno) { + + ParamType paramAnnotType = getParamType(); + return paramAnnotType.supportAnno(paramAnno); + } + + + ParamType getParamType(); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BodyProviderParamParser.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BodyProviderParamParser.java index 294de98fcb..9da9d428ea 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BodyProviderParamParser.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/BodyProviderParamParser.java @@ -51,7 +51,7 @@ public class BodyProviderParamParser extends ProviderParamParser { } @Override - protected ParamType getParamType() { + public ParamType getParamType() { return ParamType.PROVIDER_BODY; } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/HeaderProviderParamParser.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/HeaderProviderParamParser.java index 9b87792bd9..88d0abf4c3 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/HeaderProviderParamParser.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/HeaderProviderParamParser.java @@ -59,7 +59,7 @@ public class HeaderProviderParamParser extends ProviderParamParser { } @Override - protected ParamType getParamType() { + public ParamType getParamType() { return ParamType.HEADER; } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/NoAnnotationParamProviderParamParser.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/NoAnnotationParamProviderParamParser.java new file mode 100644 index 0000000000..7553ec5ba1 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/NoAnnotationParamProviderParamParser.java @@ -0,0 +1,59 @@ +/* + * 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.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.JsonUtils; +import org.apache.dubbo.metadata.rest.ArgInfo; +import org.apache.dubbo.metadata.rest.ParamType; +import org.apache.dubbo.rpc.protocol.rest.constans.RestConstant; +import org.apache.dubbo.rpc.protocol.rest.util.DataParseUtils; + + +/** + * body param parse + */ +@Activate(value = RestConstant.PROVIDER_NO_ANNOTATION) +public class NoAnnotationParamProviderParamParser extends ProviderParamParser { + + @Override + protected void doParse(ProviderParseContext parseContext, ArgInfo argInfo) { + + Object[] arrayArgs = parseContext.getArrayArgs(); + + int index = argInfo.getIndex(); + + Object arg = arrayArgs[index]; + + Object convertArg = null; + + if (DataParseUtils.isTextType(argInfo.getParamType())) { + convertArg = DataParseUtils.stringTypeConvert(argInfo.getParamType(), String.valueOf(arg)); + } else { + convertArg = JsonUtils.toJavaObject(arg.toString(), argInfo.getParamType()); + } + + parseContext.setValueByIndex(index, convertArg); + + + } + + @Override + public ParamType getParamType() { + return ParamType.PROVIDER_NO_ANNOTATION; + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ParamProviderParamParser.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ParamProviderParamParser.java index 5505ba4b80..ca0b7dc234 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ParamProviderParamParser.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ParamProviderParamParser.java @@ -59,7 +59,7 @@ public class ParamProviderParamParser extends ProviderParamParser { } @Override - protected ParamType getParamType() { + public ParamType getParamType() { return ParamType.PARAM; } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/PathProviderParamParser.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/PathProviderParamParser.java index 4addb20a53..7b81d9cd5d 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/PathProviderParamParser.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/PathProviderParamParser.java @@ -40,7 +40,7 @@ public class PathProviderParamParser extends ProviderParamParser { } @Override - protected ParamType getParamType() { + public ParamType getParamType() { return ParamType.PATH; } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParamParser.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParamParser.java index 12606b0cf5..6178232d04 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParamParser.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParamParser.java @@ -18,33 +18,19 @@ package org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider; import org.apache.dubbo.metadata.rest.ArgInfo; -import org.apache.dubbo.metadata.rest.ParamType; import org.apache.dubbo.rpc.protocol.rest.util.DataParseUtils; public abstract class ProviderParamParser implements BaseProviderParamParser { public void parse(ProviderParseContext parseContext, ArgInfo argInfo) { - if (!matchParseType(argInfo.getParamAnnotationType())) { - return; - } - doParse(parseContext, argInfo); } protected abstract void doParse(ProviderParseContext parseContext, ArgInfo argInfo); - public boolean matchParseType(Class paramAnno) { - - ParamType paramAnnotType = getParamType(); - return paramAnnotType.supportAnno(paramAnno); - } - - protected abstract ParamType getParamType(); - protected Object paramTypeConvert(Class targetType, String value) { - return DataParseUtils.stringTypeConvert(targetType, value); } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParseContext.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParseContext.java index 0e2be572a6..462acfa347 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParseContext.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/annotation/param/parse/provider/ProviderParseContext.java @@ -27,6 +27,7 @@ public class ProviderParseContext extends BaseParseContext { private RequestFacade requestFacade; private Object response; private Object request; + private Object[] arrayArgs; public ProviderParseContext(RequestFacade request) { @@ -66,5 +67,12 @@ public class ProviderParseContext extends BaseParseContext { } + public Object[] getArrayArgs() { + return arrayArgs; + } + public void setArrayArgs(Object[] objects) { + this.arrayArgs = objects; + + } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java index 09835f8cd6..fc2edc66ad 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/constans/RestConstant.java @@ -32,6 +32,7 @@ public interface RestConstant { String PROVIDER_PARAM_PARSE = "param"; String PROVIDER_HEADER_PARSE = "header"; String PROVIDER_PATH_PARSE = "path"; + String PROVIDER_NO_ANNOTATION = "no-annotation"; String ADD_MUST_ATTTACHMENT = "must-intercept"; String RPCCONTEXT_INTERCEPT = "rpc-context"; diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/util/NoAnnotationBodyParseUtil.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/util/NoAnnotationBodyParseUtil.java new file mode 100644 index 0000000000..c6abf12fef --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/util/NoAnnotationBodyParseUtil.java @@ -0,0 +1,39 @@ +/* + * 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.apache.dubbo.rpc.protocol.rest.util; + +import org.apache.dubbo.metadata.rest.media.MediaType; +import org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.ProviderParseContext; +import org.apache.dubbo.rpc.protocol.rest.exception.ParamParseException; +import org.apache.dubbo.rpc.protocol.rest.message.HttpMessageCodecManager; +import org.apache.dubbo.rpc.protocol.rest.request.RequestFacade; + +public class NoAnnotationBodyParseUtil { + + + public static Object[] doParse(ProviderParseContext parseContext) { + RequestFacade request = parseContext.getRequestFacade(); + try { + Class objectArraysType = Object[].class; + MediaType mediaType = MediaTypeUtil.convertMediaType(objectArraysType, MediaType.APPLICATION_JSON_VALUE.value); + Object[] params = (Object[]) HttpMessageCodecManager.httpMessageDecode(request.getInputStream(), objectArraysType, mediaType); + return params; + } catch (Throwable e) { + throw new ParamParseException("dubbo rest protocol provider body param parser error: " + e.getMessage()); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.BaseProviderParamParser b/dubbo-rpc/dubbo-rpc-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.BaseProviderParamParser index 0f62f51f54..8c6a561d6c 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.BaseProviderParamParser +++ b/dubbo-rpc/dubbo-rpc-rest/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.BaseProviderParamParser @@ -2,3 +2,4 @@ body=org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.BodyProv header=org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.HeaderProviderParamParser path=org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.PathProviderParamParser param=org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.ParamProviderParamParser +no-annotation=org.apache.dubbo.rpc.protocol.rest.annotation.param.parse.provider.NoAnnotationParamProviderParamParser diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/NoAnnotationRestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/NoAnnotationRestProtocolTest.java new file mode 100644 index 0000000000..1d40f2c612 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/NoAnnotationRestProtocolTest.java @@ -0,0 +1,127 @@ +/* + * 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.apache.dubbo.rpc.protocol.rest; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.NetUtils; + +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ModuleServiceRepository; +import org.apache.dubbo.rpc.model.ProviderModel; +import org.apache.dubbo.rpc.model.ServiceDescriptor; + +import org.apache.dubbo.rpc.protocol.rest.noannotation.NoAnnotationDemoService; +import org.apache.dubbo.rpc.protocol.rest.noannotation.NoAnnotationDemoServiceImpl; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; + +import org.junit.jupiter.api.Test; + + +class NoAnnotationRestProtocolTest { + private final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("rest"); + private final ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + private final int availablePort = NetUtils.getAvailablePort(); + private final URL exportUrl = URL.valueOf("rest://127.0.0.1:" + availablePort + "/rest?interface=org.apache.dubbo.rpc.protocol.rest.noannotation.NoAnnotationDemoService"); + private final ModuleServiceRepository repository = ApplicationModel.defaultModel().getDefaultModule().getServiceRepository(); + private static final String SERVER = "netty4"; + + @AfterEach + public void tearDown() { + protocol.destroy(); + FrameworkModel.destroyAll(); + } + + @Test + void testRestProtocol() { + URL url = URL.valueOf("rest://127.0.0.1:" + NetUtils.getAvailablePort() + "/?version=1.0.0&interface=org.apache.dubbo.rpc.protocol.rest.noannotation.NoAnnotationDemoService"); + + NoAnnotationDemoServiceImpl server = new NoAnnotationDemoServiceImpl(); + + url = this.registerProvider(url, server, DemoService.class); + + Exporter exporter = protocol.export(proxy.getInvoker(server, NoAnnotationDemoService.class, url)); + Invoker invoker = protocol.refer(NoAnnotationDemoService.class, url); + + + NoAnnotationDemoService client = proxy.getProxy(invoker); + Object result = client.sayHello("haha"); + Assertions.assertEquals("Hello, haha", result); + + result = client.hello(1, 2); + Assertions.assertEquals(3, result); + + User user = client.noBodyArg(User.getInstance()); + Assertions.assertEquals("invoked", user.getName()); + + + invoker.destroy(); + exporter.unexport(); + } + + + @Test + void testAnotherUserRestProtocolByDifferentRestClient() { + testAnotherUserRestProtocol(org.apache.dubbo.remoting.Constants.OK_HTTP); + testAnotherUserRestProtocol(org.apache.dubbo.remoting.Constants.APACHE_HTTP_CLIENT); + testAnotherUserRestProtocol(org.apache.dubbo.remoting.Constants.URL_CONNECTION); + } + + + void testAnotherUserRestProtocol(String restClient) { + URL url = URL.valueOf("rest://127.0.0.1:" + NetUtils.getAvailablePort() + + "/?version=1.0.0&interface=org.apache.dubbo.rpc.protocol.rest.noannotation.NoAnnotationDemoService&" + + org.apache.dubbo.remoting.Constants.CLIENT_KEY + "=" + restClient); + + NoAnnotationDemoService server = new NoAnnotationDemoServiceImpl(); + + url = this.registerProvider(url, server, DemoService.class); + + Exporter exporter = protocol.export(proxy.getInvoker(server, NoAnnotationDemoService.class, url)); + Invoker invoker = protocol.refer(NoAnnotationDemoService.class, url); + + + NoAnnotationDemoService client = proxy.getProxy(invoker); + String name = "no-annotation"; + String result = client.sayHello(name); + + Assertions.assertEquals("Hello, " + name, result); + + invoker.destroy(); + exporter.unexport(); + } + + + private URL registerProvider(URL url, Object impl, Class interfaceClass) { + ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass); + ProviderModel providerModel = new ProviderModel( + url.getServiceKey(), + impl, + serviceDescriptor, + null, + null); + repository.registerProvider(providerModel); + return url.setServiceModel(providerModel); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/noannotation/NoAnnotationDemoService.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/noannotation/NoAnnotationDemoService.java new file mode 100644 index 0000000000..5811819a27 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/noannotation/NoAnnotationDemoService.java @@ -0,0 +1,32 @@ +/* + * 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.apache.dubbo.rpc.protocol.rest.noannotation; + + +import org.apache.dubbo.rpc.protocol.rest.User; + + +public interface NoAnnotationDemoService { + Integer hello(Integer a, Integer b); + + String error(); + + String sayHello(String name); + + User noBodyArg(User user); + +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/noannotation/NoAnnotationDemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/noannotation/NoAnnotationDemoServiceImpl.java new file mode 100644 index 0000000000..77e63cef65 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/noannotation/NoAnnotationDemoServiceImpl.java @@ -0,0 +1,46 @@ +/* + * 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.apache.dubbo.rpc.protocol.rest.noannotation; + + +import org.apache.dubbo.rpc.protocol.rest.User; + + +public class NoAnnotationDemoServiceImpl implements NoAnnotationDemoService { + + + @Override + public Integer hello(Integer a, Integer b) { + return a + b; + } + + @Override + public String error() { + return null; + } + + @Override + public String sayHello(String name) { + return "Hello, "+name; + } + + @Override + public User noBodyArg(User user) { + user.setName("invoked"); + return user; + } +}