1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

hello, spring cloud alibaba

This commit is contained in:
flystar32
2018-07-27 19:18:12 +08:00
parent b4b0cceb66
commit 0ce2df89ab
34 changed files with 2151 additions and 1 deletions

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>0.2.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-autoconfigure</artifactId>
<name>Spring Cloud Alibaba Sentinel Autoconfigure</name>
<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<!--spring boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,110 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.core.Ordered;
/**
* @author xiaojing
* @author hengyunabc
*/
@ConfigurationProperties(prefix = "spring.cloud.sentinel")
public class SentinelProperties {
/**
* Enable sentinel auto configure, the default value is true
*/
private boolean enabled = true;
/**
* sentinel api port,default value is 8721
*/
private String port = "8721";
/**
* Sentinel dashboard address, won't try to connect dashboard when address is empty
*/
private String dashboard = "";
@NestedConfigurationProperty
private Filter filter;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getDashboard() {
return dashboard;
}
public void setDashboard(String dashboard) {
this.dashboard = dashboard;
}
public Filter getFilter() {
return filter;
}
public void setFilter(Filter filter) {
this.filter = filter;
}
public static class Filter {
/**
* Sentinel filter chain order.
*/
private int order = Ordered.HIGHEST_PRECEDENCE;
/**
* URL pattern for sentinel filter,default is /*
*/
private List<String> urlPatterns;
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
public List<String> getUrlPatterns() {
return urlPatterns;
}
public void setUrlPatterns(List<String> urlPatterns) {
this.urlPatterns = urlPatterns;
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel;
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.csp.sentinel.transport.config.TransportConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.servlet.Filter;
/**
* @author xiaojing
*/
@Configuration
@ConditionalOnWebApplication
@ConditionalOnProperty(name = "spring.cloud.sentinel.enabled", matchIfMissing = true)
@EnableConfigurationProperties(SentinelProperties.class)
public class SentinelWebAutoConfiguration {
private static final Logger logger = LoggerFactory
.getLogger(SentinelWebAutoConfiguration.class);
@Value("${project.name:${spring.application.name:}}")
private String projectName;
@Autowired
private SentinelProperties properties;
public static final String APP_NAME = "project.name";
@PostConstruct
private void init() {
if (StringUtils.isEmpty(System.getProperty(APP_NAME))) {
System.setProperty(APP_NAME, projectName);
}
if (StringUtils.isEmpty(System.getProperty(TransportConfig.SERVER_PORT))) {
System.setProperty(TransportConfig.SERVER_PORT, properties.getPort());
}
if (StringUtils.isEmpty(System.getProperty(TransportConfig.CONSOLE_SERVER))) {
System.setProperty(TransportConfig.CONSOLE_SERVER, properties.getDashboard());
}
}
@Bean
@ConditionalOnWebApplication
public FilterRegistrationBean<Filter> servletRequestListener() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
SentinelProperties.Filter filterConfig = properties.getFilter();
if (null == filterConfig) {
filterConfig = new SentinelProperties.Filter();
properties.setFilter(filterConfig);
}
if (filterConfig.getUrlPatterns() == null
|| filterConfig.getUrlPatterns().isEmpty()) {
List<String> defaultPatterns = new ArrayList<>();
defaultPatterns.add("/*");
filterConfig.setUrlPatterns(defaultPatterns);
}
registration.addUrlPatterns(filterConfig.getUrlPatterns().toArray(new String[0]));
Filter filter = new CommonFilter();
registration.setFilter(filter);
registration.setOrder(filterConfig.getOrder());
logger.info("[Sentinel Starter] register Sentinel with urlPatterns: {}.",
filterConfig.getUrlPatterns());
return registration;
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.custom;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to add Sentinel to custom method
* @author xiaojing
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableSentinel {
/**
* @return sentinel resource value
*/
String value();
/**
* @return Sentinel BlockException Handler name
*/
String handler() default "";
}

View File

@@ -0,0 +1,46 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.custom;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author xiaojing
*/
public class HandlerUtil {
private static final ConcurrentHashMap<String, SentinelBlockHandler> map = new ConcurrentHashMap<>(
16);
/**
* you should add your custom handler before use it
* @param name see {@link EnableSentinel#handler()}
* @param handler you custom handler
*/
public static void addHandler(String name, SentinelBlockHandler handler) {
map.put(name, handler);
}
public static SentinelBlockHandler getHandler(String name) {
SentinelBlockHandler handler = map.get(name);
if (null == handler) {
throw new RuntimeException("cannot find handler name=<" + name
+ ",> did you forgot to invoke HandlerUtil.addHandler(name, handler) ?");
}
return handler;
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.custom;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author xiaojing
*/
@Aspect
public class SentinelAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(SentinelAspect.class);
@Around("@annotation(org.springframework.cloud.alibaba.sentinel.custom.EnableSentinel)")
public Object customBlock(ProceedingJoinPoint pjp) throws Throwable {
SentinelEntry sentinelEntry = new SentinelEntry();
try {
beforeProceed(sentinelEntry, pjp);
return pjp.proceed();
}
catch (BlockException e) {
LOGGER.error(e.getMessage(), e);
if (null != sentinelEntry.getHandler()
&& sentinelEntry.getHandler().length() > 0) {
return HandlerUtil.getHandler(sentinelEntry.getHandler()).handler(e);
}
else {
throw e;
}
}
finally {
releaseContextResources(sentinelEntry);
}
}
private void beforeProceed(SentinelEntry sentinelEntry, ProceedingJoinPoint pjp)
throws BlockException {
Method method = getMethod(pjp);
int modifiers = method.getModifiers();
if (!Modifier.isPublic(modifiers) || "toString".equals(method.getName())
|| "hashCode".equals(method.getName())
|| "equals".equals(method.getName())
|| "finalize".equals(method.getName())) {
return;
}
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof EnableSentinel) {
sentinelEntry.setKey(((EnableSentinel) annotation).value());
sentinelEntry.setHandler(((EnableSentinel) annotation).handler());
}
}
if (null == sentinelEntry.getKey() || sentinelEntry.getKey().length() == 0) {
return;
}
ContextUtil.enter(sentinelEntry.getKey());
sentinelEntry.setEntry(SphU.entry(sentinelEntry.getKey()));
}
private void releaseContextResources(SentinelEntry sentinelEntry) {
if (null == sentinelEntry.getEntry()) {
return;
}
Entry entry = sentinelEntry.getEntry();
entry.exit();
ContextUtil.exit();
}
private Method getMethod(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
return signature.getMethod();
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.custom;
import com.alibaba.csp.sentinel.slots.block.BlockException;
/**
* Sentinel Block Handler
* @author xiaojing
*/
public interface SentinelBlockHandler {
/**
* custom method to process BlockException
* @param e block exception when blocked by sentinel
* @return Object result processed by the handler
*/
Object handler(BlockException e);
}

View File

@@ -0,0 +1,30 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.custom;
import org.springframework.context.annotation.Bean;
/**
* @author xiaojing
*/
public class SentinelCustomAspectAutoConfiguration {
@Bean
public SentinelAspect sentinelAspect() {
return new SentinelAspect();
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.custom;
import com.alibaba.csp.sentinel.Entry;
/**
* @author xiaojing
*/
public class SentinelEntry {
private String key;
private String handler;
private Entry entry;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getHandler() {
return handler;
}
public void setHandler(String handler) {
this.handler = handler;
}
public Entry getEntry() {
return entry;
}
public void setEntry(Entry entry) {
this.entry = entry;
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.endpoint;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
/**
* Endpoint for Sentinel, contains ans properties and rules
* @author xiaojing
*/
@Endpoint(id = "sentinel")
public class SentinelEndpoint {
@Autowired
private SentinelProperties sentinelProperties;
@ReadOperation
public Map<String, Object> invoke() {
Map<String, Object> result = new HashMap<>();
List<FlowRule> flowRules = FlowRuleManager.getRules();
List<DegradeRule> degradeRules = DegradeRuleManager.getRules();
List<SystemRule> systemRules = SystemRuleManager.getRules();
result.put("properties", sentinelProperties);
result.put("FlowRules", flowRules);
result.put("DegradeRules", degradeRules);
result.put("SystemRules", systemRules);
return result;
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel.endpoint;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.alibaba.sentinel.SentinelProperties;
import org.springframework.context.annotation.Bean;
/**
* @author hengyunabc
*/
@ConditionalOnClass(Endpoint.class)
@EnableConfigurationProperties({ SentinelProperties.class })
public class SentinelEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
public SentinelEndpoint sentinelEndPoint() {
return new SentinelEndpoint();
}
}

View File

@@ -0,0 +1,32 @@
{
"properties": [
{
"name": "spring.cloud.sentinel.enabled",
"type": "java.lang.Boolean",
"defaultValue": true,
"description": "enable or disable sentinel auto configure."
},
{
"name": "spring.cloud.sentinel.port",
"type": "java.lang.String",
"defaultValue": "8721",
"description": "sentinel api port."
},
{
"name": "spring.cloud.sentinel.dashboard",
"type": "java.lang.String",
"description": "sentinel dashboard address, won't try to connect dashboard when address is empty."
},
{
"name": "spring.cloud.sentinel.filter.order",
"type": "java.lang.Integer",
"defaultValue": "Integer.MIN_VALUE",
"description": "Sentinel filter chain order, will be set to FilterRegistrationBean."
},
{
"name": "spring.cloud.sentinel.filter.urlPatterns",
"type": "java.util.List",
"description": "URL pattern for Sentinel filter, default contains '/*'."
}
]
}

View File

@@ -0,0 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alibaba.sentinel.SentinelWebAutoConfiguration,\
org.springframework.cloud.alibaba.sentinel.endpoint.SentinelEndpointAutoConfiguration,\
org.springframework.cloud.alibaba.sentinel.custom.SentinelCustomAspectAutoConfiguration

View File

@@ -0,0 +1,66 @@
/*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.sentinel;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.alibaba.sentinel.custom.SentinelAspect;
import org.springframework.cloud.alibaba.sentinel.custom.SentinelCustomAspectAutoConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author fangjian
*/
public class SentinelAutoConfigurationTests {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(SentinelCustomAspectAutoConfiguration.class, SentinelWebAutoConfiguration.class))
.withPropertyValues("spring.cloud.sentinel.port=8888")
.withPropertyValues("spring.cloud.sentinel.filter.order=123")
.withPropertyValues("spring.cloud.sentinel.filter.urlPatterns=/*,/test");
@Test
public void testSentinelAspect() {
this.contextRunner.run(context -> assertThat(context).hasSingleBean(SentinelAspect.class));
}
@Test
public void testFilter() {
this.contextRunner.run(context -> {
assertThat(context.getBean(
"servletRequestListener").getClass() == FilterRegistrationBean.class).isTrue();
});
}
@Test
public void testProperties() {
this.contextRunner.run(context -> {
SentinelProperties sentinelProperties = context.getBean(SentinelProperties.class);
assertThat(sentinelProperties.getPort()).isEqualTo("8888");
assertThat(sentinelProperties.getFilter().getUrlPatterns().size()).isEqualTo(2);
assertThat(sentinelProperties.getFilter().getUrlPatterns().get(0)).isEqualTo("/*");
assertThat(sentinelProperties.getFilter().getUrlPatterns().get(1)).isEqualTo("/test");
});
}
}