diff --git a/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/config/ZtTenantAutoConfiguration.java b/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/config/ZtTenantAutoConfiguration.java index 10769c2c..9afdba62 100644 --- a/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/config/ZtTenantAutoConfiguration.java +++ b/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/config/ZtTenantAutoConfiguration.java @@ -25,6 +25,7 @@ import com.zt.plat.framework.web.core.handler.GlobalExceptionHandler; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import jakarta.annotation.Resource; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -49,17 +50,30 @@ import org.springframework.web.util.pattern.PathPattern; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList; @AutoConfiguration @ConditionalOnProperty(prefix = "zt.tenant", value = "enable", matchIfMissing = true) // 允许使用 zt.tenant.enable=false 禁用多租户 @EnableConfigurationProperties(TenantProperties.class) -public class ZtTenantAutoConfiguration { +public class ZtTenantAutoConfiguration implements SmartInitializingSingleton { @Resource private ApplicationContext applicationContext; + @Resource + private TenantProperties tenantProperties; + + /** + * 存放 @TenantIgnore 注解的 URL + * + * 为什么不直接放到 TenantProperties 中? + * 因为 TenantProperties 是 @ConfigurationProperties Bean,可能会被 Nacos 等配置中心刷新,导致 programmatically 添加的 URL 丢失。 + */ + private final Set globalIgnoreUrls = ConcurrentHashMap.newKeySet(); + @Bean public TenantFrameworkService tenantFrameworkService(TenantCommonApi tenantApi) { // 参见 https://gitee.com/zhijiantianya/zt-cloud/issues/IC6YZF @@ -98,16 +112,18 @@ public class ZtTenantAutoConfiguration { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new TenantContextWebFilter()); registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER); - addIgnoreUrls(tenantProperties); return registrationBean; } + @Override + public void afterSingletonsInstantiated() { + addIgnoreUrls(); + } + /** * 如果 Controller 接口上,有 {@link TenantIgnore} 注解,那么添加到忽略的 URL 中 - * - * @param tenantProperties 租户配置 */ - private void addIgnoreUrls(TenantProperties tenantProperties) { + private void addIgnoreUrls() { // 获得接口对应的 HandlerMethod 集合 RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); @@ -120,10 +136,10 @@ public class ZtTenantAutoConfiguration { } // 添加到忽略的 URL 中 if (entry.getKey().getPatternsCondition() != null) { - tenantProperties.getIgnoreUrls().addAll(entry.getKey().getPatternsCondition().getPatterns()); + globalIgnoreUrls.addAll(entry.getKey().getPatternsCondition().getPatterns()); } if (entry.getKey().getPathPatternsCondition() != null) { - tenantProperties.getIgnoreUrls().addAll( + globalIgnoreUrls.addAll( convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString)); } } @@ -172,7 +188,7 @@ public class ZtTenantAutoConfiguration { TenantFrameworkService tenantFrameworkService) { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties, - globalExceptionHandler, tenantFrameworkService)); + globalExceptionHandler, tenantFrameworkService, globalIgnoreUrls)); registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER); return registrationBean; } diff --git a/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/core/security/TenantSecurityWebFilter.java b/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/core/security/TenantSecurityWebFilter.java index c473c4ef..15c04f47 100644 --- a/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/core/security/TenantSecurityWebFilter.java +++ b/zt-framework/zt-spring-boot-starter-biz-tenant/src/main/java/com/zt/plat/framework/tenant/core/security/TenantSecurityWebFilter.java @@ -21,6 +21,7 @@ import org.springframework.util.AntPathMatcher; import java.io.IOException; import java.util.Objects; +import java.util.Set; /** * 多租户 Security Web 过滤器 @@ -39,16 +40,19 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { private final GlobalExceptionHandler globalExceptionHandler; private final TenantFrameworkService tenantFrameworkService; + private final Set globalIgnoreUrls; public TenantSecurityWebFilter(TenantProperties tenantProperties, WebProperties webProperties, GlobalExceptionHandler globalExceptionHandler, - TenantFrameworkService tenantFrameworkService) { + TenantFrameworkService tenantFrameworkService, + Set globalIgnoreUrls) { super(webProperties); this.tenantProperties = tenantProperties; this.pathMatcher = new AntPathMatcher(); this.globalExceptionHandler = globalExceptionHandler; this.tenantFrameworkService = tenantFrameworkService; + this.globalIgnoreUrls = globalIgnoreUrls; } @Override @@ -105,12 +109,20 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { if (CollUtil.contains(tenantProperties.getIgnoreUrls(), request.getRequestURI())) { return true; } + if (CollUtil.contains(globalIgnoreUrls, request.getRequestURI())) { + return true; + } // 逐个 Ant 路径匹配 for (String url : tenantProperties.getIgnoreUrls()) { if (pathMatcher.match(url, request.getRequestURI())) { return true; } } + for (String url : globalIgnoreUrls) { + if (pathMatcher.match(url, request.getRequestURI())) { + return true; + } + } return false; }