diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml
index bb075ac5..fc4b5d4d 100644
--- a/spring-cloud-alibaba-dependencies/pom.xml
+++ b/spring-cloud-alibaba-dependencies/pom.xml
@@ -17,7 +17,7 @@
Spring Cloud Alibaba Dependencies
- 1.6.0
+ 1.6.1
3.1.0
0.4.2
1.0.0
diff --git a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml
index a614f5b7..a3304e39 100644
--- a/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml
+++ b/spring-cloud-alibaba-examples/sentinel-example/sentinel-spring-cloud-gateway-example/src/main/resources/application.yaml
@@ -33,5 +33,11 @@ spring:
dashboard: localhost:8080
filter:
enabled: true
+ scg.fallback:
+ mode: redirect
+ redirect: http://www.taobao.com
+# response-status: 444
+# response-body: 1234
+# content-type: text/plain
management.endpoints.web.exposure.include: "*"
\ No newline at end of file
diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpoint.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpoint.java
index 1160db1b..b0134e77 100644
--- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpoint.java
+++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/endpoint/NacosConfigEndpoint.java
@@ -16,13 +16,6 @@
package org.springframework.cloud.alibaba.nacos.endpoint;
-import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
-import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
-import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
-import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
-import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
-import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
-
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -30,6 +23,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+import org.springframework.cloud.alibaba.nacos.NacosConfigProperties;
+import org.springframework.cloud.alibaba.nacos.NacosPropertySourceRepository;
+import org.springframework.cloud.alibaba.nacos.client.NacosPropertySource;
+import org.springframework.cloud.alibaba.nacos.refresh.NacosRefreshHistory;
+
/**
* Endpoint for Nacos, contains config data and refresh history
* @author xiaojing
@@ -41,7 +41,12 @@ public class NacosConfigEndpoint {
private final NacosRefreshHistory refreshHistory;
- private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private ThreadLocal dateFormat = new ThreadLocal() {
+ @Override
+ protected DateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ };
public NacosConfigEndpoint(NacosConfigProperties properties,
NacosRefreshHistory refreshHistory) {
@@ -60,7 +65,7 @@ public class NacosConfigEndpoint {
for (NacosPropertySource ps : all) {
Map source = new HashMap<>(16);
source.put("dataId", ps.getDataId());
- source.put("lastSynced", dateFormat.format(ps.getTimestamp()));
+ source.put("lastSynced", dateFormat.get().format(ps.getTimestamp()));
sources.add(source);
}
result.put("Sources", sources);
diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosRefreshHistory.java b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosRefreshHistory.java
index ec5a83ca..149453b6 100644
--- a/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosRefreshHistory.java
+++ b/spring-cloud-alibaba-nacos-config/src/main/java/org/springframework/cloud/alibaba/nacos/refresh/NacosRefreshHistory.java
@@ -27,10 +27,15 @@ public class NacosRefreshHistory {
private LinkedList records = new LinkedList<>();
- private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private ThreadLocal dateFormat = new ThreadLocal() {
+ @Override
+ protected DateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ };
public void add(String dataId, String md5) {
- records.addFirst(new Record(dateFormat.format(new Date()), dataId, md5));
+ records.addFirst(new Record(dateFormat.get().format(new Date()), dataId, md5));
if (records.size() > MAX_SIZE) {
records.removeLast();
}
diff --git a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java
index c092f62a..9e348a1a 100644
--- a/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java
+++ b/spring-cloud-alibaba-nacos-discovery/src/main/java/org/springframework/cloud/alibaba/nacos/NacosDiscoveryAutoConfiguration.java
@@ -17,12 +17,9 @@
package org.springframework.cloud.alibaba.nacos;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.alibaba.nacos.discovery.NacosDiscoveryClientAutoConfiguration;
import org.springframework.cloud.alibaba.nacos.registry.NacosAutoServiceRegistration;
import org.springframework.cloud.alibaba.nacos.registry.NacosRegistration;
import org.springframework.cloud.alibaba.nacos.registry.NacosServiceRegistry;
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/ConfigConstants.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/ConfigConstants.java
new file mode 100644
index 00000000..a83f6cee
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/ConfigConstants.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.alibaba.sentinel.gateway;
+
+/**
+ * @author Jim
+ */
+public interface ConfigConstants {
+
+ String APP_TYPE_ZUUL_GATEWAY = "12";
+
+ String ZUUl_PREFIX = "spring.cloud.sentinel.zuul";
+
+ String GATEWAY_PREFIX = "spring.cloud.sentinel.scg";
+
+ String FALLBACK_MSG_RESPONSE = "response";
+ String FALLBACK_REDIRECT = "redirect";
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/FallbackProperties.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/FallbackProperties.java
new file mode 100644
index 00000000..7721571b
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/FallbackProperties.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.alibaba.sentinel.gateway;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+
+/**
+ * @author Jim
+ */
+public class FallbackProperties {
+
+ /**
+ * The fallback mode for sentinel spring-cloud-gateway. choose `redirect` or
+ * `response`.
+ */
+ private String mode;
+ /**
+ * Redirect Url for `redirect` mode.
+ */
+ private String redirect;
+ /**
+ * Response Body for `response` mode.
+ */
+ private String responseBody;
+ /**
+ * Response Status for `response` mode.
+ */
+ private Integer responseStatus = HttpStatus.TOO_MANY_REQUESTS.value();
+ /**
+ * Content-Type for `response` mode.
+ */
+ private String contentType = MediaType.APPLICATION_JSON_UTF8.toString();
+
+ public String getMode() {
+ return mode;
+ }
+
+ public FallbackProperties setMode(String mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ public String getRedirect() {
+ return redirect;
+ }
+
+ public FallbackProperties setRedirect(String redirect) {
+ this.redirect = redirect;
+ return this;
+ }
+
+ public String getResponseBody() {
+ return responseBody;
+ }
+
+ public FallbackProperties setResponseBody(String responseBody) {
+ this.responseBody = responseBody;
+ return this;
+ }
+
+ public Integer getResponseStatus() {
+ return responseStatus;
+ }
+
+ public FallbackProperties setResponseStatus(Integer responseStatus) {
+ this.responseStatus = responseStatus;
+ return this;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public FallbackProperties setContentType(String contentType) {
+ this.contentType = contentType;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelGatewayProperties.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelGatewayProperties.java
new file mode 100644
index 00000000..64b61253
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelGatewayProperties.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.alibaba.sentinel.gateway.scg;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants;
+import org.springframework.cloud.alibaba.sentinel.gateway.FallbackProperties;
+
+/**
+ * @author Jim
+ */
+@ConfigurationProperties(prefix = ConfigConstants.GATEWAY_PREFIX)
+public class SentinelGatewayProperties {
+
+ @NestedConfigurationProperty
+ private FallbackProperties fallback;
+
+ public FallbackProperties getFallback() {
+ return fallback;
+ }
+
+ public SentinelGatewayProperties setFallback(FallbackProperties fallback) {
+ this.fallback = fallback;
+ return this;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java
new file mode 100644
index 00000000..393e63cc
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/scg/SentinelSCGAutoConfiguration.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.alibaba.sentinel.gateway.scg;
+
+import static org.springframework.web.reactive.function.BodyInserters.fromObject;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants;
+import org.springframework.cloud.alibaba.sentinel.gateway.FallbackProperties;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.MediaType;
+import org.springframework.http.codec.ServerCodecConfigurer;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import org.springframework.web.reactive.result.view.ViewResolver;
+import org.springframework.web.server.ServerWebExchange;
+
+import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
+import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
+import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
+import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
+import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.RedirectBlockRequestHandler;
+import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
+import com.alibaba.csp.sentinel.config.SentinelConfig;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import reactor.core.publisher.Mono;
+
+/**
+ * @author Jim
+ */
+@Configuration
+@ConditionalOnClass(GlobalFilter.class)
+@ConditionalOnProperty(prefix = ConfigConstants.GATEWAY_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
+@EnableConfigurationProperties(SentinelGatewayProperties.class)
+public class SentinelSCGAutoConfiguration {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(SentinelSCGAutoConfiguration.class);
+
+ private final List viewResolvers;
+ private final ServerCodecConfigurer serverCodecConfigurer;
+
+ @Autowired
+ private Optional blockRequestHandlerOptional;
+
+ @Autowired
+ private SentinelGatewayProperties gatewayProperties;
+
+ @PostConstruct
+ private void init() {
+ // blockRequestHandlerOptional has low priority
+ blockRequestHandlerOptional.ifPresent(GatewayCallbackManager::setBlockHandler);
+ initAppType();
+ initFallback();
+ }
+
+ public SentinelSCGAutoConfiguration(
+ ObjectProvider> viewResolversProvider,
+ ServerCodecConfigurer serverCodecConfigurer) {
+ this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
+ this.serverCodecConfigurer = serverCodecConfigurer;
+ }
+
+ private void initAppType() {
+ System.setProperty(SentinelConfig.APP_TYPE,
+ String.valueOf(SentinelGatewayConstants.APP_TYPE_GATEWAY));
+ }
+
+ private void initFallback() {
+ FallbackProperties fallbackProperties = gatewayProperties.getFallback();
+ if (fallbackProperties == null
+ || StringUtil.isBlank(fallbackProperties.getMode())) {
+ return;
+ }
+ if (ConfigConstants.FALLBACK_MSG_RESPONSE.equals(fallbackProperties.getMode())) {
+ if (StringUtil.isNotBlank(fallbackProperties.getResponseBody())) {
+ GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
+ @Override
+ public Mono handleRequest(ServerWebExchange exchange,
+ Throwable t) {
+ return ServerResponse
+ .status(fallbackProperties.getResponseStatus())
+ .contentType(MediaType
+ .valueOf(fallbackProperties.getContentType()))
+ .body(fromObject(fallbackProperties.getResponseBody()));
+ }
+ });
+ logger.info(
+ "[Sentinel SpringCloudGateway] using AnonymousBlockRequestHandler, responseStatus: "
+ + fallbackProperties.getResponseStatus()
+ + ", responseBody: "
+ + fallbackProperties.getResponseStatus());
+ }
+ }
+ String redirectUrl = fallbackProperties.getRedirect();
+ if (ConfigConstants.FALLBACK_REDIRECT.equals(fallbackProperties.getMode())
+ && StringUtil.isNotBlank(redirectUrl)) {
+ GatewayCallbackManager
+ .setBlockHandler(new RedirectBlockRequestHandler(redirectUrl));
+ logger.info(
+ "[Sentinel SpringCloudGateway] using RedirectBlockRequestHandler, redirectUrl: "
+ + redirectUrl);
+ }
+ }
+
+ @Bean
+ @Order(Ordered.HIGHEST_PRECEDENCE)
+ @ConditionalOnMissingBean
+ public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
+ // Register the block exception handler for Spring Cloud Gateway.
+ logger.info(
+ "[Sentinel SpringCloudGateway] register SentinelGatewayBlockExceptionHandler");
+ return new SentinelGatewayBlockExceptionHandler(viewResolvers,
+ serverCodecConfigurer);
+ }
+
+ @Bean
+ @Order(-1)
+ @ConditionalOnMissingBean
+ public SentinelGatewayFilter sentinelGatewayFilter() {
+ logger.info("[Sentinel SpringCloudGateway] register SentinelGatewayFilter");
+ return new SentinelGatewayFilter();
+ }
+
+}
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/handler/FallBackProviderHandler.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/FallBackProviderHandler.java
similarity index 95%
rename from spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/handler/FallBackProviderHandler.java
rename to spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/FallBackProviderHandler.java
index 6b3c21f6..be27b988 100644
--- a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/handler/FallBackProviderHandler.java
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/FallBackProviderHandler.java
@@ -1,4 +1,4 @@
-package org.springframework.cloud.alibaba.sentinel.zuul.handler;
+package org.springframework.cloud.alibaba.sentinel.gateway.zuul;
import java.util.Map;
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelZuulAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java
similarity index 64%
rename from spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelZuulAutoConfiguration.java
rename to spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java
index feb9524a..0867df6a 100644
--- a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelZuulAutoConfiguration.java
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulAutoConfiguration.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.alibaba.sentinel.zuul;
+package org.springframework.cloud.alibaba.sentinel.gateway.zuul;
import java.util.Optional;
@@ -25,19 +25,20 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.cloud.alibaba.sentinel.zuul.handler.FallBackProviderHandler;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.RequestOriginParser;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.callback.ZuulGatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulErrorFilter;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPostFilter;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPreFilter;
+import com.alibaba.csp.sentinel.config.SentinelConfig;
-import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.http.ZuulServlet;
/**
@@ -47,66 +48,49 @@ import com.netflix.zuul.http.ZuulServlet;
*/
@Configuration
@ConditionalOnClass(ZuulServlet.class)
-@ConditionalOnProperty(prefix = SentinelZuulAutoConfiguration.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
+@ConditionalOnProperty(prefix = ConfigConstants.ZUUl_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
+@EnableConfigurationProperties(SentinelZuulProperties.class)
public class SentinelZuulAutoConfiguration {
private static final Logger logger = LoggerFactory
.getLogger(SentinelZuulAutoConfiguration.class);
- public static final String PREFIX = "spring.cloud.sentinel.zuul";
-
- @Autowired
- private Environment environment;
-
@Autowired
private Optional requestOriginParserOptional;
+ @Autowired
+ private SentinelZuulProperties zuulProperties;
+
@PostConstruct
private void init() {
requestOriginParserOptional
.ifPresent(ZuulGatewayCallbackManager::setOriginParser);
+ System.setProperty(SentinelConfig.APP_TYPE,
+ String.valueOf(ConfigConstants.APP_TYPE_ZUUL_GATEWAY));
}
@Bean
- public ZuulFilter sentinelZuulPreFilter() {
- String preOrderStr = environment.getProperty(PREFIX + "." + "order.pre");
- int order = 10000;
- try {
- order = Integer.parseInt(preOrderStr);
- }
- catch (NumberFormatException e) {
- // ignore
- }
- logger.info("[Sentinel Zuul] register SentinelZuulPreFilter {}", order);
- return new SentinelZuulPreFilter(order);
+ @ConditionalOnMissingBean
+ public SentinelZuulPreFilter sentinelZuulPreFilter() {
+ logger.info("[Sentinel Zuul] register SentinelZuulPreFilter {}",
+ zuulProperties.getOrder().getPre());
+ return new SentinelZuulPreFilter(zuulProperties.getOrder().getPre());
}
@Bean
- public ZuulFilter sentinelZuulPostFilter() {
- String postOrderStr = environment.getProperty(PREFIX + "." + "order.post");
- int order = 1000;
- try {
- order = Integer.parseInt(postOrderStr);
- }
- catch (NumberFormatException e) {
- // ignore
- }
- logger.info("[Sentinel Zuul] register SentinelZuulPostFilter {}", order);
- return new SentinelZuulPostFilter(order);
+ @ConditionalOnMissingBean
+ public SentinelZuulPostFilter sentinelZuulPostFilter() {
+ logger.info("[Sentinel Zuul] register SentinelZuulPostFilter {}",
+ zuulProperties.getOrder().getPost());
+ return new SentinelZuulPostFilter(zuulProperties.getOrder().getPost());
}
@Bean
- public ZuulFilter sentinelZuulErrorFilter() {
- String errorOrderStr = environment.getProperty(PREFIX + "." + "order.error");
- int order = -1;
- try {
- order = Integer.parseInt(errorOrderStr);
- }
- catch (NumberFormatException e) {
- // ignore
- }
- logger.info("[Sentinel Zuul] register SentinelZuulErrorFilter {}", order);
- return new SentinelZuulErrorFilter(order);
+ @ConditionalOnMissingBean
+ public SentinelZuulErrorFilter sentinelZuulErrorFilter() {
+ logger.info("[Sentinel Zuul] register SentinelZuulErrorFilter {}",
+ zuulProperties.getOrder().getError());
+ return new SentinelZuulErrorFilter(zuulProperties.getOrder().getError());
}
@Bean
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulProperties.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulProperties.java
new file mode 100644
index 00000000..a89a1ad7
--- /dev/null
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/gateway/zuul/SentinelZuulProperties.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.alibaba.sentinel.gateway.zuul;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+import org.springframework.cloud.alibaba.sentinel.gateway.ConfigConstants;
+
+import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant;
+import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulErrorFilter;
+import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPostFilter;
+import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPreFilter;
+
+/**
+ * @author Jim
+ */
+@ConfigurationProperties(prefix = ConfigConstants.ZUUl_PREFIX)
+public class SentinelZuulProperties {
+
+ @NestedConfigurationProperty
+ private SentinelZuulProperties.Order order;
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public SentinelZuulProperties setOrder(Order order) {
+ this.order = order;
+ return this;
+ }
+
+ public static class Order {
+
+ /**
+ * The order of {@link SentinelZuulPreFilter}.
+ */
+ private int pre = 10000;
+
+ /**
+ * The order of {@link SentinelZuulPostFilter}.
+ */
+ private int post = ZuulConstant.SEND_RESPONSE_FILTER_ORDER;
+
+ /**
+ * The order of {@link SentinelZuulErrorFilter}.
+ */
+ private int error = -1;
+
+ public int getPre() {
+ return pre;
+ }
+
+ public void setPre(int pre) {
+ this.pre = pre;
+ }
+
+ public int getPost() {
+ return post;
+ }
+
+ public void setPost(int post) {
+ this.post = post;
+ }
+
+ public int getError() {
+ return error;
+ }
+
+ public void setError(int error) {
+ this.error = error;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelSpringCloudGatewayAutoConfiguration.java b/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelSpringCloudGatewayAutoConfiguration.java
deleted file mode 100644
index dd42c39f..00000000
--- a/spring-cloud-alibaba-sentinel-gateway/src/main/java/org/springframework/cloud/alibaba/sentinel/zuul/SentinelSpringCloudGatewayAutoConfiguration.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.cloud.alibaba.sentinel.zuul;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-import javax.annotation.PostConstruct;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.cloud.gateway.filter.GlobalFilter;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.Ordered;
-import org.springframework.core.annotation.Order;
-import org.springframework.http.codec.ServerCodecConfigurer;
-import org.springframework.web.reactive.result.view.ViewResolver;
-
-import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
-import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
-import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
-import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
-
-/**
- * @author Jim
- */
-@Configuration
-@ConditionalOnClass(GlobalFilter.class)
-@ConditionalOnProperty(prefix = "spring.cloud.sentinel.spring-cloud-gateway", name = "enabled", havingValue = "true", matchIfMissing = true)
-public class SentinelSpringCloudGatewayAutoConfiguration {
-
- private static final Logger logger = LoggerFactory
- .getLogger(SentinelSpringCloudGatewayAutoConfiguration.class);
-
- private final List viewResolvers;
- private final ServerCodecConfigurer serverCodecConfigurer;
-
- @Autowired
- private Optional blockRequestHandlerOptional;
-
- @PostConstruct
- private void init() {
- blockRequestHandlerOptional.ifPresent(GatewayCallbackManager::setBlockHandler);
- }
-
- public SentinelSpringCloudGatewayAutoConfiguration(
- ObjectProvider> viewResolversProvider,
- ServerCodecConfigurer serverCodecConfigurer) {
- this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
- this.serverCodecConfigurer = serverCodecConfigurer;
- }
-
- @Bean
- @Order(Ordered.HIGHEST_PRECEDENCE)
- public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
- // Register the block exception handler for Spring Cloud Gateway.
- logger.info(
- "[Sentinel SpringCloudGateway] register SentinelGatewayBlockExceptionHandler");
- return new SentinelGatewayBlockExceptionHandler(viewResolvers,
- serverCodecConfigurer);
- }
-
- @Bean
- @Order(-1)
- public GlobalFilter sentinelGatewayFilter() {
- logger.info("[Sentinel SpringCloudGateway] register SentinelGatewayFilter");
- return new SentinelGatewayFilter();
- }
-
-}
diff --git a/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories
index 5917e8ff..15297fce 100644
--- a/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-alibaba-sentinel-gateway/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.springframework.cloud.alibaba.sentinel.zuul.SentinelZuulAutoConfiguration,\
-org.springframework.cloud.alibaba.sentinel.zuul.SentinelSpringCloudGatewayAutoConfiguration
\ No newline at end of file
+org.springframework.cloud.alibaba.sentinel.gateway.zuul.SentinelZuulAutoConfiguration,\
+org.springframework.cloud.alibaba.sentinel.gateway.scg.SentinelSCGAutoConfiguration
\ No newline at end of file
diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpoint.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpoint.java
index 0133fe24..6160a5f6 100644
--- a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpoint.java
+++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/endpoint/AcmEndpoint.java
@@ -16,13 +16,6 @@
package org.springframework.cloud.alicloud.acm.endpoint;
-import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
-import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
-import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
-import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
-import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
-import org.springframework.cloud.alicloud.context.acm.AcmProperties;
-
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -30,6 +23,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+import org.springframework.cloud.alicloud.acm.AcmPropertySourceRepository;
+import org.springframework.cloud.alicloud.acm.bootstrap.AcmPropertySource;
+import org.springframework.cloud.alicloud.acm.refresh.AcmRefreshHistory;
+import org.springframework.cloud.alicloud.context.acm.AcmProperties;
+
/**
* Created on 01/10/2017.
*
@@ -44,7 +44,12 @@ public class AcmEndpoint {
private final AcmPropertySourceRepository propertySourceRepository;
- private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private ThreadLocal dateFormat = new ThreadLocal() {
+ @Override
+ protected DateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ };
public AcmEndpoint(AcmProperties properties, AcmRefreshHistory refreshHistory,
AcmPropertySourceRepository propertySourceRepository) {
@@ -65,7 +70,7 @@ public class AcmEndpoint {
for (AcmPropertySource ps : all) {
Map source = new HashMap<>();
source.put("dataId", ps.getDataId());
- source.put("lastSynced", dateFormat.format(ps.getTimestamp()));
+ source.put("lastSynced", dateFormat.get().format(ps.getTimestamp()));
sources.add(source);
}
runtime.put("sources", sources);
diff --git a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmRefreshHistory.java b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmRefreshHistory.java
index 439e6360..19197b89 100644
--- a/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmRefreshHistory.java
+++ b/spring-cloud-alicloud-acm/src/main/java/org/springframework/cloud/alicloud/acm/refresh/AcmRefreshHistory.java
@@ -30,10 +30,15 @@ public class AcmRefreshHistory {
private LinkedList records = new LinkedList<>();
- private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private ThreadLocal dateFormat = new ThreadLocal() {
+ @Override
+ protected DateFormat initialValue() {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ }
+ };
public void add(String dataId, String md5) {
- records.addFirst(new Record(dateFormat.format(new Date()), dataId, md5));
+ records.addFirst(new Record(dateFormat.get().format(new Date()), dataId, md5));
if (records.size() > MAX_SIZE) {
records.removeLast();
}