开发喵星球

RuoYi-Vue-Plus读取不到租户问题(333)

场景一:定时任务中的租户信息丢失

定时任务由于在执行时不携带任何租户上下文信息,因此在调用需要租户识别的功能时,往往会抛出租户读取异常。为避免这种情况,应该在相关任务上使用 @IgnoreTenant 注解来跳过租户检查。

@IgnoreTenant 注解的功能

public @interface IgnoreTenant {
    /**
     * 对事务生效,默认为开启
     */
    boolean db() default true;

    /**
     * 对缓存生效,与全局缓存一致
     * 全局缓存可通过{@link org.dromara.common.core.constant.GlobalConstants#GLOBAL_REDIS_KEY}或设置该参数为true
     */
    boolean cache() default false;
}

@IgnoreTenant 注解提供了两个主要功能:
1. db(): 控制是否对数据库事务生效。默认开启,即忽略租户限制。
2. cache(): 控制是否对缓存生效。如果开启,效果与全局缓存一致。

定时任务中使用示例

在定时任务中可以使用 @IgnoreTenant 来跳过租户上下文的注入:

@Component
public class BizJobs {

    /**
     * 每分钟执行任务
     */
    @IgnoreTenant
    @EventListener
    public void everyMinute(EveryMinuteJobEvent jobEvent) {
        // 业务逻辑
    }
}

注意事项

IgnoreTenant#cache 不建议开启,主要因为租户缓存与忽略租户缓存的机制并不相同。如果需要一致的缓存处理行为,建议使用全局缓存,而非简单忽略租户差异。

场景二:消息队列中的租户信息传递

在消息队列场景下,通常可以在发送消息时附带租户信息。为了确保消息消费端能正确处理租户,可以采用动态租户模式。以下是基于 ruoyi-common-amqp 依赖的实现方式。

发送端:携带租户信息的消息发送

使用 TenantMQMessage 类携带租户信息,通过 AmqpTransactionalTemplate 发送消息:

@Service
public class BizServiceImpl {
    @Autowired
    private AmqpTransactionalTemplate amqpTransactionalTemplate;

    @Transactional(rollbackFor = Exception.class)
    public void demo() {
        TenantMQMessage message = new TenantMQMessage();
        amqpTransactionalTemplate.convertAndSend(BizAmqpExchange.SEND_TEST, message).commit();
    }
}

在此场景下,TenantMQMessage 是包含租户信息的业务消息类。通过这种方式,租户信息可以随消息一起传递。

消费端:使用 @DynamicTenant 动态切换租户

消费端使用 @DynamicTenant 注解,通过 SpEL 表达式动态获取消息中的租户信息:

@Component
public class BizReceiver {

    @DynamicTenant(value = "#msg.tenantId")
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = BizAmqpExchange.SEND_TEST_QUEUE),
            exchange = @Exchange(value = BizAmqpExchange.SEND_TEST, type = ExchangeTypes.FANOUT)
    ))
    public void test(TenantMQMessage msg) {
        // 消费逻辑
    }
}

@DynamicTenant(value = "#msg.tenantId") 通过 SpEL 从消息对象中提取租户 ID,实现动态租户上下文的切换。

提示

在非 Web 环境中,需要将租户操作封装到 TenantHelper.ignore 中执行,或在相关方法上使用 @DynamicTenant 注解以确保正确读取租户信息。

通过在定时任务和消息队列场景中合理使用 @IgnoreTenant@DynamicTenant 注解,您可以轻松应对租户信息无法读取的问题,并确保系统多租户环境下的稳定性和一致性。

   
分类:Java/OOP 作者:无限繁荣, 吴蓉 发表于:2024-09-16 14:30:50 阅读量:102
<<   >>


powered by kaifamiao