diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/pom.xml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/pom.xml index 08a74147935..c9728a77575 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/pom.xml +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/pom.xml @@ -93,6 +93,7 @@ spring-boot-starter-log4j2 + com.github.therapi therapi-runtime-javadoc-scribe diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Animal.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Animal.java deleted file mode 100644 index 07079a375fa..00000000000 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Animal.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.springboot.demo.servlet; - -/** - * The animal - */ -public class Animal extends Live { - - /** - * The name of the animal - */ - private String name; - - private int age; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } -} diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Cat.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Cat.java deleted file mode 100644 index be97dbfcc7e..00000000000 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Cat.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.springboot.demo.servlet; - -public class Cat extends Animal { - - /** - * The length of the cat - */ - private int length; - - public int getLength() { - return length; - } - - public void setLength(int length) { - this.length = length; - } -} diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Dog.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Dog.java deleted file mode 100644 index 063e886cb77..00000000000 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Dog.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.springboot.demo.servlet; - -public class Dog extends Animal { - - private String color; - - public String getColor() { - return color; - } - - public void setColor(String color) { - this.color = color; - } -} diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterService.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterService.java index 3f279ec58e7..e777429e71d 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterService.java +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterService.java @@ -41,12 +41,4 @@ public interface GreeterService { * Sends greetings with bi streaming */ StreamObserver sayHelloBiStream(StreamObserver responseObserver); - - /** - * Create an animal - * @param cat the cat - * @param dog the dog - * @return the animal - */ - Animal createAnimal(Cat cat, Dog dog); } diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterServiceImpl.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterServiceImpl.java index 8340b7a9a3d..ef699dd69d7 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterServiceImpl.java +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/GreeterServiceImpl.java @@ -74,11 +74,6 @@ public void onCompleted() { }; } - @Override - public Animal createAnimal(Cat cat, Dog dog) { - return cat; - } - private static HelloReply toReply(String message) { HelloReply reply = new HelloReply(); reply.setMessage(message); diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Live.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Live.java deleted file mode 100644 index 40453e30956..00000000000 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/Live.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.springboot.demo.servlet; - -/** - * The live - */ -public class Live { - - /** - * The alive - */ - private boolean alive; - - private byte[] raw; - - public boolean isAlive() { - return alive; - } - - public void setAlive(boolean alive) { - this.alive = alive; - } - - public byte[] getRaw() { - return raw; - } - - public void setRaw(byte[] raw) { - this.raw = raw; - } -} diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/sub/Dog.java b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/sub/Dog.java deleted file mode 100644 index 89916a98b5d..00000000000 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/java/org/apache/dubbo/springboot/demo/servlet/sub/Dog.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.springboot.demo.servlet.sub; - -import org.apache.dubbo.springboot.demo.servlet.Animal; - -public class Dog extends Animal { - - private String color; - - public String getColor() { - return color; - } - - public void setColor(String color) { - this.color = color; - } -} diff --git a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml index 88754252174..0ff09750d54 100644 --- a/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml +++ b/dubbo-demo/dubbo-demo-spring-boot/dubbo-demo-spring-boot-servlet/src/main/resources/application.yml @@ -30,11 +30,6 @@ dubbo: openapi: enabled: true cache: false - schema-flatten: false - schema-class-excludes: - - a. - - "!b.c." - - "!org.apache.dubbo.springboot.demo." servlet: enabled: true registry: diff --git a/dubbo-plugin/dubbo-rest-swagger/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/swagger/SwaggerOpenAPIDefinitionResolver.java b/dubbo-plugin/dubbo-rest-swagger/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/swagger/SwaggerOpenAPIDefinitionResolver.java index 1303836c2ac..e34c1c98712 100644 --- a/dubbo-plugin/dubbo-rest-swagger/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/swagger/SwaggerOpenAPIDefinitionResolver.java +++ b/dubbo-plugin/dubbo-rest-swagger/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/swagger/SwaggerOpenAPIDefinitionResolver.java @@ -25,6 +25,7 @@ import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.MethodMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ServiceMeta; +import org.apache.dubbo.rpc.protocol.tri.rest.openapi.Constants; import org.apache.dubbo.rpc.protocol.tri.rest.openapi.OpenAPIDefinitionResolver; import org.apache.dubbo.rpc.protocol.tri.rest.openapi.OpenAPISchemaPredicate; import org.apache.dubbo.rpc.protocol.tri.rest.openapi.OpenAPISchemaResolver; @@ -35,15 +36,20 @@ import org.apache.dubbo.rpc.protocol.tri.rest.openapi.model.OpenAPI; import org.apache.dubbo.rpc.protocol.tri.rest.openapi.model.Operation; import org.apache.dubbo.rpc.protocol.tri.rest.openapi.model.Schema; +import org.apache.dubbo.rpc.protocol.tri.rest.openapi.model.Schema.Type; import org.apache.dubbo.rpc.protocol.tri.rest.openapi.model.Tag; +import java.util.Arrays; import java.util.Map; import io.swagger.v3.oas.annotations.ExternalDocumentation; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; +import io.swagger.v3.oas.annotations.media.Schema.AccessMode; +import io.swagger.v3.oas.annotations.media.Schema.RequiredMode; +import static org.apache.dubbo.rpc.protocol.tri.rest.openapi.Helper.setValue; import static org.apache.dubbo.rpc.protocol.tri.rest.openapi.Helper.trim; @Activate(order = 50, onClass = "io.swagger.v3.oas.annotations.OpenAPIDefinition") @@ -98,7 +104,14 @@ public OpenAPI resolve(OpenAPI openAPI, ServiceMeta serviceMeta, OpenAPIChain ch openAPI.setExternalDocs(toExternalDocs(anno.externalDocs())); - openAPI.setExtensions(toProperties(anno.extensions())); + Map properties = toProperties(anno.extensions()); + if (properties != null) { + String group = properties.remove(Constants.X_API_GROUP); + if (group != null) { + openAPI.setGroup(group); + } + openAPI.setExtensions(properties); + } return openAPI; } @@ -142,27 +155,74 @@ public Operation resolve(Operation operation, MethodMeta methodMeta, OperationCo for (String tag : anno.tags()) { operation.addTag(tag); } + Map properties = toProperties(anno.extensions()); + if (properties != null) { + String group = properties.remove(Constants.X_API_GROUP); + if (group != null) { + operation.setGroup(group); + } + String version = properties.remove(Constants.X_API_VERSION); + if (version != null) { + operation.setVersion(version); + } + operation.setExtensions(properties); + } return operation .setSummary(trim(anno.summary())) .setDescription(trim(anno.description())) .setExternalDocs(toExternalDocs(anno.externalDocs())) .setOperationId(trim(anno.operationId())) - .setDeprecated(anno.deprecated() ? Boolean.TRUE : null) - .setExtensions(toProperties(anno.extensions())); + .setDeprecated(anno.deprecated() ? Boolean.TRUE : null); } @Override public Schema resolve(ParameterMeta parameter, SchemaContext context, SchemaChain chain) { - AnnotationMeta meta = + AnnotationMeta annoMeta = parameter.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class); - if (meta == null) { + if (annoMeta == null) { return chain.resolve(parameter, context); } - io.swagger.v3.oas.annotations.media.Schema schema = meta.getAnnotation(); - if (schema.hidden() || parameter.isHierarchyAnnotated(Hidden.class)) { + io.swagger.v3.oas.annotations.media.Schema anno = annoMeta.getAnnotation(); + if (anno.hidden() || parameter.isHierarchyAnnotated(Hidden.class)) { return null; } - return chain.resolve(parameter, context); + Schema schema = chain.resolve(parameter, context); + if (schema == null) { + return null; + } + + Map properties = toProperties(anno.extensions()); + if (properties != null) { + String group = properties.remove(Constants.X_API_GROUP); + if (group != null) { + schema.setGroup(group); + } + String version = properties.remove(Constants.X_API_VERSION); + if (version != null) { + schema.setVersion(version); + } + schema.setExtensions(properties); + } + + setValue(anno::type, v -> schema.setType(Type.valueOf(v))); + setValue(anno::format, schema::setFormat); + setValue(anno::name, schema::setName); + setValue(anno::title, schema::setTitle); + setValue(anno::description, schema::setDescription); + setValue(anno::defaultValue, schema::setDefaultValue); + setValue(anno::pattern, schema::setPattern); + setValue(anno::example, schema::setExample); + String[] enumItems = trim(anno.allowableValues()); + if (enumItems != null) { + schema.setEnumeration(Arrays.asList(enumItems)); + } + schema.setRequired(anno.requiredMode() == RequiredMode.REQUIRED ? Boolean.TRUE : null); + schema.setReadOnly(anno.accessMode() == AccessMode.READ_ONLY ? Boolean.TRUE : null); + schema.setWriteOnly(anno.accessMode() == AccessMode.WRITE_ONLY ? Boolean.TRUE : null); + schema.setNullable(anno.nullable() ? Boolean.TRUE : null); + schema.setDeprecated(anno.deprecated() ? Boolean.TRUE : null); + + return schema; } @Override diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java index 4ebfbf770c3..829d046497a 100644 --- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java +++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/HttpMetadataAdapter.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.rpc.protocol.tri.servlet; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; import org.apache.dubbo.remoting.http12.HttpHeaders; import org.apache.dubbo.remoting.http12.h2.Http2Header; @@ -23,6 +24,8 @@ import java.util.Enumeration; +import io.netty.handler.codec.http2.Http2Headers.PseudoHeaderName; + public final class HttpMetadataAdapter implements Http2Header { private final HttpServletRequest request; @@ -50,6 +53,10 @@ public HttpHeaders headers() { headers.add(key, ven.nextElement()); } } + headers.add(PseudoHeaderName.METHOD.value(), method()); + headers.add(PseudoHeaderName.SCHEME.value(), request.getScheme()); + headers.add(PseudoHeaderName.AUTHORITY.value(), request.getHeader(HttpHeaderNames.HOST.getName())); + headers.add(PseudoHeaderName.PROTOCOL.value(), request.getProtocol()); this.headers = headers; } return headers; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Constants.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Constants.java index 7798481a2a2..7a1c9682c34 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Constants.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Constants.java @@ -25,6 +25,9 @@ public final class Constants { public static final String DEFAULT_GROUP = "default"; public static final String GLOBAL_GROUP = ""; + public static final String X_API_GROUP = "x-api-group"; + public static final String X_API_VERSION = "x-api-version"; + public static final String X_JAVA_TYPE = "x-java-type"; public static final String X_JAVA_METHOD = "x-java-method"; public static final String X_JAVA_PARAM = "x-java-param"; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionFilter.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionFilter.java index 741c1fc212d..4369abe44a7 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionFilter.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionFilter.java @@ -375,6 +375,8 @@ private void filterSchema( filterSchema(it::next, it::set, schema, filters, context); } } + + filterSchema(schema::getNot, schema::setNot, schema, filters, context); } private void filterSecuritySchemes(Components components, OpenAPIFilter[] filters, Context context) { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionMerger.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionMerger.java index e172c2aa304..38b92806dc4 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionMerger.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/DefinitionMerger.java @@ -88,92 +88,93 @@ private OpenAPINamingStrategy getNamingStrategy() { public OpenAPI merge(List openAPIs, OpenAPIRequest request) { Info info = new Info(); - OpenAPI model = new OpenAPI().setInfo(info); + OpenAPI target = new OpenAPI().setInfo(info); OpenAPIConfig globalConfig = configFactory.getGlobalConfig(); - model.setGlobalConfig(globalConfig); - applyConfig(model, globalConfig); + target.setGlobalConfig(globalConfig); + applyConfig(target, globalConfig); if (openAPIs.isEmpty()) { - return model; + return target; } String group = request.getGroup(); - String version = request.getVersion(); - String[] tags = request.getTag(); - String[] services = request.getService(); - if (group == null) { group = Constants.DEFAULT_GROUP; } - model.setGroup(group); + target.setGroup(group); + + String version = request.getVersion(); if (version != null) { info.setVersion(version); } - model.setOpenapi(Helper.formatSpecVersion(request.getOpenapi())); + target.setOpenapi(Helper.formatSpecVersion(request.getOpenapi())); OpenAPIConfig config = configFactory.getConfig(group); - model.setConfig(config); + target.setConfig(config); - for (OpenAPI api : openAPIs) { - if (isServiceNotMatch(api.getMeta().getServiceInterface(), services)) { + String[] tags = request.getTag(); + String[] services = request.getService(); + for (int i = openAPIs.size() - 1; i >= 0; i--) { + OpenAPI source = openAPIs.get(i); + if (isServiceNotMatch(source.getMeta().getServiceInterface(), services)) { continue; } - if (group.equals(api.getGroup())) { - mergeBasic(model, api); + if (group.equals(source.getGroup())) { + mergeBasic(target, source); } - mergePaths(model, api, group, version, tags); + mergePaths(target, source, group, version, tags); - mergeSecuritySchemes(model, api); + mergeSecuritySchemes(target, source); - mergeTags(model, api); + mergeTags(target, source); } - applyConfig(model, config); + applyConfig(target, config); - addSchemas(model, version, group); + addSchemas(target, version, group); - completeOperations(model); + completeOperations(target); - completeModel(model); + completeModel(target); - return model; + return target; } - private void applyConfig(OpenAPI api, OpenAPIConfig config) { + private void applyConfig(OpenAPI target, OpenAPIConfig config) { if (config == null) { return; } - Info info = api.getInfo(); - setValue(info::setTitle, config::getInfoTitle); - setValue(info::setDescription, config::getInfoDescription); - setValue(info::setVersion, config::getInfoVersion); + Info info = target.getInfo(); + setValue(config::getInfoTitle, info::setTitle); + setValue(config::getInfoDescription, info::setDescription); + setValue(config::getInfoVersion, info::setVersion); Contact contact = info.getContact(); if (contact == null) { info.setContact(contact = new Contact()); } - setValue(contact::setName, config::getInfoContactName); - setValue(contact::setUrl, config::getInfoContactUrl); - setValue(contact::setEmail, config::getInfoContactEmail); + setValue(config::getInfoContactName, contact::setName); + setValue(config::getInfoContactUrl, contact::setUrl); + setValue(config::getInfoContactEmail, contact::setEmail); - ExternalDocs externalDocs = api.getExternalDocs(); + ExternalDocs externalDocs = target.getExternalDocs(); if (externalDocs == null) { - api.setExternalDocs(externalDocs = new ExternalDocs()); + target.setExternalDocs(externalDocs = new ExternalDocs()); } - setValue(externalDocs::setDescription, config::getExternalDocsDescription); - setValue(externalDocs::setUrl, config::getExternalDocsUrl); + setValue(config::getExternalDocsDescription, externalDocs::setDescription); + setValue(config::getExternalDocsUrl, externalDocs::setUrl); String[] servers = config.getServers(); if (servers != null) { - api.setServers(Arrays.stream(servers).map(Helper::parseServer).collect(Collectors.toList())); + target.setServers(Arrays.stream(servers).map(Helper::parseServer).collect(Collectors.toList())); } - Components components = api.getComponents(); - if (api.getComponents() == null) { - api.setComponents(components = new Components()); + Components components = target.getComponents(); + if (target.getComponents() == null) { + target.setComponents(components = new Components()); } String securityScheme = config.getSecurityScheme(); @@ -194,86 +195,86 @@ private void applyConfig(OpenAPI api, OpenAPIConfig config) { if (SECURITY_TYPE == null) { SECURITY_TYPE = OpenAPI.class.getDeclaredField("security").getGenericType(); } - api.setSecurity(JsonUtils.toJavaObject(securityScheme, SECURITY_TYPE)); + target.setSecurity(JsonUtils.toJavaObject(securityScheme, SECURITY_TYPE)); } catch (NoSuchFieldException ignored) { } } } - private void mergeBasic(OpenAPI api, OpenAPI from) { - mergeInfo(api, from); + private void mergeBasic(OpenAPI target, OpenAPI source) { + mergeInfo(target, source); - if (api.getServers() == null) { - api.setServers(Node.clone(from.getServers())); + if (target.getServers() == null) { + target.setServers(Node.clone(source.getServers())); } - List fromSecurity = from.getSecurity(); - if (api.getSecurity() == null) { - api.setSecurity(Node.clone(fromSecurity)); + List sourceSecurity = source.getSecurity(); + if (target.getSecurity() == null) { + target.setSecurity(Node.clone(sourceSecurity)); } - ExternalDocs fromExternalDocs = from.getExternalDocs(); - if (fromExternalDocs != null) { - ExternalDocs externalDocs = api.getExternalDocs(); - setValue(externalDocs::setDescription, fromExternalDocs::getDescription); - setValue(externalDocs::setUrl, fromExternalDocs::getUrl); - externalDocs.addExtensions(fromExternalDocs.getExtensions()); + ExternalDocs sourceExternalDocs = source.getExternalDocs(); + if (sourceExternalDocs != null) { + ExternalDocs targetExternalDocs = target.getExternalDocs(); + setValue(sourceExternalDocs::getDescription, targetExternalDocs::setDescription); + setValue(sourceExternalDocs::getUrl, targetExternalDocs::setUrl); + targetExternalDocs.addExtensions(sourceExternalDocs.getExtensions()); } - api.addExtensions(from.getExtensions()); + target.addExtensions(source.getExtensions()); } - private void mergeInfo(OpenAPI api, OpenAPI from) { - Info fromInfo = from.getInfo(); - if (fromInfo == null) { + private void mergeInfo(OpenAPI target, OpenAPI source) { + Info sourceInfo = source.getInfo(); + if (sourceInfo == null) { return; } - Info info = api.getInfo(); - setValue(info::setTitle, fromInfo::getTitle); - setValue(info::setSummary, fromInfo::getSummary); - setValue(info::setDescription, fromInfo::getDescription); - setValue(info::setTermsOfService, fromInfo::getTermsOfService); - setValue(info::setVersion, fromInfo::getVersion); + Info info = target.getInfo(); + setValue(sourceInfo::getTitle, info::setTitle); + setValue(sourceInfo::getSummary, info::setSummary); + setValue(sourceInfo::getDescription, info::setDescription); + setValue(sourceInfo::getTermsOfService, info::setTermsOfService); + setValue(sourceInfo::getVersion, info::setVersion); - Contact fromContact = fromInfo.getContact(); - if (fromContact != null) { + Contact sourceContact = sourceInfo.getContact(); + if (sourceContact != null) { Contact contact = info.getContact(); - setValue(contact::setName, fromContact::getName); - setValue(contact::setUrl, fromContact::getUrl); - setValue(contact::setEmail, fromContact::getEmail); + setValue(sourceContact::getName, contact::setName); + setValue(sourceContact::getUrl, contact::setUrl); + setValue(sourceContact::getEmail, contact::setEmail); - contact.addExtensions(fromContact.getExtensions()); + contact.addExtensions(sourceContact.getExtensions()); } - License fromLicense = fromInfo.getLicense(); - if (fromLicense != null) { + License sourceLicense = sourceInfo.getLicense(); + if (sourceLicense != null) { License license = info.getLicense(); - setValue(license::setName, fromLicense::getName); - setValue(license::setUrl, fromLicense::getUrl); - license.addExtensions(fromLicense.getExtensions()); + setValue(sourceLicense::getName, license::setName); + setValue(sourceLicense::getUrl, license::setUrl); + license.addExtensions(sourceLicense.getExtensions()); } - info.addExtensions(fromInfo.getExtensions()); + info.addExtensions(sourceInfo.getExtensions()); } - private void mergePaths(OpenAPI api, OpenAPI from, String group, String version, String[] tags) { - Map fromPaths = from.getPaths(); - if (fromPaths == null) { + private void mergePaths(OpenAPI target, OpenAPI source, String group, String version, String[] tags) { + Map sourcePaths = source.getPaths(); + if (sourcePaths == null) { return; } - Map paths = api.getPaths(); + Map paths = target.getPaths(); if (paths == null) { - api.setPaths(paths = new TreeMap<>()); + target.setPaths(paths = new TreeMap<>()); } - for (Entry entry : fromPaths.entrySet()) { + for (Entry entry : sourcePaths.entrySet()) { String path = entry.getKey(); - PathItem fromPathItem = entry.getValue(); + PathItem sourcePathItem = entry.getValue(); PathItem pathItem = paths.get(path); if (pathItem != null) { - String ref = fromPathItem.getRef(); + String ref = sourcePathItem.getRef(); if (ref != null) { pathItem = paths.get(ref); } @@ -281,64 +282,64 @@ private void mergePaths(OpenAPI api, OpenAPI from, String group, String version, if (pathItem == null) { paths.put(path, pathItem = new PathItem()); } - mergePath(path, pathItem, fromPathItem, group, version, tags); + mergePath(path, pathItem, sourcePathItem, group, version, tags); } } - private void mergePath(String path, PathItem pathItem, PathItem from, String group, String version, String[] tags) { - if (pathItem.getRef() == null) { - pathItem.setRef(from.getRef()); + private void mergePath(String path, PathItem target, PathItem source, String group, String version, String[] tags) { + if (target.getRef() == null) { + target.setRef(source.getRef()); } - if (pathItem.getSummary() == null) { - pathItem.setSummary(from.getSummary()); + if (target.getSummary() == null) { + target.setSummary(source.getSummary()); } - if (pathItem.getDescription() == null) { - pathItem.setDescription(from.getDescription()); + if (target.getDescription() == null) { + target.setDescription(source.getDescription()); } - Map fromOperations = from.getOperations(); - if (fromOperations != null) { - for (Entry entry : fromOperations.entrySet()) { + Map sourceOperations = source.getOperations(); + if (sourceOperations != null) { + for (Entry entry : sourceOperations.entrySet()) { HttpMethods httpMethod = entry.getKey(); - Operation fromOperation = entry.getValue(); - if (isGroupNotMatch(group, fromOperation.getGroup()) - || isVersionNotMatch(version, fromOperation.getVersion()) - || isTagNotMatch(tags, fromOperation.getTags())) { + Operation sourceOperation = entry.getValue(); + if (isGroupNotMatch(group, sourceOperation.getGroup()) + || isVersionNotMatch(version, sourceOperation.getVersion()) + || isTagNotMatch(tags, sourceOperation.getTags())) { continue; } - Operation operation = pathItem.getOperation(httpMethod); + Operation operation = target.getOperation(httpMethod); if (operation == null) { - pathItem.addOperation(httpMethod, fromOperation.clone()); + target.addOperation(httpMethod, sourceOperation.clone()); } else if (operation.getMeta() != null) { LOG.internalWarn( "Operation already exists, path='{}', httpMethod='{}', method={}", path, httpMethod, - fromOperation.getMeta()); + sourceOperation.getMeta()); } } } - if (pathItem.getServers() == null) { - List fromServers = from.getServers(); - if (fromServers != null) { - pathItem.setServers(Node.clone(fromServers)); + if (target.getServers() == null) { + List sourceServers = source.getServers(); + if (sourceServers != null) { + target.setServers(Node.clone(sourceServers)); } } - List fromParameters = from.getParameters(); - if (fromParameters != null) { - if (pathItem.getParameters() == null) { - pathItem.setParameters(Node.clone(fromParameters)); + List sourceParameters = source.getParameters(); + if (sourceParameters != null) { + if (target.getParameters() == null) { + target.setParameters(Node.clone(sourceParameters)); } else { - for (Parameter parameter : fromParameters) { - pathItem.addParameter(parameter.clone()); + for (Parameter parameter : sourceParameters) { + target.addParameter(parameter.clone()); } } } - pathItem.addExtensions(from.getExtensions()); + target.addExtensions(source.getExtensions()); } private static boolean isServiceNotMatch(String apiService, String[] services) { @@ -353,14 +354,14 @@ private static boolean isServiceNotMatch(String apiService, String[] services) { return true; } - private static boolean isGroupNotMatch(String group, String fromGroup) { - return !(fromGroup == null && Constants.DEFAULT_GROUP.equals(group) + private static boolean isGroupNotMatch(String group, String sourceGroup) { + return !(sourceGroup == null && Constants.DEFAULT_GROUP.equals(group) || Constants.ALL_GROUP.equals(group) - || group.equals(fromGroup)); + || group.equals(sourceGroup)); } - private static boolean isVersionNotMatch(String version, String fromVersion) { - return !(version == null || fromVersion == null || Helper.isVersionGreaterOrEqual(fromVersion, version)); + private static boolean isVersionNotMatch(String version, String sourceVersion) { + return !(version == null || sourceVersion == null || Helper.isVersionGreaterOrEqual(sourceVersion, version)); } private static boolean isTagNotMatch(String[] tags, Set operationTags) { @@ -375,50 +376,47 @@ private static boolean isTagNotMatch(String[] tags, Set operationTags) { return true; } - private void mergeSecuritySchemes(OpenAPI api, OpenAPI from) { - Components fromComponents = from.getComponents(); - if (fromComponents == null) { + private void mergeSecuritySchemes(OpenAPI target, OpenAPI source) { + Components sourceComponents = source.getComponents(); + if (sourceComponents == null) { return; } - Map fromSecuritySchemes = fromComponents.getSecuritySchemes(); - if (fromSecuritySchemes == null) { + Map sourceSecuritySchemes = sourceComponents.getSecuritySchemes(); + if (sourceSecuritySchemes == null) { return; } - Components components = api.getComponents(); + Components components = target.getComponents(); Map securitySchemes = components.getSecuritySchemes(); if (securitySchemes == null) { - components.setSecuritySchemes(Node.clone(fromSecuritySchemes)); + components.setSecuritySchemes(Node.clone(sourceSecuritySchemes)); } else { - for (Entry entry : fromSecuritySchemes.entrySet()) { - String key = entry.getKey(); - if (securitySchemes.containsKey(key)) { - continue; - } - securitySchemes.put(key, entry.getValue().clone()); + for (Entry entry : sourceSecuritySchemes.entrySet()) { + securitySchemes.computeIfAbsent( + entry.getKey(), k -> entry.getValue().clone()); } } } - private void mergeTags(OpenAPI api, OpenAPI from) { - List fromTags = from.getTags(); - if (fromTags == null) { + private void mergeTags(OpenAPI target, OpenAPI source) { + List sourceTags = source.getTags(); + if (sourceTags == null) { return; } - if (api.getTags() == null) { - api.setTags(Node.clone(fromTags)); + if (target.getTags() == null) { + target.setTags(Node.clone(sourceTags)); } else { - for (Tag tag : fromTags) { - api.addTag(tag.clone()); + for (Tag tag : sourceTags) { + target.addTag(tag.clone()); } } } - private void addSchemas(OpenAPI api, String version, String group) { + private void addSchemas(OpenAPI target, String version, String group) { Map schemas = new IdentityHashMap<>(); - for (PathItem pathItem : api.getPaths().values()) { + for (PathItem pathItem : target.getPaths().values()) { Map operations = pathItem.getOperations(); if (operations == null) { continue; @@ -469,9 +467,9 @@ private void addSchemas(OpenAPI api, String version, String group) { } } - Components components = api.getComponents(); + Components components = target.getComponents(); if (components == null) { - api.setComponents(components = new Components()); + target.setComponents(components = new Components()); } Set names = CollectionUtils.newHashSet(schemas.size()); @@ -487,10 +485,10 @@ private void addSchemas(OpenAPI api, String version, String group) { String name = schema.getName(); if (name == null) { Class clazz = schema.getJavaType(); - name = strategy.generateSchemaName(clazz, api); + name = strategy.generateSchemaName(clazz, target); for (int i = 1; i < 100; i++) { if (names.contains(name)) { - name = strategy.resolveSchemaNameConflict(i, name, clazz, api); + name = strategy.resolveSchemaNameConflict(i, name, clazz, target); } else { names.add(name); break; @@ -568,15 +566,15 @@ private void addSchema(Schema schema, Map schemas, String group, }); } - private void completeOperations(OpenAPI api) { - Map paths = api.getPaths(); + private void completeOperations(OpenAPI target) { + Map paths = target.getPaths(); if (paths == null) { return; } Set allOperationIds = new HashSet<>(32); Set allTags = new HashSet<>(32); - api.walkOperations(operation -> { + target.walkOperations(operation -> { String operationId = operation.getOperationId(); if (operationId != null) { allOperationIds.add(operationId); @@ -588,15 +586,15 @@ private void completeOperations(OpenAPI api) { }); OpenAPINamingStrategy strategy = getNamingStrategy(); - api.walkOperations(operation -> { + target.walkOperations(operation -> { String id = operation.getOperationId(); if (id != null) { return; } - id = strategy.generateOperationId(operation.getMeta(), api); + id = strategy.generateOperationId(operation.getMeta(), target); for (int i = 1; i < 100; i++) { if (allOperationIds.contains(id)) { - id = strategy.resolveOperationIdConflict(i, id, operation.getMeta(), api); + id = strategy.resolveOperationIdConflict(i, id, operation.getMeta(), target); } else { allOperationIds.add(id); break; @@ -605,7 +603,7 @@ private void completeOperations(OpenAPI api) { operation.setOperationId(id); }); - List tags = api.getTags(); + List tags = target.getTags(); if (tags != null) { ListIterator it = tags.listIterator(); while (it.hasNext()) { @@ -617,17 +615,17 @@ private void completeOperations(OpenAPI api) { } } - private void completeModel(OpenAPI api) { - Info info = api.getInfo(); + private void completeModel(OpenAPI target) { + Info info = target.getInfo(); if (info.getTitle() == null) { info.setTitle("Dubbo OpenAPI"); } if (info.getVersion() == null) { info.setVersion("v1"); } - ExternalDocs docs = api.getExternalDocs(); + ExternalDocs docs = target.getExternalDocs(); if (docs.getUrl() == null && docs.getDescription() == null) { - docs.setUrl("../redoc/index.html?group=" + api.getGroup()).setDescription("ReDoc"); + docs.setUrl("../redoc/index.html?group=" + target.getGroup()).setDescription("ReDoc"); } } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Helper.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Helper.java index 135f466c904..729b3205d07 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Helper.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/openapi/Helper.java @@ -17,8 +17,10 @@ package org.apache.dubbo.rpc.protocol.tri.rest.openapi; import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.remoting.http12.rest.OpenAPIRequest; import org.apache.dubbo.remoting.http12.rest.ParamType; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.AnnotationMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.MethodMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; import org.apache.dubbo.rpc.protocol.tri.rest.openapi.model.Parameter.In; @@ -247,13 +249,34 @@ public static Server parseServer(String server) { return new Server().setDescription(description).setUrl(url); } - public static void setValue(Consumer setter, Supplier getter) { + public static void setValue(Supplier getter, Consumer setter) { String value = trim(getter.get()); if (value != null) { setter.accept(value); } } + public static void setBoolValue(Supplier getter, Consumer setter) { + String value = trim(getter.get()); + if (value != null) { + setter.accept(StringUtils.toBoolean(value)); + } + } + + public static void setValue(AnnotationMeta schema, String key, Consumer setter) { + String value = trim(schema.getString(key)); + if (value != null) { + setter.accept(value); + } + } + + public static void setBoolValue(AnnotationMeta schema, String key, Consumer setter) { + Boolean value = schema.getBoolean(key); + if (Boolean.TRUE.equals(value)) { + setter.accept(true); + } + } + public static String pathToRef(String path) { StringBuilder sb = new StringBuilder(path.length() + 16); sb.append("#/paths/"); diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/BasicOpenAPIDefinitionResolver.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/BasicOpenAPIDefinitionResolver.java index a6a348e7d31..7ec64728724 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/BasicOpenAPIDefinitionResolver.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/BasicOpenAPIDefinitionResolver.java @@ -39,8 +39,9 @@ import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Map; -import java.util.function.Consumer; +import static org.apache.dubbo.rpc.protocol.tri.rest.openapi.Helper.setBoolValue; +import static org.apache.dubbo.rpc.protocol.tri.rest.openapi.Helper.setValue; import static org.apache.dubbo.rpc.protocol.tri.rest.openapi.Helper.trim; @Activate(order = 100) @@ -150,8 +151,8 @@ public Schema resolve(ParameterMeta parameter, SchemaContext context, SchemaChai setValue(annoMeta, "name", schema::setName); String title = trim(annoMeta.getValue()); schema.setTitle(title == null ? trim(annoMeta.getString("title")) : title); - setValue(annoMeta, "title", schema::setTitle); setValue(annoMeta, "description", schema::setDescription); + setValue(annoMeta, "defaultValue", schema::setDefaultValue); setValue(annoMeta, "max", v -> schema.setMaxLength(Integer.parseInt(v))); setValue(annoMeta, "min", v -> schema.setMinLength(Integer.parseInt(v))); setValue(annoMeta, "pattern", schema::setPattern); @@ -161,7 +162,6 @@ public Schema resolve(ParameterMeta parameter, SchemaContext context, SchemaChai schema.setEnumeration(Arrays.asList(enumItems)); } setBoolValue(annoMeta, "required", schema::setRequired); - setValue(annoMeta, "defaultValue", schema::setDefaultValue); setBoolValue(annoMeta, "readOnly", schema::setReadOnly); setBoolValue(annoMeta, "writeOnly", schema::setWriteOnly); setBoolValue(annoMeta, "nullable", schema::setNullable); @@ -175,18 +175,4 @@ public Boolean acceptProperty(BeanMeta bean, PropertyMeta property) { AnnotationMeta annoMeta = property.getAnnotation(Annotations.Schema); return annoMeta == null ? null : annoMeta.getBoolean(HIDDEN); } - - private static void setValue(AnnotationMeta schema, String key, Consumer setter) { - String value = trim(schema.getString(key)); - if (value != null) { - setter.accept(value); - } - } - - private static void setBoolValue(AnnotationMeta schema, String key, Consumer setter) { - Boolean value = schema.getBoolean(key); - if (Boolean.TRUE.equals(value)) { - setter.accept(true); - } - } }