hoxton 2.0.0.0 (#1458)
* fix:fix restTemplateCustomizer bean conflict causing service to fail to start properly. * fix:fix NullPointerException when properties contain kv with null value. * fix: memory not released while using wildcard api call with circuitbreaker (#1361) * fix: memory not released while using wildcard api call with circuitbreaker enabled * fix: change version 1.13.3-Hoxton.SR12-SNAPSHOT * fix: update polaris verion to 1.15.9 release * Update CHANGELOG.md * release 1.13.3-Hoxton.SR12 (#1362) * fix: memory not released while using wildcard api call with circuitbreaker enabled * fix: change version 1.13.3-Hoxton.SR12-SNAPSHOT * fix: update polaris verion to 1.15.9 release * Update CHANGELOG.md * release: 1.13.3-Hoxton.SR12 * fix: fix PolarisCircuitBreakerConfiguration not clear when gateway invoke by wildcard apis (#1392) * fix: CHANGE VERSION TO 1.13.4-Hoxton.SR12-SNAPSHOT (#1407) * fix: fix PolarisCircuitBreakerConfiguration not clear when gateway invoked by wildcard apis * Update CHANGELOG.md * fix: restore PolarisCircuitBreakerUtils and use ThreadPoolUtils.waitAndStopThreadPools instead * fix: 修复命名不一致问题 * fix: CHANGE VERSION TO 1.13.4-Hoxton.SR12-SNAPSHOT * Update polaris version to 1.15.10-SNAPSHOT * fix:fix rate limit window update bug. * fix: fix npe when feign.hystrix.enabled=false (#1436) * feat: support 2.0.0 feature * fix * feat: support lossless config from console & support warmup (#1435) feat:add admin http handler. (#1448) feat:support concurrency rate limit. (#1454) * fix * add changelog * fix * fix changelog * fix * fix checkstyle * fix ut --------- Co-authored-by: 码匠君 <pointer_v@qq.com> Co-authored-by: Haotian Zhang <928016560@qq.com> Co-authored-by: andrew shan <45474304+andrewshan@users.noreply.github.com> Co-authored-by: shedfreewu <shedfreewu@tencent.com>pull/1466/head
parent
eab382b371
commit
84a98de136
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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.metadata.provider;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.util.UrlUtils;
|
||||||
|
import com.tencent.cloud.common.util.expresstion.ExpressionLabelUtils;
|
||||||
|
import com.tencent.polaris.metadata.core.MessageMetadataContainer;
|
||||||
|
import com.tencent.polaris.metadata.core.MetadataProvider;
|
||||||
|
import com.tencent.polaris.metadata.core.constant.MetadataConstants;
|
||||||
|
import com.tencent.polaris.metadata.core.manager.CalleeMetadataContainerGroup;
|
||||||
|
import feign.RequestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MetadataProvider used for Feign RequestTemplate.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public class FeignRequestTemplateMetadataProvider implements MetadataProvider {
|
||||||
|
|
||||||
|
private final RequestTemplate requestTemplate;
|
||||||
|
|
||||||
|
public FeignRequestTemplateMetadataProvider(RequestTemplate requestTemplate) {
|
||||||
|
this.requestTemplate = requestTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRawMetadataStringValue(String key) {
|
||||||
|
switch (key) {
|
||||||
|
case MessageMetadataContainer.LABEL_KEY_METHOD:
|
||||||
|
return requestTemplate.method();
|
||||||
|
case MessageMetadataContainer.LABEL_KEY_PATH:
|
||||||
|
URI uri = URI.create(requestTemplate.request().url());
|
||||||
|
return UrlUtils.decode(uri.getPath());
|
||||||
|
case MessageMetadataContainer.LABEL_KEY_CALLER_IP:
|
||||||
|
return CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer()
|
||||||
|
.getRawMetadataStringValue(MetadataConstants.LOCAL_IP);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRawMetadataMapValue(String key, String mapKey) {
|
||||||
|
Map<String, Collection<String>> headers = requestTemplate.headers();
|
||||||
|
switch (key) {
|
||||||
|
case MessageMetadataContainer.LABEL_MAP_KEY_HEADER:
|
||||||
|
return UrlUtils.decode(ExpressionLabelUtils.getFirstValue(headers, mapKey));
|
||||||
|
case MessageMetadataContainer.LABEL_MAP_KEY_COOKIE:
|
||||||
|
return UrlUtils.decode(ExpressionLabelUtils.getCookieFirstValue(headers, mapKey));
|
||||||
|
case MessageMetadataContainer.LABEL_MAP_KEY_QUERY:
|
||||||
|
return UrlUtils.decode(ExpressionLabelUtils.getFirstValue(requestTemplate.queries(), mapKey));
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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.metadata.provider;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.util.UrlUtils;
|
||||||
|
import com.tencent.cloud.common.util.expresstion.SpringWebExpressionLabelUtils;
|
||||||
|
import com.tencent.polaris.metadata.core.MessageMetadataContainer;
|
||||||
|
import com.tencent.polaris.metadata.core.MetadataProvider;
|
||||||
|
import com.tencent.polaris.metadata.core.constant.MetadataConstants;
|
||||||
|
import com.tencent.polaris.metadata.core.manager.CalleeMetadataContainerGroup;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MetadataProvider used for RestTemplate HttpRequest.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public class RestTemplateMetadataProvider implements MetadataProvider {
|
||||||
|
|
||||||
|
private final HttpRequest request;
|
||||||
|
|
||||||
|
public RestTemplateMetadataProvider(HttpRequest request) {
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRawMetadataStringValue(String key) {
|
||||||
|
switch (key) {
|
||||||
|
case MessageMetadataContainer.LABEL_KEY_METHOD:
|
||||||
|
return request.getMethod().toString();
|
||||||
|
case MessageMetadataContainer.LABEL_KEY_PATH:
|
||||||
|
return UrlUtils.decode(request.getURI().getPath());
|
||||||
|
case MessageMetadataContainer.LABEL_KEY_CALLER_IP:
|
||||||
|
return CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer()
|
||||||
|
.getRawMetadataStringValue(MetadataConstants.LOCAL_IP);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRawMetadataMapValue(String key, String mapKey) {
|
||||||
|
switch (key) {
|
||||||
|
case MessageMetadataContainer.LABEL_MAP_KEY_HEADER:
|
||||||
|
return UrlUtils.decode(SpringWebExpressionLabelUtils.getHeaderValue(request, mapKey));
|
||||||
|
case MessageMetadataContainer.LABEL_MAP_KEY_COOKIE:
|
||||||
|
return UrlUtils.decode(SpringWebExpressionLabelUtils.getCookieValue(request, mapKey));
|
||||||
|
case MessageMetadataContainer.LABEL_MAP_KEY_QUERY:
|
||||||
|
return UrlUtils.decode(SpringWebExpressionLabelUtils.getQueryValue(request, mapKey));
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.metadata.core;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.netflix.zuul.context.RequestContext;
|
|
||||||
import com.netflix.zuul.exception.ZuulException;
|
|
||||||
import com.tencent.cloud.common.metadata.MetadataContext;
|
|
||||||
import com.tencent.cloud.common.metadata.MetadataContextHolder;
|
|
||||||
import com.tencent.cloud.common.util.JacksonUtils;
|
|
||||||
import com.tencent.cloud.rpc.enhancement.zuul.EnhancedPreZuulFilter;
|
|
||||||
import org.assertj.core.api.Assertions;
|
|
||||||
import org.assertj.core.util.Maps;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.mock.web.MockMultipartHttpServletRequest;
|
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|
||||||
|
|
||||||
import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
|
|
||||||
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_DISPOSABLE_METADATA;
|
|
||||||
import static com.tencent.cloud.common.constant.MetadataConstant.HeaderName.CUSTOM_METADATA;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
|
||||||
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVICE_ID_KEY;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for {@link EncodeTransferMetadataZuulEnhancedPlugin}.
|
|
||||||
*
|
|
||||||
* @author quan, Shedfree Wu
|
|
||||||
*/
|
|
||||||
@ExtendWith(SpringExtension.class)
|
|
||||||
@SpringBootTest(webEnvironment = RANDOM_PORT,
|
|
||||||
classes = EncodeTransferMetadataZuulFilterTest.TestApplication.class,
|
|
||||||
properties = {"spring.config.location = classpath:application-test.yml",
|
|
||||||
"spring.main.web-application-type = reactive"})
|
|
||||||
public class EncodeTransferMetadataZuulFilterTest {
|
|
||||||
|
|
||||||
private final MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
|
||||||
@Autowired
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
RequestContext ctx = RequestContext.getCurrentContext();
|
|
||||||
ctx.clear();
|
|
||||||
ctx.setRequest(this.request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRun() throws ZuulException, UnsupportedEncodingException {
|
|
||||||
EnhancedPreZuulFilter filter = applicationContext.getBean(EnhancedPreZuulFilter.class);
|
|
||||||
RequestContext context = RequestContext.getCurrentContext();
|
|
||||||
context.set(SERVICE_ID_KEY, "test-service");
|
|
||||||
|
|
||||||
MetadataContext metadataContext = MetadataContextHolder.get();
|
|
||||||
metadataContext.setTransitiveMetadata(Maps.newHashMap("t-key", "t-value"));
|
|
||||||
metadataContext.setDisposableMetadata(Maps.newHashMap("d-key", "d-value"));
|
|
||||||
filter.run();
|
|
||||||
|
|
||||||
final RequestContext ctx = RequestContext.getCurrentContext();
|
|
||||||
Map<String, String> zuulRequestHeaders = ctx.getZuulRequestHeaders();
|
|
||||||
// convert header to lower case in com.netflix.zuul.context.RequestContext.addZuulRequestHeader
|
|
||||||
assertThat(zuulRequestHeaders.get(CUSTOM_METADATA.toLowerCase())).isNotNull();
|
|
||||||
assertThat(zuulRequestHeaders.get(CUSTOM_DISPOSABLE_METADATA.toLowerCase())).isNotNull();
|
|
||||||
|
|
||||||
String metadata = zuulRequestHeaders.get(CUSTOM_METADATA.toLowerCase());
|
|
||||||
|
|
||||||
Assertions.assertThat(metadata).isNotNull();
|
|
||||||
|
|
||||||
String decode = URLDecoder.decode(metadata, UTF_8);
|
|
||||||
Map<String, String> transitiveMap = JacksonUtils.deserialize2Map(decode);
|
|
||||||
// expect {"b":"2","t-key":"t-value"}
|
|
||||||
Assertions.assertThat(transitiveMap.size()).isEqualTo(2);
|
|
||||||
Assertions.assertThat(transitiveMap.get("b")).isEqualTo("2");
|
|
||||||
}
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
protected static class TestApplication {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.circuitbreaker.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of Polaris CircuitBreaker .
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties("spring.cloud.polaris.circuitbreaker")
|
||||||
|
public class PolarisCircuitBreakerProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether enable polaris circuit-breaker function.
|
||||||
|
*/
|
||||||
|
@Value("${spring.cloud.polaris.circuitbreaker.enabled:#{true}}")
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interval to clean up PolarisCircuitBreakerConfiguration, unit millisecond.
|
||||||
|
*/
|
||||||
|
@Value("${spring.cloud.polaris.circuitbreaker.configuration-cleanup-interval:#{300000}}")
|
||||||
|
private long configurationCleanupInterval = 300000;
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getConfigurationCleanupInterval() {
|
||||||
|
return configurationCleanupInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfigurationCleanupInterval(long configurationCleanupInterval) {
|
||||||
|
this.configurationCleanupInterval = configurationCleanupInterval;
|
||||||
|
}
|
||||||
|
}
|
@ -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.config.tsf.encrypt;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ConfigEncryptAESProvider extends ConfigEncryptProvider {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ConfigEncryptAESProvider.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encrypt(String content, String password) {
|
||||||
|
try {
|
||||||
|
return EncryptAlgorithm.AES256.encrypt(content, password);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
log.error("Error on encrypting.", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String decrypt(String encryptedContent, String password) {
|
||||||
|
try {
|
||||||
|
return EncryptAlgorithm.AES256.decrypt(encryptedContent, password);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
log.error("Error on decrypting.", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.config.tsf.encrypt;
|
||||||
|
|
||||||
|
public final class ConfigEncryptProviderFactory {
|
||||||
|
|
||||||
|
private static ConfigEncryptProvider configEncryptProvider = null;
|
||||||
|
|
||||||
|
private ConfigEncryptProviderFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigEncryptProvider getInstance() {
|
||||||
|
if (null == configEncryptProvider) {
|
||||||
|
try {
|
||||||
|
Class<?> providerClass = Class.forName(EncryptConfig.getProviderClass());
|
||||||
|
configEncryptProvider = (ConfigEncryptProvider) providerClass.newInstance();
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return configEncryptProvider;
|
||||||
|
}
|
||||||
|
}
|
@ -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.config.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils for PolarisPropertySource.
|
||||||
|
*
|
||||||
|
* @author Haotian Zhang
|
||||||
|
*/
|
||||||
|
public final class PolarisPropertySourceUtils {
|
||||||
|
|
||||||
|
private PolarisPropertySourceUtils() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateName(String namespace, String group, String fileName) {
|
||||||
|
return namespace + "-" + group + "-" + fileName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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.tsf.consul.config.watch;
|
||||||
|
|
||||||
|
public interface ConfigChangeCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置变更回调函数.
|
||||||
|
* @param lastConfigProperty 旧的配置属性
|
||||||
|
* @param newConfigProperty 新的配置属性
|
||||||
|
*/
|
||||||
|
void callback(ConfigProperty lastConfigProperty, ConfigProperty newConfigProperty);
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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.tsf.consul.config.watch;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Component
|
||||||
|
public @interface ConfigChangeListener {
|
||||||
|
String prefix() default "";
|
||||||
|
|
||||||
|
String[] value() default {};
|
||||||
|
|
||||||
|
boolean async() default false;
|
||||||
|
|
||||||
|
}
|
@ -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.tsf.consul.config.watch;
|
||||||
|
|
||||||
|
public class ConfigProperty {
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
public ConfigProperty(String key, Object value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Object value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -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.tsf.consul.config.watch;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.tencent.cloud.polaris.config.listener.ConfigChangeEvent;
|
||||||
|
import com.tencent.cloud.polaris.config.listener.PolarisConfigListenerContext;
|
||||||
|
import com.tencent.cloud.polaris.config.listener.SyncConfigChangeListener;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.PriorityOrdered;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
public class TsfConsulConfigRefreshEventListener implements BeanPostProcessor, PriorityOrdered {
|
||||||
|
private static final String DOT = ".";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Ordered.LOWEST_PRECEDENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessBeforeInitialization(@NonNull Object obj, @NonNull String beanName) throws BeansException {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessAfterInitialization(@NonNull Object obj, @NonNull String beanName) throws BeansException {
|
||||||
|
Class<?> clz = obj.getClass();
|
||||||
|
if (!clz.isAnnotationPresent(ConfigChangeListener.class) || !ConfigChangeCallback.class.isAssignableFrom(clz)) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigChangeListener targetAnno = clz.getAnnotation(ConfigChangeListener.class);
|
||||||
|
String watchedPrefix = targetAnno.prefix();
|
||||||
|
String[] watchedConfirmedValue = targetAnno.value();
|
||||||
|
boolean isAsync = targetAnno.async();
|
||||||
|
if (watchedConfirmedValue.length == 0 && StringUtils.isEmpty(watchedPrefix)) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigChangeCallback bean = (ConfigChangeCallback) obj;
|
||||||
|
com.tencent.cloud.polaris.config.listener.ConfigChangeListener listener = new SyncConfigChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onChange(ConfigChangeEvent changeEvent) {
|
||||||
|
List<TsfCallbackParam> paramList = parseConfigChangeEventToTsfCallbackParam(changeEvent);
|
||||||
|
for (TsfCallbackParam param : paramList) {
|
||||||
|
if (isAsync()) {
|
||||||
|
PolarisConfigListenerContext.executor()
|
||||||
|
.execute(() -> bean.callback(param.oldValue, param.newValue));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bean.callback(param.oldValue, param.newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAsync() {
|
||||||
|
return isAsync;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Set<String> interestedKeys = new HashSet<>();
|
||||||
|
Set<String> interestedKeyPrefixes = new HashSet<>();
|
||||||
|
if (watchedConfirmedValue.length > 0) {
|
||||||
|
for (String value : watchedConfirmedValue) {
|
||||||
|
interestedKeys.add(StringUtils.isEmpty(watchedPrefix) ? value : watchedPrefix + DOT + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
interestedKeyPrefixes.add(watchedPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
PolarisConfigListenerContext.addChangeListener(listener, interestedKeys, interestedKeyPrefixes);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TsfCallbackParam> parseConfigChangeEventToTsfCallbackParam(ConfigChangeEvent event) {
|
||||||
|
List<TsfCallbackParam> result = new ArrayList<>();
|
||||||
|
Set<String> changedKeys = event.changedKeys();
|
||||||
|
for (String changedKey : changedKeys) {
|
||||||
|
ConfigProperty oldValue = new ConfigProperty(changedKey, event.getChange(changedKey).getOldValue());
|
||||||
|
ConfigProperty newValue = new ConfigProperty(changedKey, event.getChange(changedKey).getNewValue());
|
||||||
|
TsfCallbackParam param = new TsfCallbackParam(oldValue, newValue);
|
||||||
|
result.add(param);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TsfCallbackParam {
|
||||||
|
ConfigProperty oldValue;
|
||||||
|
ConfigProperty newValue;
|
||||||
|
|
||||||
|
TsfCallbackParam(ConfigProperty oldValue, ConfigProperty newValue) {
|
||||||
|
this.oldValue = oldValue;
|
||||||
|
this.newValue = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
|
||||||
com.tencent.cloud.polaris.config.PolarisConfigBootstrapAutoConfiguration
|
|
||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
com.tencent.cloud.polaris.config.PolarisConfigAutoConfiguration,\
|
com.tencent.cloud.polaris.config.PolarisConfigAutoConfiguration,\
|
||||||
com.tencent.cloud.polaris.config.endpoint.PolarisConfigEndpointAutoConfiguration
|
com.tencent.cloud.polaris.config.endpoint.PolarisConfigEndpointAutoConfiguration,\
|
||||||
|
com.tencent.cloud.polaris.config.tsf.PolarisAdaptorTsfConfigAutoConfiguration,\
|
||||||
|
com.tencent.cloud.polaris.config.PolarisConfigBootstrapAutoConfiguration
|
||||||
|
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||||
|
com.tencent.cloud.polaris.config.PolarisConfigBootstrapAutoConfiguration
|
||||||
|
|
||||||
|
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* 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.tsf;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.tencent.cloud.common.util.GzipUtil;
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springdoc.api.AbstractOpenApiResource;
|
||||||
|
import org.springdoc.api.AbstractOpenApiResourceUtil;
|
||||||
|
import org.springdoc.core.providers.ObjectMapperProvider;
|
||||||
|
import org.springdoc.webflux.api.OpenApiWebFluxUtil;
|
||||||
|
import org.springdoc.webmvc.api.OpenApiWebMvcUtil;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.SmartLifecycle;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
public class TsfApiMetadataGrapher implements SmartLifecycle {
|
||||||
|
|
||||||
|
private final AtomicBoolean isRunning = new AtomicBoolean(false);
|
||||||
|
private final org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource;
|
||||||
|
private final org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource;
|
||||||
|
private final ObjectMapperProvider springdocObjectMapperProvider;
|
||||||
|
private Logger logger = LoggerFactory.getLogger(TsfApiMetadataGrapher.class);
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
private String groupName;
|
||||||
|
|
||||||
|
public TsfApiMetadataGrapher(org.springdoc.webmvc.api.MultipleOpenApiResource multipleOpenApiWebMvcResource,
|
||||||
|
org.springdoc.webflux.api.MultipleOpenApiResource multipleOpenApiWebFluxResource,
|
||||||
|
String groupName, ApplicationContext applicationContext, ObjectMapperProvider springdocObjectMapperProvider) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
this.multipleOpenApiWebMvcResource = multipleOpenApiWebMvcResource;
|
||||||
|
this.multipleOpenApiWebFluxResource = multipleOpenApiWebFluxResource;
|
||||||
|
this.groupName = groupName;
|
||||||
|
this.springdocObjectMapperProvider = springdocObjectMapperProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAutoStartup() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(Runnable runnable) {
|
||||||
|
runnable.run();
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (!isRunning.compareAndSet(false, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
AbstractOpenApiResource openApiResource = null;
|
||||||
|
if (multipleOpenApiWebMvcResource != null) {
|
||||||
|
openApiResource = OpenApiWebMvcUtil.getOpenApiResourceOrThrow(multipleOpenApiWebMvcResource, groupName);
|
||||||
|
}
|
||||||
|
else if (multipleOpenApiWebFluxResource != null) {
|
||||||
|
openApiResource = OpenApiWebFluxUtil.getOpenApiResourceOrThrow(multipleOpenApiWebFluxResource, groupName);
|
||||||
|
}
|
||||||
|
OpenAPI openAPI = null;
|
||||||
|
if (openApiResource != null) {
|
||||||
|
openAPI = AbstractOpenApiResourceUtil.getOpenApi(openApiResource);
|
||||||
|
}
|
||||||
|
String jsonValue;
|
||||||
|
if (springdocObjectMapperProvider != null && springdocObjectMapperProvider.jsonMapper() != null) {
|
||||||
|
jsonValue = springdocObjectMapperProvider.jsonMapper().writeValueAsString(openAPI);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||||
|
jsonValue = mapper.writeValueAsString(openAPI);
|
||||||
|
}
|
||||||
|
if (openAPI != null && !StringUtils.isEmpty(jsonValue)) {
|
||||||
|
String serviceApiMeta = GzipUtil.compressBase64Encode(jsonValue, "utf-8");
|
||||||
|
Environment environment = applicationContext.getEnvironment();
|
||||||
|
String tsfToken = environment.getProperty("tsf_token");
|
||||||
|
String tsfGroupId = environment.getProperty("tsf_group_id");
|
||||||
|
if (StringUtils.isEmpty(tsfGroupId) || StringUtils.isEmpty(tsfToken)) {
|
||||||
|
logger.info("[tsf-swagger] auto smart check application start with local consul, api registry not work");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info("[tsf-swagger] api_meta len: {}", serviceApiMeta.length());
|
||||||
|
String applicationName = environment.getProperty("spring.application.name");
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[tsf-swagger] service: {} openApi json data: {}", applicationName, jsonValue);
|
||||||
|
logger.debug("[tsf-swagger] service: {} api_meta info: {}", applicationName, serviceApiMeta);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.setProperty(String.format("$%s", "api_metas"), serviceApiMeta);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.warn("[tsf-swagger] swagger or json is null, openApiResource keys:{}, group:{}", openApiResource, groupName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
logger.error("[tsf swagger] init TsfApiMetadataGrapher failed. occur exception: ", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
isRunning.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRunning() {
|
||||||
|
return isRunning.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPhase() {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
@ -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.tsf;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.tsf.ConditionalOnTsfConsulEnabled;
|
||||||
|
import com.tencent.cloud.polaris.contract.config.PolarisContractProperties;
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import org.springdoc.core.providers.ObjectMapperProvider;
|
||||||
|
import org.springdoc.webflux.api.MultipleOpenApiWebFluxResource;
|
||||||
|
import org.springdoc.webmvc.api.MultipleOpenApiWebMvcResource;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnTsfConsulEnabled
|
||||||
|
@ConditionalOnProperty(value = "tsf.swagger.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
public class TsfSwaggerAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(OpenAPI.class)
|
||||||
|
public TsfApiMetadataGrapher tsfApiMetadataGrapher(@Nullable MultipleOpenApiWebMvcResource multipleOpenApiWebMvcResource,
|
||||||
|
@Nullable MultipleOpenApiWebFluxResource multipleOpenApiWebFluxResource, ApplicationContext context,
|
||||||
|
PolarisContractProperties polarisContractProperties, ObjectMapperProvider springdocObjectMapperProvider) {
|
||||||
|
return new TsfApiMetadataGrapher(multipleOpenApiWebMvcResource, multipleOpenApiWebFluxResource,
|
||||||
|
polarisContractProperties.getGroup(), context, springdocObjectMapperProvider);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue