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