houzhongjian
2024-08-02 4a47e4b93f62b5e636ac0e76f3e4ee98e2b83154
提交 | 用户 | 时间
e7c126 1 package com.iailab.framework.tenant.config;
H 2
3 import com.iailab.framework.common.enums.WebFilterOrderEnum;
4 import com.iailab.framework.mybatis.core.util.MyBatisUtils;
5 import com.iailab.framework.redis.config.IailabCacheProperties;
6 import com.iailab.framework.tenant.core.aop.TenantIgnoreAspect;
7 import com.iailab.framework.tenant.core.db.TenantDatabaseInterceptor;
8 import com.iailab.framework.tenant.core.job.TenantJobAspect;
9 import com.iailab.framework.tenant.core.mq.rabbitmq.TenantRabbitMQInitializer;
10 import com.iailab.framework.tenant.core.mq.redis.TenantRedisMessageInterceptor;
11 import com.iailab.framework.tenant.core.mq.rocketmq.TenantRocketMQInitializer;
12 import com.iailab.framework.tenant.core.redis.TenantRedisCacheManager;
13 import com.iailab.framework.tenant.core.security.TenantSecurityWebFilter;
14 import com.iailab.framework.tenant.core.service.TenantFrameworkService;
15 import com.iailab.framework.tenant.core.service.TenantFrameworkServiceImpl;
16 import com.iailab.framework.tenant.core.web.TenantContextWebFilter;
17 import com.iailab.framework.web.config.WebProperties;
18 import com.iailab.framework.web.core.handler.GlobalExceptionHandler;
19 import com.iailab.module.system.api.tenant.TenantApi;
20 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
21 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
22 import org.springframework.boot.autoconfigure.AutoConfiguration;
23 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
24 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
25 import org.springframework.boot.context.properties.EnableConfigurationProperties;
26 import org.springframework.boot.web.servlet.FilterRegistrationBean;
27 import org.springframework.context.annotation.Bean;
28 import org.springframework.context.annotation.Configuration;
29 import org.springframework.context.annotation.Primary;
30 import org.springframework.data.redis.cache.BatchStrategies;
31 import org.springframework.data.redis.cache.RedisCacheConfiguration;
32 import org.springframework.data.redis.cache.RedisCacheManager;
33 import org.springframework.data.redis.cache.RedisCacheWriter;
34 import org.springframework.data.redis.connection.RedisConnectionFactory;
35 import org.springframework.data.redis.core.RedisTemplate;
36
37 import java.util.Objects;
38
39 @AutoConfiguration
40 @ConditionalOnProperty(prefix = "iailab.tenant", value = "enable", matchIfMissing = true) // 允许使用 iailab.tenant.enable=false 禁用多租户
41 @EnableConfigurationProperties(TenantProperties.class)
42 public class IailabTenantAutoConfiguration {
43
44     @Bean
45     public TenantFrameworkService tenantFrameworkService(TenantApi tenantApi) {
46         return new TenantFrameworkServiceImpl(tenantApi);
47     }
48
49     // ========== AOP ==========
50
51     @Bean
52     public TenantIgnoreAspect tenantIgnoreAspect() {
53         return new TenantIgnoreAspect();
54     }
55
56     // ========== DB ==========
57
58     @Bean
59     public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties,
60                                                                  MybatisPlusInterceptor interceptor) {
61         TenantLineInnerInterceptor inner = new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
62         // 添加到 interceptor 中
63         // 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
64         MyBatisUtils.addInterceptor(interceptor, inner, 0);
65         return inner;
66     }
67
68     // ========== WEB ==========
69
70     @Bean
71     public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
72         FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
73         registrationBean.setFilter(new TenantContextWebFilter());
74         registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
75         return registrationBean;
76     }
77
78     // ========== Security ==========
79
80     @Bean
81     public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties,
82                                                                                    WebProperties webProperties,
83                                                                                    GlobalExceptionHandler globalExceptionHandler,
84                                                                                    TenantFrameworkService tenantFrameworkService) {
85         FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
86         registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties,
87                 globalExceptionHandler, tenantFrameworkService));
88         registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
89         return registrationBean;
90     }
91
92     // ========== Job ==========
93
94     @Bean
95     @ConditionalOnClass(name = "com.xxl.job.core.handler.annotation.XxlJob")
96     public TenantJobAspect tenantJobAspect(TenantFrameworkService tenantFrameworkService) {
97         return new TenantJobAspect(tenantFrameworkService);
98     }
99
100     // ========== MQ ==========
101
102     /**
103      * 多租户 Redis 消息队列的配置类
104      *
105      * 为什么要单独一个配置类呢?如果直接把 TenantRedisMessageInterceptor Bean 的初始化放外面,会报 RedisMessageInterceptor 类不存在的错误
106      */
107     @Configuration
108     @ConditionalOnClass(name = "com.iailab.framework.mq.redis.core.RedisMQTemplate")
109     public static class TenantRedisMQAutoConfiguration {
110
111         @Bean
112         public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() {
113             return new TenantRedisMessageInterceptor();
114         }
115
116     }
117
118     @Bean
119     @ConditionalOnClass(name = "org.springframework.amqp.rabbit.core.RabbitTemplate")
120     public TenantRabbitMQInitializer tenantRabbitMQInitializer() {
121         return new TenantRabbitMQInitializer();
122     }
123
124     @Bean
125     @ConditionalOnClass(name = "org.apache.rocketmq.spring.core.RocketMQTemplate")
126     public TenantRocketMQInitializer tenantRocketMQInitializer() {
127         return new TenantRocketMQInitializer();
128     }
129
130     // ========== Redis ==========
131
132     @Bean
133     @Primary // 引入租户时,tenantRedisCacheManager 为主 Bean
134     public RedisCacheManager tenantRedisCacheManager(RedisTemplate<String, Object> redisTemplate,
135                                                      RedisCacheConfiguration redisCacheConfiguration,
4a47e4 136                                                      IailabCacheProperties iailabCacheProperties,
H 137                                                      TenantProperties tenantProperties) {
e7c126 138         // 创建 RedisCacheWriter 对象
H 139         RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory());
140         RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory,
141                 BatchStrategies.scan(iailabCacheProperties.getRedisScanBatchSize()));
142         // 创建 TenantRedisCacheManager 对象
4a47e4 143         return new TenantRedisCacheManager(cacheWriter, redisCacheConfiguration, tenantProperties.getIgnoreCaches());
e7c126 144     }
H 145 }