增加 Tenant MQ 的支持

pull/2/head
YunaiV 2021-12-06 01:32:41 +08:00
parent a231582637
commit 1ce2c09f47
12 changed files with 95 additions and 31 deletions

View File

@ -1,7 +1,7 @@
### 请求 /login 接口 => 成功
POST {{baseUrl}}/login
Content-Type: application/json
tenant-id: 0
tenant-id: 1
{
"username": "admin",
@ -13,10 +13,13 @@ tenant-id: 0
### 请求 /get-permission-info 接口 => 成功
GET {{baseUrl}}/get-permission-info
Authorization: Bearer {{token}}
tenant-id: 1
### 请求 /list-menus 接口 => 成功
GET {{baseUrl}}/list-menus
Authorization: Bearer {{token}}
#Authorization: Bearer 0d161f69c9ac4c7f836e1b850715a7b0
tenant-id: 1
### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
GET http://127.0.0.1:8080/druid/123

View File

@ -21,7 +21,7 @@ public class SysTenantController {
@ApiImplicitParam(name = "name", value = "租户名", required = true, example = "芋道源码", dataTypeClass = Long.class)
public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
if (Objects.equals("芋道源码", name)) {
return CommonResult.success(0L);
return CommonResult.success(1L);
}
return CommonResult.success(null);
}

View File

@ -22,7 +22,7 @@ spring:
# MyBatis Plus 的配置项
mybatis-plus:
# 在 mybatis-config/mybatis-config.xml 中设置
# 在 mybatis-config/mybatis-config.xml 中设置 TODO jason看看有没其它解决方案
# configuration:
# map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志

View File

@ -6,6 +6,7 @@
<settings>
<setting name="lazyLoadingEnabled" value="false" />
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>
</settings>
<typeAliases>
<typeAlias type="org.activiti.engine.impl.persistence.ByteArrayRefTypeHandler" alias="ByteArrayRefTypeHandler"/>

View File

@ -1,5 +1,7 @@
package cn.iocoder.yudao.framework.mq.core.message;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@ -8,12 +10,13 @@ import java.util.Map;
*
* @author
*/
@Data
public abstract class AbstractRedisMessage {
/**
*
*/
private final Map<String, String> headers = new HashMap<>();
private Map<String, String> headers = new HashMap<>();
public String getHeader(String key) {
return headers.get(key);

View File

@ -40,10 +40,11 @@ public class MyBatisUtils {
*
* @param interceptor
* @param inner
* @param index
*/
public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner) {
public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) {
List<InnerInterceptor> inners = new ArrayList<>(interceptor.getInterceptors());
inners.add(0, inner);
inners.add(index, inner);
interceptor.setInterceptors(inners);
}

View File

@ -38,6 +38,12 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-job</artifactId>
</dependency>
<!-- 消息队列相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mq</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -4,40 +4,27 @@ import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* DB
*
* @author
*/
@Configuration
@EnableConfigurationProperties(TenantProperties.class)
public class YudaoTenantDatabaseAutoConfiguration {
@Bean
public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties) {
return new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
}
@Bean
public BeanPostProcessor mybatisPlusInterceptorBeanPostProcessor(TenantLineInnerInterceptor tenantLineInnerInterceptor) {
return new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof MybatisPlusInterceptor)) {
return bean;
}
// 将 TenantDatabaseInterceptor 添加到最前面
MybatisPlusInterceptor interceptor = (MybatisPlusInterceptor) bean;
MyBatisUtils.addInterceptor(interceptor, tenantLineInnerInterceptor);
return bean;
}
};
public TenantLineInnerInterceptor tenantLineInnerInterceptor(TenantProperties properties,
MybatisPlusInterceptor interceptor) {
TenantLineInnerInterceptor inner = new TenantLineInnerInterceptor(new TenantDatabaseInterceptor(properties));
// 添加到 interceptor 中
// 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
MyBatisUtils.addInterceptor(interceptor, inner, 0);
return inner;
}
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.iocoder.yudao.framework.tenant.core.mq.TenantRedisMessageInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MQ
*
* @author
*/
@Configuration
public class YudaoTenantMQAutoConfiguration {
@Bean
public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() {
return new TenantRedisMessageInterceptor();
}
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.framework.tenant.core.mq;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.mq.core.interceptor.RedisMessageInterceptor;
import cn.iocoder.yudao.framework.mq.core.message.AbstractRedisMessage;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
/**
* {@link AbstractRedisMessage}
*
* 1. Producer {@link TenantContextHolder} Header
* 2. Consumer Header {@link TenantContextHolder}
*
* @author
*/
public class TenantRedisMessageInterceptor implements RedisMessageInterceptor {
private static final String HEADER_TENANT_ID = "tenant-id";
@Override
public void sendMessageBefore(AbstractRedisMessage message) {
Long tenantId = TenantContextHolder.getTenantId();
if (tenantId != null) {
message.addHeader(HEADER_TENANT_ID, tenantId.toString());
}
}
@Override
public void consumeMessageBefore(AbstractRedisMessage message) {
String tenantIdStr = message.getHeader(HEADER_TENANT_ID);
if (StrUtil.isNotEmpty(tenantIdStr)) {
TenantContextHolder.setTenantId(Long.valueOf(tenantIdStr));
}
}
@Override
public void consumeMessageAfter(AbstractRedisMessage message) {
// 注意Consumer 是一个逻辑的入口,所以不考虑原本上下文就存在租户编号的情况
TenantContextHolder.clear();
}
}

View File

@ -1,9 +1,9 @@
/**
*
* 1. DB MyBatis Plus
* 2. Web HTTP API Header tenant-id
* 2. Web HTTP API Header tenant-id
* 3. Job JobHandler
* 4. MQTODO
* 4. MQ Producer Header tenant-id Consumer Header tenant-id
* 5. Async ThreadLocal 使 TransmittableThreadLocal
* 1Spring Async
* {@link cn.iocoder.yudao.framework.quartz.config.YudaoAsyncAutoConfiguration#threadPoolTaskExecutorBeanPostProcessor()}

View File

@ -1,4 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantDatabaseAutoConfiguration,\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantWebAutoConfiguration,\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantJobAutoConfiguration
cn.iocoder.yudao.framework.tenant.config.YudaoTenantJobAutoConfiguration,\
cn.iocoder.yudao.framework.tenant.config.YudaoTenantMQAutoConfiguration