From 79a03c2800252e0e1fb18471f0876f97ad415973 Mon Sep 17 00:00:00 2001
From: Haotian Zhang <928016560@qq.com>
Date: Mon, 25 Sep 2023 14:46:40 +0800
Subject: [PATCH] feat:support service contract reporting. (#1135)
---
CHANGELOG.md | 1 +
pom.xml | 1 +
spring-cloud-starter-tencent-all/pom.xml | 22 +-
.../adapter/PolarisConfigFileLocator.java | 4 +-
.../PolarisConfigPropertyAutoRefresher.java | 4 +-
.../pom.xml | 69 ++++++
.../contract/PolarisContractReporter.java | 150 ++++++++++++
.../PolarisSwaggerApplicationListener.java | 35 +++
.../polaris/contract/SwaggerContext.java | 36 +++
.../contract/config/ContractProperties.java | 46 ++++
.../config/ExtendedContractProperties.java | 26 +++
.../config/PolarisContractModifier.java | 52 +++++
.../config/PolarisContractProperties.java | 122 ++++++++++
...isContractPropertiesAutoConfiguration.java | 48 ++++
...tractPropertiesBootstrapConfiguration.java | 34 +++
.../PolarisSwaggerAutoConfiguration.java | 147 ++++++++++++
.../polaris/contract/utils/PackageUtil.java | 214 ++++++++++++++++++
.../main/resources/META-INF/spring.factories | 7 +
.../polaris/PolarisDiscoveryProperties.java | 2 +-
.../cloud/common/constant/OrderConstant.java | 5 +
spring-cloud-tencent-coverage/pom.xml | 5 +
spring-cloud-tencent-dependencies/pom.xml | 26 +++
.../discovery-caller-service/pom.xml | 5 +
.../caller/DiscoveryCallerController.java | 2 +-
.../plugin/PluginOrderConstant.java | 22 --
25 files changed, 1052 insertions(+), 33 deletions(-)
create mode 100644 spring-cloud-starter-tencent-polaris-contract/pom.xml
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisSwaggerApplicationListener.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/SwaggerContext.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ExtendedContractProperties.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractModifier.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesAutoConfiguration.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesBootstrapConfiguration.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java
create mode 100644 spring-cloud-starter-tencent-polaris-contract/src/main/resources/META-INF/spring.factories
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9eec1f9..6b815393 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,3 +5,4 @@
- [Refactoring:remove invalid @AutoConfigureAfter and @AutoConfigureBefore from discovery client automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1118)
- [fix:fix feign url bug when using sleuth.](https://github.com/Tencent/spring-cloud-tencent/pull/1119)
- [refactor:optimize the order and condition matching of service registration automatic configuration.](https://github.com/Tencent/spring-cloud-tencent/pull/1133)
+- [feat:support service contract reporting.](https://github.com/Tencent/spring-cloud-tencent/pull/1135)
diff --git a/pom.xml b/pom.xml
index 23c9868c..a2579ba6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,6 +48,7 @@
spring-cloud-starter-tencent-polaris-ratelimit
spring-cloud-starter-tencent-polaris-circuitbreaker
spring-cloud-starter-tencent-polaris-router
+ spring-cloud-starter-tencent-polaris-contract
spring-cloud-tencent-plugin-starters
spring-cloud-tencent-dependencies
spring-cloud-starter-tencent-all
diff --git a/spring-cloud-starter-tencent-all/pom.xml b/spring-cloud-starter-tencent-all/pom.xml
index 1c45b11d..fc6470e9 100644
--- a/spring-cloud-starter-tencent-all/pom.xml
+++ b/spring-cloud-starter-tencent-all/pom.xml
@@ -45,6 +45,11 @@
spring-cloud-starter-tencent-metadata-transfer
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-contract
+
+
org.springframework.cloud
@@ -88,12 +93,19 @@
true
-
-
- META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports
+
+
+
+ META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports
+
-
- META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+
+
+ META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
index 634807a1..0e67d7a1 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigFileLocator.java
@@ -102,7 +102,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
private void initCustomPolarisConfigExtensionFiles(CompositePropertySource compositePropertySource) {
if (polarisConfigCustomExtensionLayer == null) {
- LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps");
+ LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return;
}
polarisConfigCustomExtensionLayer.initConfigFiles(environment, compositePropertySource, polarisPropertySourceManager, configFileService);
@@ -110,7 +110,7 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
private void afterLocatePolarisConfigExtension(CompositePropertySource compositePropertySource) {
if (polarisConfigCustomExtensionLayer == null) {
- LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps");
+ LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return;
}
polarisConfigCustomExtensionLayer.executeAfterLocateConfigReturning(compositePropertySource);
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigPropertyAutoRefresher.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigPropertyAutoRefresher.java
index 904b8709..47ff8d95 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigPropertyAutoRefresher.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisConfigPropertyAutoRefresher.java
@@ -89,7 +89,7 @@ public abstract class PolarisConfigPropertyAutoRefresher implements ApplicationL
private void customInitRegisterPolarisConfig(PolarisConfigPropertyAutoRefresher polarisConfigPropertyAutoRefresher) {
if (polarisConfigCustomExtensionLayer == null) {
- LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps");
+ LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return;
}
polarisConfigCustomExtensionLayer.initRegisterConfig(polarisConfigPropertyAutoRefresher);
@@ -139,7 +139,7 @@ public abstract class PolarisConfigPropertyAutoRefresher implements ApplicationL
private void customRegisterPolarisConfigPublishChangeListener(PolarisPropertySource polarisPropertySource) {
if (polarisConfigCustomExtensionLayer == null) {
- LOGGER.debug("[SCT Config] PolarisAdaptorTsfConfigExtensionLayer is not init, ignore the following execution steps");
+ LOGGER.debug("[SCT Config] PolarisConfigCustomExtensionLayer is not init, ignore the following execution steps");
return;
}
polarisConfigCustomExtensionLayer.executeRegisterPublishChangeListener(polarisPropertySource);
diff --git a/spring-cloud-starter-tencent-polaris-contract/pom.xml b/spring-cloud-starter-tencent-polaris-contract/pom.xml
new file mode 100644
index 00000000..c17c92b3
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/pom.xml
@@ -0,0 +1,69 @@
+
+
+
+ spring-cloud-tencent
+ com.tencent.cloud
+ ${revision}
+ ../pom.xml
+
+ 4.0.0
+
+ spring-cloud-starter-tencent-polaris-contract
+ Spring Cloud Starter Tencent Polaris Contract
+
+
+
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-discovery
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ true
+
+
+
+
+ io.springfox
+ springfox-boot-starter
+
+
+ swagger-models
+ io.swagger
+
+
+ swagger-annotations
+ io.swagger
+
+
+
+
+
+ io.swagger
+ swagger-models
+
+
+
+ io.swagger
+ swagger-annotations
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java
new file mode 100644
index 00000000..dd421b45
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisContractReporter.java
@@ -0,0 +1,150 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.tencent.cloud.common.util.JacksonUtils;
+import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
+import com.tencent.polaris.api.core.ProviderAPI;
+import com.tencent.polaris.api.plugin.server.InterfaceDescriptor;
+import com.tencent.polaris.api.plugin.server.ReportServiceContractRequest;
+import com.tencent.polaris.api.plugin.server.ReportServiceContractResponse;
+import io.swagger.models.HttpMethod;
+import io.swagger.models.Operation;
+import io.swagger.models.Path;
+import io.swagger.models.Swagger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import springfox.documentation.service.Documentation;
+import springfox.documentation.spring.web.DocumentationCache;
+import springfox.documentation.spring.web.json.JsonSerializer;
+import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper;
+
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.lang.NonNull;
+import org.springframework.util.CollectionUtils;
+
+public class PolarisContractReporter implements ApplicationListener {
+
+ private final Logger LOG = LoggerFactory.getLogger(PolarisContractReporter.class);
+ private final ServiceModelToSwagger2Mapper swagger2Mapper;
+ private final DocumentationCache documentationCache;
+ private final JsonSerializer jsonSerializer;
+ private final String groupName;
+
+ private final ProviderAPI providerAPI;
+
+ private final PolarisDiscoveryProperties polarisDiscoveryProperties;
+
+ public PolarisContractReporter(DocumentationCache documentationCache, ServiceModelToSwagger2Mapper swagger2Mapper,
+ JsonSerializer jsonSerializer, String groupName, ProviderAPI providerAPI,
+ PolarisDiscoveryProperties polarisDiscoveryProperties) {
+ this.swagger2Mapper = swagger2Mapper;
+ this.documentationCache = documentationCache;
+ this.jsonSerializer = jsonSerializer;
+ this.groupName = groupName;
+ this.providerAPI = providerAPI;
+ this.polarisDiscoveryProperties = polarisDiscoveryProperties;
+ }
+
+ @Override
+ public void onApplicationEvent(@NonNull ApplicationReadyEvent applicationReadyEvent) {
+ try {
+ Documentation documentation = documentationCache.documentationByGroup(groupName);
+ Swagger swagger = swagger2Mapper.mapDocumentation(documentation);
+ if (swagger != null) {
+ ReportServiceContractRequest request = new ReportServiceContractRequest();
+ request.setName(polarisDiscoveryProperties.getService());
+ request.setNamespace(polarisDiscoveryProperties.getNamespace());
+ request.setService(polarisDiscoveryProperties.getService());
+ request.setProtocol("http");
+ request.setVersion(polarisDiscoveryProperties.getVersion());
+ List interfaceDescriptorList = getInterfaceDescriptorFromSwagger(swagger);
+ request.setInterfaceDescriptors(interfaceDescriptorList);
+ ReportServiceContractResponse response = providerAPI.reportServiceContract(request);
+ LOG.info("Service contract [Namespace: {}. Name: {}. Service: {}. Protocol:{}. Version: {}. API counter: {}] is reported.",
+ request.getNamespace(), request.getName(), request.getService(), request.getProtocol(),
+ request.getVersion(), request.getInterfaceDescriptors().size());
+ if (LOG.isDebugEnabled()) {
+ String jsonValue = JacksonUtils.serialize2Json(swagger);
+ LOG.debug("OpenApi json data: {}", jsonValue);
+ }
+ }
+ else {
+ LOG.warn("Swagger or json is null, documentationCache keys:{}, group:{}", documentationCache.all()
+ .keySet(), groupName);
+ }
+ }
+ catch (Throwable t) {
+ LOG.error("Report contract failed.", t);
+ }
+ }
+
+ private List getInterfaceDescriptorFromSwagger(Swagger swagger) {
+ List interfaceDescriptorList = new ArrayList<>();
+ Map paths = swagger.getPaths();
+ for (Map.Entry p : paths.entrySet()) {
+ Path path = p.getValue();
+ Map operationMap = getOperationMapFromPath(path);
+ if (CollectionUtils.isEmpty(operationMap)) {
+ continue;
+ }
+ for (Map.Entry o : operationMap.entrySet()) {
+ InterfaceDescriptor interfaceDescriptor = new InterfaceDescriptor();
+ interfaceDescriptor.setPath(p.getKey());
+ interfaceDescriptor.setMethod(o.getKey());
+ interfaceDescriptor.setContent(JacksonUtils.serialize2Json(p.getValue()));
+ interfaceDescriptorList.add(interfaceDescriptor);
+ }
+ }
+ return interfaceDescriptorList;
+ }
+
+ private Map getOperationMapFromPath(Path path) {
+ Map operationMap = new HashMap<>();
+
+ if (path.getGet() != null) {
+ operationMap.put(HttpMethod.GET.name(), path.getGet());
+ }
+ if (path.getPut() != null) {
+ operationMap.put(HttpMethod.PUT.name(), path.getPut());
+ }
+ if (path.getPost() != null) {
+ operationMap.put(HttpMethod.POST.name(), path.getPost());
+ }
+ if (path.getHead() != null) {
+ operationMap.put(HttpMethod.HEAD.name(), path.getHead());
+ }
+ if (path.getDelete() != null) {
+ operationMap.put(HttpMethod.DELETE.name(), path.getDelete());
+ }
+ if (path.getPatch() != null) {
+ operationMap.put(HttpMethod.PATCH.name(), path.getPatch());
+ }
+ if (path.getOptions() != null) {
+ operationMap.put(HttpMethod.OPTIONS.name(), path.getOptions());
+ }
+
+ return operationMap;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisSwaggerApplicationListener.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisSwaggerApplicationListener.java
new file mode 100644
index 00000000..76d4259f
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/PolarisSwaggerApplicationListener.java
@@ -0,0 +1,35 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
+import org.springframework.context.ApplicationListener;
+
+public class PolarisSwaggerApplicationListener implements ApplicationListener {
+
+ @Override
+ public void onApplicationEvent(ApplicationEnvironmentPreparedEvent startingEvent) {
+ SpringApplication application = startingEvent.getSpringApplication();
+ Class> mainClass = application.getMainApplicationClass();
+ if (mainClass == null) {
+ return;
+ }
+ SwaggerContext.setAttribute(String.format("$%s", "MainClass"), mainClass);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/SwaggerContext.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/SwaggerContext.java
new file mode 100644
index 00000000..b4f24794
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/SwaggerContext.java
@@ -0,0 +1,36 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+public final class SwaggerContext {
+ private static final ConcurrentHashMap attribute = new ConcurrentHashMap<>();
+
+ private SwaggerContext() {
+
+ }
+
+ public static void setAttribute(String key, Object value) {
+ attribute.put(key, value);
+ }
+
+ public static Object getAttribute(String key) {
+ return attribute.get(key);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java
new file mode 100644
index 00000000..32970b06
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ContractProperties.java
@@ -0,0 +1,46 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.config;
+
+/**
+ * Interface for contract properties.
+ *
+ * @author Haotian Zhang
+ */
+public interface ContractProperties {
+
+ boolean isEnabled();
+
+ void setEnabled(boolean enabled);
+
+ String getBasePackage();
+
+ void setBasePackage(String basePackage);
+
+ String getExcludePath();
+
+ void setExcludePath(String excludePath);
+
+ String getGroup();
+
+ void setGroup(String group);
+
+ String getBasePath();
+
+ void setBasePath(String basePath);
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ExtendedContractProperties.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ExtendedContractProperties.java
new file mode 100644
index 00000000..22830fa8
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/ExtendedContractProperties.java
@@ -0,0 +1,26 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.config;
+
+/**
+ * Extend contract properties.
+ *
+ * @author Haotian Zhang
+ */
+public interface ExtendedContractProperties extends ContractProperties {
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractModifier.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractModifier.java
new file mode 100644
index 00000000..f48a01d2
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractModifier.java
@@ -0,0 +1,52 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.config;
+
+import java.util.List;
+
+import com.tencent.cloud.common.constant.OrderConstant;
+import com.tencent.cloud.polaris.context.PolarisConfigModifier;
+import com.tencent.polaris.factory.config.ConfigurationImpl;
+import com.tencent.polaris.factory.config.provider.RegisterConfigImpl;
+
+/**
+ * Modifier of service contract.
+ *
+ * @author Haotian Zhang
+ */
+public class PolarisContractModifier implements PolarisConfigModifier {
+
+ private final PolarisContractProperties polarisContractProperties;
+
+ public PolarisContractModifier(PolarisContractProperties polarisContractProperties) {
+ this.polarisContractProperties = polarisContractProperties;
+ }
+
+ @Override
+ public void modify(ConfigurationImpl configuration) {
+ List registerConfigs = configuration.getProvider().getRegisters();
+ for (RegisterConfigImpl registerConfig : registerConfigs) {
+ registerConfig.setReportServiceContractEnable(polarisContractProperties.isEnabled());
+ }
+ }
+
+ @Override
+ public int getOrder() {
+ return OrderConstant.Modifier.SERVICE_CONTRACT_ORDER;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java
new file mode 100644
index 00000000..edafa77f
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractProperties.java
@@ -0,0 +1,122 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.config;
+
+import java.util.Objects;
+
+import javax.annotation.Nullable;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Properties for Polaris contract.
+ *
+ * @author Haotian Zhang
+ */
+@ConfigurationProperties("spring.cloud.polaris.contract")
+public class PolarisContractProperties implements ContractProperties {
+
+ private final ExtendedContractProperties extendContractProperties;
+
+ private boolean enabled = true;
+ /**
+ * Packages to be scanned. Split by ",".
+ */
+ private String basePackage;
+ /**
+ * Paths to be excluded. Split by ",".
+ */
+ private String excludePath;
+ /**
+ * Group to create swagger docket.
+ */
+ private String group = "default";
+ /**
+ * Base paths to be scanned. Split by ",".
+ */
+ private String basePath = "/**";
+
+ public PolarisContractProperties(@Nullable ExtendedContractProperties extendContractProperties) {
+ this.extendContractProperties = extendContractProperties;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ if (Objects.nonNull(extendContractProperties)) {
+ return extendContractProperties.isEnabled();
+ }
+ return enabled;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ @Override
+ public String getBasePackage() {
+ if (Objects.nonNull(extendContractProperties)) {
+ return extendContractProperties.getBasePackage();
+ }
+ return basePackage;
+ }
+
+ @Override
+ public void setBasePackage(String basePackage) {
+ this.basePackage = basePackage;
+ }
+
+ @Override
+ public String getExcludePath() {
+ if (Objects.nonNull(extendContractProperties)) {
+ return extendContractProperties.getExcludePath();
+ }
+ return excludePath;
+ }
+
+ @Override
+ public void setExcludePath(String excludePath) {
+ this.excludePath = excludePath;
+ }
+
+ @Override
+ public String getGroup() {
+ if (Objects.nonNull(extendContractProperties)) {
+ return extendContractProperties.getGroup();
+ }
+ return group;
+ }
+
+ @Override
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ @Override
+ public String getBasePath() {
+ if (Objects.nonNull(extendContractProperties)) {
+ return extendContractProperties.getBasePath();
+ }
+ return basePath;
+ }
+
+ @Override
+ public void setBasePath(String basePath) {
+ this.basePath = basePath;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesAutoConfiguration.java
new file mode 100644
index 00000000..d3e0edb3
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesAutoConfiguration.java
@@ -0,0 +1,48 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.config;
+
+import javax.annotation.Nullable;
+
+import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Auto configuration for Polaris contract properties.
+ *
+ * @author Haotian Zhang
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnPolarisEnabled
+public class PolarisContractPropertiesAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public PolarisContractProperties polarisContractProperties(@Nullable ExtendedContractProperties extendedContractProperties) {
+ return new PolarisContractProperties(extendedContractProperties);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public PolarisContractModifier polarisContractModifier(PolarisContractProperties polarisContractProperties) {
+ return new PolarisContractModifier(polarisContractProperties);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesBootstrapConfiguration.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesBootstrapConfiguration.java
new file mode 100644
index 00000000..ceb2d102
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisContractPropertiesBootstrapConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+/**
+ * Bootstrap configuration for Polaris contract properties.
+ *
+ * @author Haotian Zhang
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnProperty("spring.cloud.polaris.enabled")
+@Import(PolarisContractPropertiesAutoConfiguration.class)
+public class PolarisContractPropertiesBootstrapConfiguration {
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java
new file mode 100644
index 00000000..c4c720ea
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/config/PolarisSwaggerAutoConfiguration.java
@@ -0,0 +1,147 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.config;
+
+import java.time.LocalDate;
+import java.util.Date;
+import java.util.List;
+import java.util.function.Predicate;
+
+import com.tencent.cloud.polaris.PolarisDiscoveryProperties;
+import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
+import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
+import com.tencent.cloud.polaris.contract.PolarisContractReporter;
+import com.tencent.cloud.polaris.contract.PolarisSwaggerApplicationListener;
+import com.tencent.cloud.polaris.contract.utils.PackageUtil;
+import springfox.boot.starter.autoconfigure.OpenApiAutoConfiguration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.DocumentationCache;
+import springfox.documentation.spring.web.json.JsonSerializer;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnPolarisEnabled
+@ConditionalOnProperty(name = "spring.cloud.polaris.contract.enabled", havingValue = "true", matchIfMissing = true)
+@Import(OpenApiAutoConfiguration.class)
+public class PolarisSwaggerAutoConfiguration {
+
+ static {
+ // After springboot2.6.x, the default path matching strategy of spring MVC is changed from ANT_PATH_MATCHER
+ // mode to PATH_PATTERN_PARSER mode, causing an error. The solution is to switch to the original ANT_PATH_MATCHER mode.
+ System.setProperty("spring.mvc.pathmatch.matching-strategy", "ant-path-matcher");
+ }
+
+ @Bean
+ public Docket polarisDocket(PolarisContractProperties polarisContractProperties) {
+ List> excludePathList = PackageUtil.getExcludePathPredicates(polarisContractProperties.getExcludePath());
+ List> basePathList = PackageUtil.getBasePathPredicates(polarisContractProperties.getBasePath());
+ String basePackage = PackageUtil.scanPackage(polarisContractProperties.getBasePackage());
+
+ Predicate basePathListOr = null;
+ for (Predicate basePathPredicate : basePathList) {
+ if (basePathListOr == null) {
+ basePathListOr = basePathPredicate;
+ }
+ else {
+ basePathListOr = basePathListOr.or(basePathPredicate);
+ }
+ }
+
+ Predicate excludePathListOr = null;
+ for (Predicate excludePathPredicate : excludePathList) {
+ if (excludePathListOr == null) {
+ excludePathListOr = excludePathPredicate;
+ }
+ else {
+ excludePathListOr = excludePathListOr.or(excludePathPredicate);
+ }
+ }
+
+ Predicate pathsPredicate = basePathListOr;
+
+ if (excludePathListOr != null) {
+ excludePathListOr = excludePathListOr.negate();
+ pathsPredicate = pathsPredicate.and(excludePathListOr);
+ }
+
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(PackageUtil.basePackage(basePackage))
+ .paths(pathsPredicate)
+ .build()
+ .groupName(polarisContractProperties.getGroup())
+ .enable(polarisContractProperties.isEnabled())
+ .directModelSubstitute(LocalDate.class, Date.class)
+ .apiInfo(new ApiInfoBuilder()
+ .title("Polaris Swagger API")
+ .description("This is to show polaris api description.")
+ .license("BSD-3-Clause")
+ .licenseUrl("https://opensource.org/licenses/BSD-3-Clause")
+ .termsOfServiceUrl("")
+ .version("1.0.0")
+ .contact(new Contact("", "", ""))
+ .build());
+ }
+
+ @Bean
+ @ConditionalOnBean(Docket.class)
+ @ConditionalOnMissingBean
+ public PolarisContractReporter polarisApiMetadataGrapher(DocumentationCache documentationCache,
+ ServiceModelToSwagger2Mapper swagger2Mapper, JsonSerializer jsonSerializer,
+ PolarisContractProperties polarisContractProperties, PolarisSDKContextManager polarisSDKContextManager,
+ PolarisDiscoveryProperties polarisDiscoveryProperties) {
+ return new PolarisContractReporter(documentationCache, swagger2Mapper, jsonSerializer,
+ polarisContractProperties.getGroup(), polarisSDKContextManager.getProviderAPI(), polarisDiscoveryProperties);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public PolarisSwaggerApplicationListener polarisSwaggerApplicationListener() {
+ return new PolarisSwaggerApplicationListener();
+ }
+
+ /**
+ * Create when web application type is SERVLET.
+ */
+ @Configuration(proxyBeanMethods = false)
+ @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
+ protected static class SwaggerServletConfig {
+
+ }
+
+ /**
+ * Create when web application type is REACTIVE.
+ */
+ @Configuration(proxyBeanMethods = false)
+ @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
+ protected static class SwaggerReactiveConfig {
+
+
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java
new file mode 100644
index 00000000..7ce8a7ec
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/java/com/tencent/cloud/polaris/contract/utils/PackageUtil.java
@@ -0,0 +1,214 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * 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 com.tencent.cloud.polaris.contract.utils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.tencent.cloud.polaris.contract.SwaggerContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import springfox.documentation.RequestHandler;
+import springfox.documentation.builders.PathSelectors;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.util.StringUtils;
+
+import static com.google.common.base.Optional.fromNullable;
+
+/**
+ * Util for package processing.
+ *
+ * @author Haotian Zhang
+ */
+public final class PackageUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PackageUtil.class);
+
+ private static final String SPLITTER = ",";
+
+
+ private PackageUtil() {
+ }
+
+ public static Predicate basePackage(String basePackage) {
+ return input -> declaringClass(input).transform(handlerPackage(basePackage, SPLITTER)).or(false);
+ }
+
+ public static Optional> declaringClass(RequestHandler input) {
+ if (input == null) {
+ return Optional.absent();
+ }
+ return fromNullable(input.declaringClass());
+ }
+
+ public static Function, Boolean> handlerPackage(String basePackage, String splitter) {
+ return input -> {
+ try {
+ if (StringUtils.isEmpty(basePackage)) {
+ return false;
+ }
+ String[] packages = basePackage.trim().split(splitter);
+ // Loop to determine matching
+ for (String strPackage : packages) {
+ if (input == null) {
+ continue;
+ }
+ Package pkg = input.getPackage();
+ if (pkg == null) {
+ continue;
+ }
+ String name = pkg.getName();
+ if (StringUtils.isEmpty(name)) {
+ continue;
+ }
+ boolean isMatch = name.startsWith(strPackage);
+ if (isMatch) {
+ return true;
+ }
+ }
+ }
+ catch (Exception e) {
+ LOG.error("handler package error", e);
+ }
+ return false;
+ };
+ }
+
+ public static List> getExcludePathPredicates(String excludePath) {
+ List> excludePathList = new ArrayList<>();
+ if (StringUtils.isEmpty(excludePath)) {
+ return excludePathList;
+ }
+ String[] exs = excludePath.split(SPLITTER);
+ for (String ex : exs) {
+ if (!StringUtils.isEmpty(ex)) {
+ excludePathList.add(PathSelectors.ant(ex));
+ }
+ }
+ return excludePathList;
+ }
+
+ public static List> getBasePathPredicates(String basePath) {
+ List> basePathList = new ArrayList<>();
+ if (!StringUtils.isEmpty(basePath)) {
+ String[] bps = basePath.split(SPLITTER);
+ for (String bp : bps) {
+ if (!StringUtils.isEmpty(bp)) {
+ basePathList.add(PathSelectors.ant(bp));
+ }
+ }
+ }
+ if (basePathList.isEmpty()) {
+ basePathList.add(PathSelectors.ant("/**"));
+ }
+ return basePathList;
+ }
+
+ public static String scanPackage(String configBasePackage) {
+ String validScanPackage;
+ // Externally configured scan package
+ Set configPackageSet = new HashSet<>();
+ if (!StringUtils.isEmpty(configBasePackage)) {
+ configPackageSet.addAll(Arrays.asList(configBasePackage.split(SPLITTER)));
+ }
+ Object mainClz = SwaggerContext.getAttribute(String.format("$%s", "MainClass"));
+ // Verification of the valid path of MainClass
+ if (mainClz != null) {
+ Set autoDetectPackageSet = parseDefaultScanPackage((Class>) mainClz);
+ if (LOG.isInfoEnabled() && !autoDetectPackageSet.isEmpty()) {
+ LOG.info("Auto detect default swagger scan packages: {}",
+ String.join(SPLITTER, autoDetectPackageSet).trim());
+ }
+ Set validScanPackageSet = merge(configPackageSet, autoDetectPackageSet);
+ validScanPackage = String.join(SPLITTER, validScanPackageSet).trim();
+ if (LOG.isInfoEnabled() && !StringUtils.isEmpty(validScanPackage)) {
+ LOG.info("Swagger scan valid packages: {}", validScanPackage);
+ }
+ }
+ else {
+ // If there is no MainClass, the configured path is used for scanning
+ validScanPackage = String.join(SPLITTER, configPackageSet);
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Cannot detect main class, swagger scanning packages is set to: {}",
+ validScanPackage);
+ }
+ }
+ return validScanPackage;
+ }
+
+ public static Set merge(Set configPackageSet, Set autoDetectPackageSet) {
+ if (configPackageSet == null || configPackageSet.size() == 0) {
+ return autoDetectPackageSet;
+ }
+ return configPackageSet;
+ }
+
+
+ public static Set parseDefaultScanPackage(Class> mainClass) {
+ Set packageSets = new HashSet<>();
+ String defaultPackage = mainClass.getPackage().getName();
+ try {
+ boolean springBootEnv = true;
+ try {
+ Class.forName("org.springframework.boot.autoconfigure.SpringBootApplication");
+ }
+ catch (Throwable t) {
+ LOG.info("Can not load annotation @SpringBootApplication, " +
+ "current environment is not in spring boot framework. ");
+ springBootEnv = false;
+ }
+ if (!springBootEnv) {
+ packageSets.add(defaultPackage);
+ return packageSets;
+ }
+ SpringBootApplication bootAnnotation = mainClass.getAnnotation(SpringBootApplication.class);
+ Class>[] baseClassPackages;
+ String[] basePackages;
+ if (bootAnnotation == null) {
+ packageSets.add(defaultPackage);
+ }
+ else {
+ // baseClassPackages annotation
+ baseClassPackages = bootAnnotation.scanBasePackageClasses();
+ for (Class> clz : baseClassPackages) {
+ packageSets.add(clz.getPackage().getName());
+ }
+ // basePackage annotation
+ basePackages = bootAnnotation.scanBasePackages();
+ packageSets.addAll(Arrays.asList(basePackages));
+ // When basePackage and baseClassPackages are both empty, the package path where the MainClass class is located is used by default.
+ if (packageSets.isEmpty()) {
+ packageSets.add(defaultPackage);
+ }
+ }
+ }
+ catch (Throwable t) {
+ LOG.warn("Swagger scan package is empty and auto detect main class occur exception: {}",
+ t.getMessage());
+
+ }
+ return packageSets;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-contract/src/main/resources/META-INF/spring.factories b/spring-cloud-starter-tencent-polaris-contract/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..86a23f5b
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-contract/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,7 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.tencent.cloud.polaris.contract.config.PolarisSwaggerAutoConfiguration,\
+ com.tencent.cloud.polaris.contract.config.PolarisContractProperties
+org.springframework.cloud.bootstrap.BootstrapConfiguration=\
+ com.tencent.cloud.polaris.contract.config.PolarisContractPropertiesAutoConfiguration
+org.springframework.context.ApplicationListener=\
+ com.tencent.cloud.polaris.contract.PolarisSwaggerApplicationListener
diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java
index 3f83bfd4..0477ebfb 100644
--- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java
+++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/PolarisDiscoveryProperties.java
@@ -64,7 +64,7 @@ public class PolarisDiscoveryProperties {
/**
* Version number.
*/
- private String version;
+ private String version = "1.0.0";
/**
* Protocol name such as http, https.
diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
index 1f9cdcef..633f069b 100644
--- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
+++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/constant/OrderConstant.java
@@ -213,5 +213,10 @@ public class OrderConstant {
* Order of stat reporter configuration modifier.
*/
public static Integer STAT_REPORTER_ORDER = 1;
+
+ /**
+ * Order of service contract configuration modifier.
+ */
+ public static Integer SERVICE_CONTRACT_ORDER = Integer.MAX_VALUE - 9;
}
}
diff --git a/spring-cloud-tencent-coverage/pom.xml b/spring-cloud-tencent-coverage/pom.xml
index ee44f02f..8a06ec03 100644
--- a/spring-cloud-tencent-coverage/pom.xml
+++ b/spring-cloud-tencent-coverage/pom.xml
@@ -69,6 +69,11 @@
spring-cloud-starter-tencent-polaris-config
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-contract
+
+
com.tencent.cloud
spring-cloud-tencent-featureenv-plugin
diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml
index 8ffd15a8..c804beff 100644
--- a/spring-cloud-tencent-dependencies/pom.xml
+++ b/spring-cloud-tencent-dependencies/pom.xml
@@ -76,6 +76,8 @@
1.15.0-SNAPSHOT
32.0.1-jre
1.2.11
+ 3.0.0
+ 1.5.24
4.5.1
1.12.10
2.12.7
@@ -161,6 +163,12 @@
${revision}
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-contract
+ ${revision}
+
+
com.tencent.cloud
spring-cloud-starter-tencent-all
@@ -237,6 +245,24 @@
${jackson.version}
+
+ io.springfox
+ springfox-boot-starter
+ ${springfox.swagger2.version}
+
+
+
+ io.swagger
+ swagger-models
+ ${io.swagger.version}
+
+
+
+ io.swagger
+ swagger-annotations
+ ${io.swagger.version}
+
+
com.google.protobuf
protobuf-java
diff --git a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/pom.xml b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/pom.xml
index aadcea9e..69e5c1e6 100644
--- a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/pom.xml
+++ b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/pom.xml
@@ -28,6 +28,11 @@
spring-cloud-starter-tencent-polaris-discovery
+
+ com.tencent.cloud
+ spring-cloud-starter-tencent-polaris-contract
+
+
diff --git a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/java/com/tencent/cloud/polaris/discovery/service/caller/DiscoveryCallerController.java b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/java/com/tencent/cloud/polaris/discovery/service/caller/DiscoveryCallerController.java
index b07c2267..d709d1b4 100644
--- a/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/java/com/tencent/cloud/polaris/discovery/service/caller/DiscoveryCallerController.java
+++ b/spring-cloud-tencent-examples/polaris-discovery-example/discovery-caller-service/src/main/java/com/tencent/cloud/polaris/discovery/service/caller/DiscoveryCallerController.java
@@ -45,7 +45,7 @@ public class DiscoveryCallerController {
* @param value2 value 2
* @return sum
*/
- @GetMapping("/feign")
+ @RequestMapping("/feign")
public int feign(@RequestParam int value1, @RequestParam int value2) {
return discoveryCalleeService.sum(value1, value2);
}
diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java
index 95807dba..6677dac0 100644
--- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java
+++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/PluginOrderConstant.java
@@ -44,27 +44,5 @@ public class PluginOrderConstant {
* {@link com.tencent.cloud.polaris.circuitbreaker.reporter.ExceptionCircuitBreakerReporter}.
*/
public static final int CIRCUIT_BREAKER_REPORTER_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 2;
-
- /**
- * order for
- * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPreHook}
- * and
- * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientPostHook}
- * and
- * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.client.AssemblyClientExceptionHook}.
- */
- public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 3;
- }
-
- public static class ServerPluginOrder {
- /**
- * order for
- * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPreHook}
- * and
- * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerPostHook}
- * and
- * {@link com.tencent.cloud.rpc.enhancement.plugin.assembly.server.AssemblyServerExceptionHook}.
- */
- public static final int ASSEMBLY_PLUGIN_ORDER = Ordered.HIGHEST_PRECEDENCE + 1;
}
}