简化本地缓存的实现,萌新更容易看懂!
parent
0763c720d2
commit
c744e115e3
|
@ -81,22 +81,19 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 逐条插入,适合少量数据插入,或者对性能要求不高的场景
|
* 批量插入,适合大量数据插入
|
||||||
* <p>
|
|
||||||
* 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
|
|
||||||
* 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
|
|
||||||
*
|
*
|
||||||
* @param entities 实体们
|
* @param entities 实体们
|
||||||
*/
|
*/
|
||||||
default void insertBatch(Collection<T> entities) {
|
default void insertBatch(Collection<T> entities) {
|
||||||
entities.forEach(this::insert);
|
Db.saveBatch(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量插入,适合大量数据插入
|
* 批量插入,适合大量数据插入
|
||||||
*
|
*
|
||||||
* @param entities 实体们
|
* @param entities 实体们
|
||||||
* @param size 插入数量 Db.saveBatch 默认为1000
|
* @param size 插入数量 Db.saveBatch 默认为 1000
|
||||||
*/
|
*/
|
||||||
default void insertBatch(Collection<T> entities, int size) {
|
default void insertBatch(Collection<T> entities, int size) {
|
||||||
Db.saveBatch(entities, size);
|
Db.saveBatch(entities, size);
|
||||||
|
|
|
@ -6,15 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
|
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
|
||||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件配置 Mapper
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
|
public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
|
||||||
|
|
||||||
|
@ -26,7 +18,4 @@ public interface FileConfigMapper extends BaseMapperX<FileConfigDO> {
|
||||||
.orderByDesc(FileConfigDO::getId));
|
.orderByDesc(FileConfigDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM infra_file_config WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class FileConfigRefreshConsumer extends AbstractChannelMessageListener<Fi
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(FileConfigRefreshMessage message) {
|
public void onMessage(FileConfigRefreshMessage message) {
|
||||||
log.info("[onMessage][收到 FileConfig 刷新消息]");
|
log.info("[onMessage][收到 FileConfig 刷新消息]");
|
||||||
fileConfigService.initFileClients();
|
fileConfigService.initLocalCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public interface FileConfigService {
|
||||||
/**
|
/**
|
||||||
* 初始化文件客户端
|
* 初始化文件客户端
|
||||||
*/
|
*/
|
||||||
void initFileClients();
|
void initLocalCache();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建文件配置
|
* 创建文件配置
|
||||||
|
|
|
@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.service.file;
|
||||||
import cn.hutool.core.io.resource.ResourceUtil;
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||||
import cn.iocoder.yudao.framework.file.core.client.FileClient;
|
import cn.iocoder.yudao.framework.file.core.client.FileClient;
|
||||||
|
@ -19,7 +18,6 @@ import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
|
||||||
import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer;
|
import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
|
@ -29,7 +27,6 @@ import org.springframework.validation.annotation.Validated;
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.validation.Validator;
|
import javax.validation.Validator;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -48,18 +45,6 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class FileConfigServiceImpl implements FileConfigService {
|
public class FileConfigServiceImpl implements FileConfigService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private FileClientFactory fileClientFactory;
|
private FileClientFactory fileClientFactory;
|
||||||
/**
|
/**
|
||||||
|
@ -79,34 +64,12 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initFileClients() {
|
public void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
// 第一步:查询数据
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<FileConfigDO> configs = fileConfigMapper.selectList();
|
List<FileConfigDO> configs = fileConfigMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存文件配置,数量为:{}]", configs.size());
|
log.info("[initLocalCache][缓存文件配置,数量为:{}]", configs.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。创建或更新文件 Client
|
// 第二步:构建缓存:创建或更新文件 Client
|
||||||
configs.forEach(config -> {
|
configs.forEach(config -> {
|
||||||
fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
|
fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig());
|
||||||
// 如果是 master,进行设置
|
// 如果是 master,进行设置
|
||||||
|
@ -114,9 +77,6 @@ public class FileConfigServiceImpl implements FileConfigService {
|
||||||
masterFileClient = fileClientFactory.getFileClient(config.getId());
|
masterFileClient = fileClientFactory.getFileClient(config.getId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,7 +30,6 @@ import java.util.Map;
|
||||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||||
|
@ -74,16 +73,13 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
|
||||||
when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient);
|
when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
fileConfigService.initFileClients();
|
fileConfigService.initLocalCache();
|
||||||
// 断言 fileClientFactory 调用
|
// 断言 fileClientFactory 调用
|
||||||
verify(fileClientFactory).createOrUpdateFileClient(eq(1L),
|
verify(fileClientFactory).createOrUpdateFileClient(eq(1L),
|
||||||
eq(configDO1.getStorage()), eq(configDO1.getConfig()));
|
eq(configDO1.getStorage()), eq(configDO1.getConfig()));
|
||||||
verify(fileClientFactory).createOrUpdateFileClient(eq(2L),
|
verify(fileClientFactory).createOrUpdateFileClient(eq(2L),
|
||||||
eq(configDO2.getStorage()), eq(configDO2.getConfig()));
|
eq(configDO2.getStorage()), eq(configDO2.getConfig()));
|
||||||
assertSame(masterFileClient, fileConfigService.getMasterFileClient());
|
assertSame(masterFileClient, fileConfigService.getMasterFileClient());
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
assertEquals(max(configDO1.getUpdateTime(), configDO2.getUpdateTime()),
|
|
||||||
fileConfigService.getMaxUpdateTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -8,9 +8,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChann
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO;
|
import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -21,9 +19,6 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
|
||||||
return selectOne(PayChannelDO::getAppId, appId, PayChannelDO::getCode, code);
|
return selectOne(PayChannelDO::getAppId, appId, PayChannelDO::getCode, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM pay_channel WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) {
|
default PageResult<PayChannelDO> selectPage(PayChannelPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new QueryWrapperX<PayChannelDO>()
|
return selectPage(reqVO, new QueryWrapperX<PayChannelDO>()
|
||||||
.eqIfPresent("code", reqVO.getCode())
|
.eqIfPresent("code", reqVO.getCode())
|
||||||
|
@ -67,14 +62,14 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
|
||||||
* 根据条件获取渠道
|
* 根据条件获取渠道
|
||||||
*
|
*
|
||||||
* @param merchantId 商户编号
|
* @param merchantId 商户编号
|
||||||
* @param appid 应用编号 // TODO @aquan:appid =》appId
|
* @param appI 应用编号
|
||||||
* @param code 渠道编码
|
* @param code 渠道编码
|
||||||
* @return 数量
|
* @return 数量
|
||||||
*/
|
*/
|
||||||
default PayChannelDO selectOne(Long merchantId, Long appid, String code) {
|
default PayChannelDO selectOne(Long merchantId, Long appI, String code) {
|
||||||
return this.selectOne((new QueryWrapper<PayChannelDO>().lambda()
|
return this.selectOne((new QueryWrapper<PayChannelDO>().lambda()
|
||||||
.eq(PayChannelDO::getMerchantId, merchantId)
|
.eq(PayChannelDO::getMerchantId, merchantId)
|
||||||
.eq(PayChannelDO::getAppId, appid)
|
.eq(PayChannelDO::getAppId, appI)
|
||||||
.eq(PayChannelDO::getCode, code)
|
.eq(PayChannelDO::getCode, code)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import cn.hutool.json.JSONUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||||
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
|
||||||
|
@ -19,7 +18,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper;
|
import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper;
|
||||||
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
@ -44,12 +42,6 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_E
|
||||||
@Validated
|
@Validated
|
||||||
public class PayChannelServiceImpl implements PayChannelService {
|
public class PayChannelServiceImpl implements PayChannelService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
|
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
|
||||||
*/
|
*/
|
||||||
|
@ -70,40 +62,15 @@ public class PayChannelServiceImpl implements PayChannelService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 注意:忽略自动多租户,因为要全局初始化缓存
|
// 注意:忽略自动多租户,因为要全局初始化缓存
|
||||||
TenantUtils.executeIgnore(() -> {
|
TenantUtils.executeIgnore(() -> {
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
// 第一步:查询数据
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& channelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<PayChannelDO> channels = channelMapper.selectList();
|
List<PayChannelDO> channels = channelMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存支付渠道,数量为:{}]", channels.size());
|
log.info("[initLocalCache][缓存支付渠道,数量为:{}]", channels.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。创建或更新支付 Client
|
// 第二步:构建缓存:创建或更新支付 Client
|
||||||
channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(),
|
channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(),
|
||||||
payChannel.getCode(), payChannel.getConfig()));
|
payChannel.getCode(), payChannel.getConfig()));
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = CollectionUtils.getMaxValue(channels, PayChannelDO::getUpdateTime);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqV
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
|
@ -30,7 +28,4 @@ public interface DeptMapper extends BaseMapperX<DeptDO> {
|
||||||
return selectCount(DeptDO::getParentId, parentId);
|
return selectCount(DeptDO::getParentId, parentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_dept WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +27,4 @@ public interface OAuth2ClientMapper extends BaseMapperX<OAuth2ClientDO> {
|
||||||
return selectOne(OAuth2ClientDO::getClientId, clientId);
|
return selectOne(OAuth2ClientDO::getClientId, clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_oauth2_client WHERE update_time > #{maxUpdateTime}")
|
|
||||||
int selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuLi
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
|
@ -28,7 +26,4 @@ public interface MenuMapper extends BaseMapperX<MenuDO> {
|
||||||
.eqIfPresent(MenuDO::getStatus, reqVO.getStatus()));
|
.eqIfPresent(MenuDO::getStatus, reqVO.getStatus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_menu WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,8 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleEx
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -47,7 +45,4 @@ public interface RoleMapper extends BaseMapperX<RoleDO> {
|
||||||
return selectList(RoleDO::getStatus, statuses);
|
return selectList(RoleDO::getStatus, statuses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_role WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.system.dal.mysql.permission;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实体 {@link RoleMenuDO} 的批量插入 Mapper
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Repository
|
|
||||||
public class RoleMenuBatchInsertMapper extends ServiceImpl<RoleMenuMapper, RoleMenuDO> {
|
|
||||||
}
|
|
|
@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -20,23 +18,21 @@ public interface RoleMenuMapper extends BaseMapperX<RoleMenuDO> {
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<RoleMenuDO> selectListByRoleId(Long roleId) {
|
default List<RoleMenuDO> selectListByRoleId(Long roleId) {
|
||||||
return selectList(new QueryWrapper<RoleMenuDO>().eq("role_id", roleId));
|
return selectList(RoleMenuDO::getRoleId, roleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deleteListByRoleIdAndMenuIds(Long roleId, Collection<Long> menuIds) {
|
default void deleteListByRoleIdAndMenuIds(Long roleId, Collection<Long> menuIds) {
|
||||||
delete(new QueryWrapper<RoleMenuDO>().eq("role_id", roleId)
|
delete(new LambdaQueryWrapper<RoleMenuDO>()
|
||||||
.in("menu_id", menuIds));
|
.eq(RoleMenuDO::getRoleId, roleId)
|
||||||
|
.in(RoleMenuDO::getMenuId, menuIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deleteListByMenuId(Long menuId) {
|
default void deleteListByMenuId(Long menuId) {
|
||||||
delete(new QueryWrapper<RoleMenuDO>().eq("menu_id", menuId));
|
delete(new LambdaQueryWrapper<RoleMenuDO>().eq(RoleMenuDO::getMenuId, menuId));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deleteListByRoleId(Long roleId) {
|
default void deleteListByRoleId(Long roleId) {
|
||||||
delete(new QueryWrapper<RoleMenuDO>().eq("role_id", roleId));
|
delete(new LambdaQueryWrapper<RoleMenuDO>().eq(RoleMenuDO::getRoleId, roleId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_role_menu WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.system.dal.mysql.permission;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实体 {@link UserRoleDO} 的批量插入 Mapper
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Repository
|
|
||||||
public class UserRoleBatchInsertMapper extends ServiceImpl<UserRoleMapper, UserRoleDO> {
|
|
||||||
}
|
|
|
@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -14,32 +12,25 @@ import java.util.List;
|
||||||
public interface UserRoleMapper extends BaseMapperX<UserRoleDO> {
|
public interface UserRoleMapper extends BaseMapperX<UserRoleDO> {
|
||||||
|
|
||||||
default List<UserRoleDO> selectListByUserId(Long userId) {
|
default List<UserRoleDO> selectListByUserId(Long userId) {
|
||||||
return selectList(new QueryWrapper<UserRoleDO>().eq("user_id", userId));
|
return selectList(UserRoleDO::getUserId, userId);
|
||||||
}
|
|
||||||
|
|
||||||
default List<UserRoleDO> selectListByRoleId(Long roleId) {
|
|
||||||
return selectList(new QueryWrapper<UserRoleDO>().eq("role_id", roleId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deleteListByUserIdAndRoleIdIds(Long userId, Collection<Long> roleIds) {
|
default void deleteListByUserIdAndRoleIdIds(Long userId, Collection<Long> roleIds) {
|
||||||
delete(new QueryWrapper<UserRoleDO>().eq("user_id", userId)
|
delete(new LambdaQueryWrapper<UserRoleDO>()
|
||||||
.in("role_id", roleIds));
|
.eq(UserRoleDO::getUserId, userId)
|
||||||
|
.in(UserRoleDO::getRoleId, roleIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deleteListByUserId(Long userId) {
|
default void deleteListByUserId(Long userId) {
|
||||||
delete(new QueryWrapper<UserRoleDO>().eq("user_id", userId));
|
delete(new LambdaQueryWrapper<UserRoleDO>().eq(UserRoleDO::getUserId, userId));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void deleteListByRoleId(Long roleId) {
|
default void deleteListByRoleId(Long roleId) {
|
||||||
delete(new QueryWrapper<UserRoleDO>().eq("role_id", roleId));
|
delete(new LambdaQueryWrapper<UserRoleDO>().eq(UserRoleDO::getRoleId, roleId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default List<UserRoleDO> selectListByRoleIds(Collection<Long> roleIds) {
|
default List<UserRoleDO> selectListByRoleIds(Collection<Long> roleIds) {
|
||||||
return selectList(UserRoleDO::getRoleId, roleIds);
|
return selectList(UserRoleDO::getRoleId, roleIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_user_role WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,7 @@ import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.Sensitiv
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,7 +40,4 @@ public interface SensitiveWordMapper extends BaseMapperX<SensitiveWordDO> {
|
||||||
return selectOne(SensitiveWordDO::getName, name);
|
return selectOne(SensitiveWordDO::getName, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_sensitive_word WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
|
public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
|
||||||
|
@ -21,7 +18,4 @@ public interface SmsChannelMapper extends BaseMapperX<SmsChannelDO> {
|
||||||
.orderByDesc(SmsChannelDO::getId));
|
.orderByDesc(SmsChannelDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_sms_channel WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,12 @@ import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTempla
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface SmsTemplateMapper extends BaseMapperX<SmsTemplateDO> {
|
public interface SmsTemplateMapper extends BaseMapperX<SmsTemplateDO> {
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_sms_template WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
default SmsTemplateDO selectByCode(String code) {
|
default SmsTemplateDO selectByCode(String code) {
|
||||||
return selectOne(SmsTemplateDO::getCode, code);
|
return selectOne(SmsTemplateDO::getCode, code);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.system.dal.mysql.tenant;
|
package cn.iocoder.yudao.module.system.dal.mysql.tenant;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,7 +50,4 @@ public interface TenantMapper extends BaseMapperX<TenantDO> {
|
||||||
return selectList(TenantDO::getPackageId, packageId);
|
return selectList(TenantDO::getPackageId, packageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Select("SELECT COUNT(*) FROM system_tenant WHERE update_time > #{maxUpdateTime}")
|
|
||||||
Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -40,19 +41,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DeptServiceImpl implements DeptService {
|
public class DeptServiceImpl implements DeptService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门缓存
|
* 部门缓存
|
||||||
* key:部门编号 {@link DeptDO#getId()}
|
* key:部门编号 {@link DeptDO#getId()}
|
||||||
*
|
*
|
||||||
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("FieldCanBeLocal")
|
@Getter
|
||||||
private volatile Map<Long, DeptDO> deptCache;
|
private volatile Map<Long, DeptDO> deptCache;
|
||||||
/**
|
/**
|
||||||
* 父部门缓存
|
* 父部门缓存
|
||||||
|
@ -61,11 +56,8 @@ public class DeptServiceImpl implements DeptService {
|
||||||
*
|
*
|
||||||
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
||||||
*/
|
*/
|
||||||
|
@Getter
|
||||||
private volatile Multimap<Long, DeptDO> parentDeptCache;
|
private volatile Multimap<Long, DeptDO> parentDeptCache;
|
||||||
/**
|
|
||||||
* 缓存部门的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DeptMapper deptMapper;
|
private DeptMapper deptMapper;
|
||||||
|
@ -79,48 +71,21 @@ public class DeptServiceImpl implements DeptService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public synchronized void initLocalCache() {
|
public synchronized void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 注意:忽略自动多租户,因为要全局初始化缓存
|
// 注意:忽略自动多租户,因为要全局初始化缓存
|
||||||
TenantUtils.executeIgnore(() -> {
|
TenantUtils.executeIgnore(() -> {
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
// 第一步:查询数据
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& deptMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<DeptDO> depts = deptMapper.selectList();
|
List<DeptDO> depts = deptMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存部门,数量为:{}]", depts.size());
|
log.info("[initLocalCache][缓存部门,数量为:{}]", depts.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。创建或更新支付 Client
|
// 第二步:构建缓存
|
||||||
// 构建缓存
|
|
||||||
ImmutableMap.Builder<Long, DeptDO> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<Long, DeptDO> builder = ImmutableMap.builder();
|
||||||
ImmutableMultimap.Builder<Long, DeptDO> parentBuilder = ImmutableMultimap.builder();
|
ImmutableMultimap.Builder<Long, DeptDO> parentBuilder = ImmutableMultimap.builder();
|
||||||
depts.forEach(sysRoleDO -> {
|
depts.forEach(sysRoleDO -> {
|
||||||
builder.put(sysRoleDO.getId(), sysRoleDO);
|
builder.put(sysRoleDO.getId(), sysRoleDO);
|
||||||
parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO);
|
parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO);
|
||||||
});
|
});
|
||||||
// 设置缓存
|
|
||||||
deptCache = builder.build();
|
deptCache = builder.build();
|
||||||
parentDeptCache = parentBuilder.build();
|
parentDeptCache = parentBuilder.build();
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = CollectionUtils.getMaxValue(depts, DeptDO::getUpdateTime);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,20 +17,17 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
|
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,12 +40,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端缓存
|
* 客户端缓存
|
||||||
* key:客户端编号 {@link OAuth2ClientDO#getClientId()} ()}
|
* key:客户端编号 {@link OAuth2ClientDO#getClientId()} ()}
|
||||||
|
@ -58,11 +49,6 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
||||||
@Getter // 解决单测
|
@Getter // 解决单测
|
||||||
@Setter // 解决单测
|
@Setter // 解决单测
|
||||||
private volatile Map<String, OAuth2ClientDO> clientCache;
|
private volatile Map<String, OAuth2ClientDO> clientCache;
|
||||||
/**
|
|
||||||
* 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private OAuth2ClientMapper oauth2ClientMapper;
|
private OAuth2ClientMapper oauth2ClientMapper;
|
||||||
|
@ -76,37 +62,12 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
// 第一步:查询数据
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& oauth2ClientMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<OAuth2ClientDO> clients = oauth2ClientMapper.selectList();
|
List<OAuth2ClientDO> clients = oauth2ClientMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存 OAuth2 客户端,数量为:{}]", clients.size());
|
log.info("[initLocalCache][缓存 OAuth2 客户端,数量为:{}]", clients.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。
|
// 第二步:构建缓存。
|
||||||
clientCache = convertMap(clients, OAuth2ClientDO::getClientId);
|
clientCache = convertMap(clients, OAuth2ClientDO::getClientId);
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = getMaxValue(clients, OAuth2ClientDO::getUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,9 +18,9 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
|
@ -28,7 +28,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -43,18 +42,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class MenuServiceImpl implements MenuService {
|
public class MenuServiceImpl implements MenuService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 菜单缓存
|
* 菜单缓存
|
||||||
* key:菜单编号
|
* key:菜单编号
|
||||||
*
|
*
|
||||||
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
||||||
*/
|
*/
|
||||||
|
@Getter
|
||||||
private volatile Map<Long, MenuDO> menuCache;
|
private volatile Map<Long, MenuDO> menuCache;
|
||||||
/**
|
/**
|
||||||
* 权限与菜单缓存
|
* 权限与菜单缓存
|
||||||
|
@ -63,11 +57,8 @@ public class MenuServiceImpl implements MenuService {
|
||||||
*
|
*
|
||||||
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
||||||
*/
|
*/
|
||||||
|
@Getter
|
||||||
private volatile Multimap<String, MenuDO> permissionMenuCache;
|
private volatile Multimap<String, MenuDO> permissionMenuCache;
|
||||||
/**
|
|
||||||
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private MenuMapper menuMapper;
|
private MenuMapper menuMapper;
|
||||||
|
@ -86,33 +77,11 @@ public class MenuServiceImpl implements MenuService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public synchronized void initLocalCache() {
|
public synchronized void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
// 第一步:查询数据
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& menuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<MenuDO> menuList = menuMapper.selectList();
|
List<MenuDO> menuList = menuMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存菜单,数量为:{}]", menuList.size());
|
log.info("[initLocalCache][缓存菜单,数量为:{}]", menuList.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。
|
// 第二步:构建缓存
|
||||||
ImmutableMap.Builder<Long, MenuDO> menuCacheBuilder = ImmutableMap.builder();
|
ImmutableMap.Builder<Long, MenuDO> menuCacheBuilder = ImmutableMap.builder();
|
||||||
ImmutableMultimap.Builder<String, MenuDO> permMenuCacheBuilder = ImmutableMultimap.builder();
|
ImmutableMultimap.Builder<String, MenuDO> permMenuCacheBuilder = ImmutableMultimap.builder();
|
||||||
menuList.forEach(menuDO -> {
|
menuList.forEach(menuDO -> {
|
||||||
|
@ -123,9 +92,6 @@ public class MenuServiceImpl implements MenuService {
|
||||||
});
|
});
|
||||||
menuCache = menuCacheBuilder.build();
|
menuCache = menuCacheBuilder.build();
|
||||||
permissionMenuCache = permMenuCacheBuilder.build();
|
permissionMenuCache = permMenuCacheBuilder.build();
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = CollectionUtils.getMaxValue(menuList, MenuDO::getUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,9 +16,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuBatchInsertMapper;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleBatchInsertMapper;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
|
||||||
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
|
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
|
||||||
import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
|
import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
|
||||||
|
@ -32,7 +30,6 @@ import com.google.common.collect.Sets;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
|
@ -40,12 +37,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
|
|
||||||
import static java.util.Collections.singleton;
|
import static java.util.Collections.singleton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,12 +52,6 @@ import static java.util.Collections.singleton;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class PermissionServiceImpl implements PermissionService {
|
public class PermissionServiceImpl implements PermissionService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色编号与菜单编号的缓存映射
|
* 角色编号与菜单编号的缓存映射
|
||||||
* key:角色编号
|
* key:角色编号
|
||||||
|
@ -83,11 +72,6 @@ public class PermissionServiceImpl implements PermissionService {
|
||||||
@Getter
|
@Getter
|
||||||
@Setter // 单元测试需要
|
@Setter // 单元测试需要
|
||||||
private volatile Multimap<Long, Long> menuRoleCache;
|
private volatile Multimap<Long, Long> menuRoleCache;
|
||||||
/**
|
|
||||||
* 缓存 RoleMenu 的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private volatile LocalDateTime roleMenuMaxUpdateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户编号与角色编号的缓存映射
|
* 用户编号与角色编号的缓存映射
|
||||||
|
@ -99,20 +83,11 @@ public class PermissionServiceImpl implements PermissionService {
|
||||||
@Getter
|
@Getter
|
||||||
@Setter // 单元测试需要
|
@Setter // 单元测试需要
|
||||||
private volatile Map<Long, Set<Long>> userRoleCache;
|
private volatile Map<Long, Set<Long>> userRoleCache;
|
||||||
/**
|
|
||||||
* 缓存 UserRole 的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private volatile LocalDateTime userRoleMaxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RoleMenuMapper roleMenuMapper;
|
private RoleMenuMapper roleMenuMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private RoleMenuBatchInsertMapper roleMenuBatchInsertMapper;
|
|
||||||
@Resource
|
|
||||||
private UserRoleMapper userRoleMapper;
|
private UserRoleMapper userRoleMapper;
|
||||||
@Resource
|
|
||||||
private UserRoleBatchInsertMapper userRoleBatchInsertMapper;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private RoleService roleService;
|
private RoleService roleService;
|
||||||
|
@ -129,38 +104,22 @@ public class PermissionServiceImpl implements PermissionService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
initLocalCacheIfUpdateForRoleMenu(null);
|
initLocalCacheForRoleMenu();
|
||||||
initLocalCacheIfUpdateForUserRole(null);
|
initLocalCacheForUserRole();
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdateForRoleMenu(this.roleMenuMaxUpdateTime);
|
|
||||||
initLocalCacheIfUpdateForUserRole(this.userRoleMaxUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新 RoleMenu 本地缓存
|
* 刷新 RoleMenu 本地缓存
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void initLocalCacheIfUpdateForRoleMenu(LocalDateTime maxUpdateTime) {
|
void initLocalCacheForRoleMenu() {
|
||||||
// 注意:忽略自动多租户,因为要全局初始化缓存
|
// 注意:忽略自动多租户,因为要全局初始化缓存
|
||||||
TenantUtils.executeIgnore(() -> {
|
TenantUtils.executeIgnore(() -> {
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
// 第一步:查询数据
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& roleMenuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdateForRoleMenu][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<RoleMenuDO> roleMenus = roleMenuMapper.selectList();
|
List<RoleMenuDO> roleMenus = roleMenuMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdateForRoleMenu][缓存角色与菜单,数量为:{}]", roleMenus.size());
|
log.info("[initLocalCacheForRoleMenu][缓存角色与菜单,数量为:{}]", roleMenus.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。
|
// 第二步:构建缓存
|
||||||
ImmutableMultimap.Builder<Long, Long> roleMenuCacheBuilder = ImmutableMultimap.builder();
|
ImmutableMultimap.Builder<Long, Long> roleMenuCacheBuilder = ImmutableMultimap.builder();
|
||||||
ImmutableMultimap.Builder<Long, Long> menuRoleCacheBuilder = ImmutableMultimap.builder();
|
ImmutableMultimap.Builder<Long, Long> menuRoleCacheBuilder = ImmutableMultimap.builder();
|
||||||
roleMenus.forEach(roleMenuDO -> {
|
roleMenus.forEach(roleMenuDO -> {
|
||||||
|
@ -169,40 +128,24 @@ public class PermissionServiceImpl implements PermissionService {
|
||||||
});
|
});
|
||||||
roleMenuCache = roleMenuCacheBuilder.build();
|
roleMenuCache = roleMenuCacheBuilder.build();
|
||||||
menuRoleCache = menuRoleCacheBuilder.build();
|
menuRoleCache = menuRoleCacheBuilder.build();
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.roleMenuMaxUpdateTime = getMaxValue(roleMenus, RoleMenuDO::getUpdateTime);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新 UserRole 本地缓存
|
* 刷新 UserRole 本地缓存
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void initLocalCacheIfUpdateForUserRole(LocalDateTime maxUpdateTime) {
|
void initLocalCacheForUserRole() {
|
||||||
// 注意:忽略自动多租户,因为要全局初始化缓存
|
// 注意:忽略自动多租户,因为要全局初始化缓存
|
||||||
TenantUtils.executeIgnore(() -> {
|
TenantUtils.executeIgnore(() -> {
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
// 第一步:加载数据
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& userRoleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdateForUserRole][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<UserRoleDO> userRoles = userRoleMapper.selectList();
|
List<UserRoleDO> userRoles = userRoleMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdateForUserRole][缓存用户与角色,数量为:{}]", userRoles.size());
|
log.info("[initLocalCacheForUserRole][缓存用户与角色,数量为:{}]", userRoles.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。
|
// 第二步:构建缓存。
|
||||||
ImmutableMultimap.Builder<Long, Long> userRoleCacheBuilder = ImmutableMultimap.builder();
|
ImmutableMultimap.Builder<Long, Long> userRoleCacheBuilder = ImmutableMultimap.builder();
|
||||||
userRoles.forEach(userRoleDO -> userRoleCacheBuilder.put(userRoleDO.getUserId(), userRoleDO.getRoleId()));
|
userRoles.forEach(userRoleDO -> userRoleCacheBuilder.put(userRoleDO.getUserId(), userRoleDO.getRoleId()));
|
||||||
userRoleCache = CollectionUtils.convertMultiMap2(userRoles, UserRoleDO::getUserId, UserRoleDO::getRoleId);
|
userRoleCache = CollectionUtils.convertMultiMap2(userRoles, UserRoleDO::getUserId, UserRoleDO::getRoleId);
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.userRoleMaxUpdateTime = getMaxValue(userRoles, UserRoleDO::getUpdateTime);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +207,7 @@ public class PermissionServiceImpl implements PermissionService {
|
||||||
Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds);
|
Collection<Long> deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds);
|
||||||
// 执行新增和删除。对于已经授权的菜单,不用做任何处理
|
// 执行新增和删除。对于已经授权的菜单,不用做任何处理
|
||||||
if (!CollectionUtil.isEmpty(createMenuIds)) {
|
if (!CollectionUtil.isEmpty(createMenuIds)) {
|
||||||
roleMenuBatchInsertMapper.saveBatch(CollectionUtils.convertList(createMenuIds, menuId -> {
|
roleMenuMapper.insertBatch(CollectionUtils.convertList(createMenuIds, menuId -> {
|
||||||
RoleMenuDO entity = new RoleMenuDO();
|
RoleMenuDO entity = new RoleMenuDO();
|
||||||
entity.setRoleId(roleId);
|
entity.setRoleId(roleId);
|
||||||
entity.setMenuId(menuId);
|
entity.setMenuId(menuId);
|
||||||
|
@ -308,7 +251,7 @@ public class PermissionServiceImpl implements PermissionService {
|
||||||
Collection<Long> deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIds);
|
Collection<Long> deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIds);
|
||||||
// 执行新增和删除。对于已经授权的角色,不用做任何处理
|
// 执行新增和删除。对于已经授权的角色,不用做任何处理
|
||||||
if (!CollectionUtil.isEmpty(createRoleIds)) {
|
if (!CollectionUtil.isEmpty(createRoleIds)) {
|
||||||
userRoleBatchInsertMapper.saveBatch(CollectionUtils.convertList(createRoleIds, roleId -> {
|
userRoleMapper.insertBatch(CollectionUtils.convertList(createRoleIds, roleId -> {
|
||||||
UserRoleDO entity = new UserRoleDO();
|
UserRoleDO entity = new UserRoleDO();
|
||||||
entity.setUserId(userId);
|
entity.setUserId(userId);
|
||||||
entity.setRoleId(roleId);
|
entity.setRoleId(roleId);
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionSynchronization;
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
|
@ -31,7 +30,6 @@ import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -47,12 +45,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class RoleServiceImpl implements RoleService {
|
public class RoleServiceImpl implements RoleService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 角色缓存
|
* 角色缓存
|
||||||
* key:角色编号 {@link RoleDO#getId()}
|
* key:角色编号 {@link RoleDO#getId()}
|
||||||
|
@ -61,11 +53,6 @@ public class RoleServiceImpl implements RoleService {
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private volatile Map<Long, RoleDO> roleCache;
|
private volatile Map<Long, RoleDO> roleCache;
|
||||||
/**
|
|
||||||
* 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
@ -82,39 +69,14 @@ public class RoleServiceImpl implements RoleService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 注意:忽略自动多租户,因为要全局初始化缓存
|
// 注意:忽略自动多租户,因为要全局初始化缓存
|
||||||
TenantUtils.executeIgnore(() -> {
|
TenantUtils.executeIgnore(() -> {
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
// 第一步:查询数据
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& roleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<RoleDO> roleList = roleMapper.selectList();
|
List<RoleDO> roleList = roleMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存角色,数量为:{}]", roleList.size());
|
log.info("[initLocalCache][缓存角色,数量为:{}]", roleList.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。
|
// 第二步:构建缓存
|
||||||
roleCache = CollectionUtils.convertMap(roleList, RoleDO::getId);
|
roleCache = CollectionUtils.convertMap(roleList, RoleDO::getId);
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = CollectionUtils.getMaxValue(roleList, RoleDO::getUpdateTime);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,11 @@ import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
@ -40,12 +38,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SENSITIVE_
|
||||||
@Validated
|
@Validated
|
||||||
public class SensitiveWordServiceImpl implements SensitiveWordService {
|
public class SensitiveWordServiceImpl implements SensitiveWordService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 敏感词标签缓存
|
* 敏感词标签缓存
|
||||||
* key:敏感词编号 {@link SensitiveWordDO#getId()}
|
* key:敏感词编号 {@link SensitiveWordDO#getId()}
|
||||||
|
@ -55,12 +47,6 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
|
||||||
@Getter
|
@Getter
|
||||||
private volatile Set<String> sensitiveWordTagsCache = Collections.emptySet();
|
private volatile Set<String> sensitiveWordTagsCache = Collections.emptySet();
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存敏感词的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SensitiveWordMapper sensitiveWordMapper;
|
private SensitiveWordMapper sensitiveWordMapper;
|
||||||
|
|
||||||
|
@ -84,42 +70,17 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
// 第一步:查询数据
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& sensitiveWordMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<SensitiveWordDO> sensitiveWords = sensitiveWordMapper.selectList();
|
List<SensitiveWordDO> sensitiveWords = sensitiveWordMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存敏感词,数量为:{}]", sensitiveWords.size());
|
log.info("[initLocalCache][缓存敏感词,数量为:{}]", sensitiveWords.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。
|
// 第二步:构建缓存
|
||||||
// 写入 sensitiveWordTagsCache 缓存
|
// 写入 sensitiveWordTagsCache 缓存
|
||||||
Set<String> tags = new HashSet<>();
|
Set<String> tags = new HashSet<>();
|
||||||
sensitiveWords.forEach(word -> tags.addAll(word.getTags()));
|
sensitiveWords.forEach(word -> tags.addAll(word.getTags()));
|
||||||
sensitiveWordTagsCache = tags;
|
sensitiveWordTagsCache = tags;
|
||||||
// 写入 defaultSensitiveWordTrie、tagSensitiveWordTries 缓存
|
// 写入 defaultSensitiveWordTrie、tagSensitiveWordTries 缓存
|
||||||
initSensitiveWordTrie(sensitiveWords);
|
initSensitiveWordTrie(sensitiveWords);
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = CollectionUtils.getMaxValue(sensitiveWords, SensitiveWordDO::getUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSensitiveWordTrie(List<SensitiveWordDO> wordDOs) {
|
private void initSensitiveWordTrie(List<SensitiveWordDO> wordDOs) {
|
||||||
|
|
|
@ -11,17 +11,14 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper;
|
||||||
import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer;
|
import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
|
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS;
|
||||||
|
|
||||||
|
@ -34,17 +31,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNE
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SmsChannelServiceImpl implements SmsChannelService {
|
public class SmsChannelServiceImpl implements SmsChannelService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SmsClientFactory smsClientFactory;
|
private SmsClientFactory smsClientFactory;
|
||||||
|
|
||||||
|
@ -60,38 +46,13 @@ public class SmsChannelServiceImpl implements SmsChannelService {
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
initLocalCacheIfUpdate(null);
|
// 第一步:查询数据
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCacheIfUpdate(this.maxUpdateTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 刷新本地缓存
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 最大更新时间
|
|
||||||
* 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存
|
|
||||||
* 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存
|
|
||||||
*/
|
|
||||||
private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 第一步:基于 maxUpdateTime 判断缓存是否刷新。
|
|
||||||
// 如果没有增量的数据变化,则不进行本地缓存的刷新
|
|
||||||
if (maxUpdateTime != null
|
|
||||||
&& smsChannelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<SmsChannelDO> channels = smsChannelMapper.selectList();
|
List<SmsChannelDO> channels = smsChannelMapper.selectList();
|
||||||
log.info("[initLocalCacheIfUpdate][缓存短信渠道,数量为:{}]", channels.size());
|
log.info("[initLocalCache][缓存短信渠道,数量为:{}]", channels.size());
|
||||||
|
|
||||||
// 第二步:构建缓存。创建或更新短信 Client
|
// 第二步:构建缓存:创建或更新短信 Client
|
||||||
List<SmsChannelProperties> propertiesList = SmsChannelConvert.INSTANCE.convertList02(channels);
|
List<SmsChannelProperties> propertiesList = SmsChannelConvert.INSTANCE.convertList02(channels);
|
||||||
propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties));
|
propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties));
|
||||||
|
|
||||||
// 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。
|
|
||||||
this.maxUpdateTime = getMaxValue(channels, SmsChannelDO::getUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package cn.iocoder.yudao.module.system.service.sms;
|
package cn.iocoder.yudao.module.system.service.sms;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.util.ReUtil;
|
import cn.hutool.core.util.ReUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
|
@ -20,15 +19,17 @@ import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper;
|
||||||
import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer;
|
import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Collection;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
@ -44,12 +45,6 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SmsTemplateServiceImpl implements SmsTemplateService {
|
public class SmsTemplateServiceImpl implements SmsTemplateService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 定时执行 {@link #schedulePeriodicRefresh()} 的周期
|
|
||||||
* 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
|
|
||||||
*/
|
|
||||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 正则表达式,匹配 {} 中的变量
|
* 正则表达式,匹配 {} 中的变量
|
||||||
*/
|
*/
|
||||||
|
@ -73,51 +68,18 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
|
||||||
*
|
*
|
||||||
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
||||||
*/
|
*/
|
||||||
|
@Getter // 为了方便测试,这里提供 getter 方法
|
||||||
private volatile Map<String, SmsTemplateDO> smsTemplateCache;
|
private volatile Map<String, SmsTemplateDO> smsTemplateCache;
|
||||||
/**
|
|
||||||
* 缓存短信模板的最大更新时间,用于后续的增量轮询,判断是否有更新
|
|
||||||
*/
|
|
||||||
private volatile LocalDateTime maxUpdateTime;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
// 获取短信模板列表,如果有更新
|
// 第一步:查询数据
|
||||||
List<SmsTemplateDO> smsTemplateList = this.loadSmsTemplateIfUpdate(maxUpdateTime);
|
List<SmsTemplateDO> smsTemplateList = smsTemplateMapper.selectList();
|
||||||
if (CollUtil.isEmpty(smsTemplateList)) {
|
log.info("[initLocalCache][缓存短信模版,数量为:{}]", smsTemplateList.size());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入缓存
|
// 第二步:构建缓存
|
||||||
smsTemplateCache = CollectionUtils.convertMap(smsTemplateList, SmsTemplateDO::getCode);
|
smsTemplateCache = CollectionUtils.convertMap(smsTemplateList, SmsTemplateDO::getCode);
|
||||||
maxUpdateTime = CollectionUtils.getMaxValue(smsTemplateList, SmsTemplateDO::getUpdateTime);
|
|
||||||
log.info("[initLocalCache][初始化 SmsTemplate 数量为 {}]", smsTemplateList.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果短信模板发生变化,从数据库中获取最新的全量短信模板。
|
|
||||||
* 如果未发生变化,则返回空
|
|
||||||
*
|
|
||||||
* @param maxUpdateTime 当前短信模板的最大更新时间
|
|
||||||
* @return 短信模板列表
|
|
||||||
*/
|
|
||||||
private List<SmsTemplateDO> loadSmsTemplateIfUpdate(LocalDateTime maxUpdateTime) {
|
|
||||||
// 第一步,判断是否要更新。
|
|
||||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
|
||||||
log.info("[loadSmsTemplateIfUpdate][首次加载全量短信模板]");
|
|
||||||
} else { // 判断数据库中是否有更新的短信模板
|
|
||||||
if (smsTemplateMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
log.info("[loadSmsTemplateIfUpdate][增量加载全量短信模板]");
|
|
||||||
}
|
|
||||||
// 第二步,如果有更新,则从数据库加载所有短信模板
|
|
||||||
return smsTemplateMapper.selectList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
|
||||||
public void schedulePeriodicRefresh() {
|
|
||||||
initLocalCache();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -5,8 +5,6 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
|
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
|
||||||
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
|
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
|
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
|
||||||
|
@ -16,7 +14,7 @@ import cn.iocoder.yudao.module.system.service.member.MemberService;
|
||||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
|
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
|
||||||
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
|
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
|
||||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||||
import com.anji.captcha.service.CaptchaService;
|
import com.xingyuv.captcha.service.CaptchaService;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
@ -25,7 +23,6 @@ import javax.annotation.Resource;
|
||||||
import javax.validation.Validator;
|
import javax.validation.Validator;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.system.service.dept;
|
package cn.iocoder.yudao.module.system.service.dept;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO;
|
||||||
|
@ -9,9 +12,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
|
||||||
import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;
|
import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum;
|
||||||
import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer;
|
import cn.iocoder.yudao.module.system.mq.producer.dept.DeptProducer;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -19,17 +19,15 @@ import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static cn.hutool.core.bean.BeanUtil.getFieldValue;
|
|
||||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
@ -56,8 +54,7 @@ public class DeptServiceTest extends BaseDbUnitTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
public void testInitLocalCache() {
|
||||||
void testInitLocalCache() {
|
|
||||||
// mock 数据
|
// mock 数据
|
||||||
DeptDO deptDO1 = randomDeptDO();
|
DeptDO deptDO1 = randomDeptDO();
|
||||||
deptMapper.insert(deptDO1);
|
deptMapper.insert(deptDO1);
|
||||||
|
@ -67,18 +64,15 @@ public class DeptServiceTest extends BaseDbUnitTest {
|
||||||
// 调用
|
// 调用
|
||||||
deptService.initLocalCache();
|
deptService.initLocalCache();
|
||||||
// 断言 deptCache 缓存
|
// 断言 deptCache 缓存
|
||||||
Map<Long, DeptDO> deptCache = (Map<Long, DeptDO>) getFieldValue(deptService, "deptCache");
|
Map<Long, DeptDO> deptCache = deptService.getDeptCache();
|
||||||
assertEquals(2, deptCache.size());
|
assertEquals(2, deptCache.size());
|
||||||
assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId()));
|
assertPojoEquals(deptDO1, deptCache.get(deptDO1.getId()));
|
||||||
assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId()));
|
assertPojoEquals(deptDO2, deptCache.get(deptDO2.getId()));
|
||||||
// 断言 parentDeptCache 缓存
|
// 断言 parentDeptCache 缓存
|
||||||
Multimap<Long, DeptDO> parentDeptCache = (Multimap<Long, DeptDO>) getFieldValue(deptService, "parentDeptCache");
|
Multimap<Long, DeptDO> parentDeptCache = deptService.getParentDeptCache();
|
||||||
assertEquals(2, parentDeptCache.size());
|
assertEquals(2, parentDeptCache.size());
|
||||||
assertPojoEquals(deptDO1, parentDeptCache.get(deptDO1.getParentId()));
|
assertPojoEquals(deptDO1, parentDeptCache.get(deptDO1.getParentId()));
|
||||||
assertPojoEquals(deptDO2, parentDeptCache.get(deptDO2.getParentId()));
|
assertPojoEquals(deptDO2, parentDeptCache.get(deptDO2.getParentId()));
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
LocalDateTime maxUpdateTime = (LocalDateTime) getFieldValue(deptService, "maxUpdateTime");
|
|
||||||
assertEquals(ObjectUtils.max(deptDO1.getUpdateTime(), deptDO2.getUpdateTime()), maxUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
|
@ -59,8 +58,6 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest {
|
||||||
assertEquals(2, clientCache.size());
|
assertEquals(2, clientCache.size());
|
||||||
assertPojoEquals(clientDO1, clientCache.get(clientDO1.getClientId()));
|
assertPojoEquals(clientDO1, clientCache.get(clientDO1.getClientId()));
|
||||||
assertPojoEquals(clientDO2, clientCache.get(clientDO2.getClientId()));
|
assertPojoEquals(clientDO2, clientCache.get(clientDO2.getClientId()));
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
assertEquals(max(clientDO1.getUpdateTime(), clientDO2.getUpdateTime()), oauth2ClientService.getMaxUpdateTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.permission;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.spring.SpringAopUtils;
|
import cn.iocoder.yudao.framework.common.util.spring.SpringAopUtils;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO;
|
||||||
|
@ -20,7 +19,6 @@ import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||||
|
@ -51,32 +49,24 @@ public class MenuServiceTest extends BaseDbUnitTest {
|
||||||
private TenantService tenantService;
|
private TenantService tenantService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitLocalCache_success() throws Exception {
|
public void testInitLocalCache_success() {
|
||||||
MenuDO menuDO1 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L);
|
MenuDO menuDO1 = randomPojo(MenuDO.class);
|
||||||
menuMapper.insert(menuDO1);
|
menuMapper.insert(menuDO1);
|
||||||
MenuDO menuDO2 = createMenuDO(MenuTypeEnum.MENU, "xxxx", 0L);
|
MenuDO menuDO2 = randomPojo(MenuDO.class);
|
||||||
menuMapper.insert(menuDO2);
|
menuMapper.insert(menuDO2);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
menuService.initLocalCache();
|
menuService.initLocalCache();
|
||||||
|
// 校验 menuCache 缓存
|
||||||
// 获取代理对象
|
Map<Long, MenuDO> menuCache = menuService.getMenuCache();
|
||||||
MenuServiceImpl target = (MenuServiceImpl) SpringAopUtils.getTarget(menuService);
|
|
||||||
|
|
||||||
Map<Long, MenuDO> menuCache =
|
|
||||||
(Map<Long, MenuDO>) BeanUtil.getFieldValue(target, "menuCache");
|
|
||||||
Assert.isTrue(menuCache.size() == 2);
|
Assert.isTrue(menuCache.size() == 2);
|
||||||
assertPojoEquals(menuDO1, menuCache.get(menuDO1.getId()));
|
assertPojoEquals(menuDO1, menuCache.get(menuDO1.getId()));
|
||||||
assertPojoEquals(menuDO2, menuCache.get(menuDO2.getId()));
|
assertPojoEquals(menuDO2, menuCache.get(menuDO2.getId()));
|
||||||
|
// 校验 permissionMenuCache 缓存
|
||||||
Multimap<String, MenuDO> permissionMenuCache =
|
Multimap<String, MenuDO> permissionMenuCache = menuService.getPermissionMenuCache();
|
||||||
(Multimap<String, MenuDO>) BeanUtil.getFieldValue(target, "permissionMenuCache");
|
|
||||||
Assert.isTrue(permissionMenuCache.size() == 2);
|
Assert.isTrue(permissionMenuCache.size() == 2);
|
||||||
assertPojoEquals(menuDO1, permissionMenuCache.get(menuDO1.getPermission()));
|
assertPojoEquals(menuDO1, permissionMenuCache.get(menuDO1.getPermission()));
|
||||||
assertPojoEquals(menuDO2, permissionMenuCache.get(menuDO2.getPermission()));
|
assertPojoEquals(menuDO2, permissionMenuCache.get(menuDO2.getPermission()));
|
||||||
|
|
||||||
LocalDateTime maxUpdateTime = (LocalDateTime) BeanUtil.getFieldValue(target, "maxUpdateTime");
|
|
||||||
assertEquals(ObjectUtils.max(menuDO1.getUpdateTime(), menuDO2.getUpdateTime()), maxUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -3,18 +3,15 @@ package cn.iocoder.yudao.module.system.service.permission;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
|
||||||
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
|
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
|
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuBatchInsertMapper;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleBatchInsertMapper;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
|
||||||
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
|
import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
|
||||||
import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
|
import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer;
|
||||||
|
@ -27,8 +24,10 @@ import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Collection;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
|
@ -42,8 +41,7 @@ import static org.mockito.ArgumentMatchers.same;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@Import({PermissionServiceImpl.class,
|
@Import({PermissionServiceImpl.class})
|
||||||
RoleMenuBatchInsertMapper.class, UserRoleBatchInsertMapper.class})
|
|
||||||
public class PermissionServiceTest extends BaseDbUnitTest {
|
public class PermissionServiceTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -52,11 +50,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
|
||||||
@Resource
|
@Resource
|
||||||
private RoleMenuMapper roleMenuMapper;
|
private RoleMenuMapper roleMenuMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private RoleMenuBatchInsertMapper roleMenuBatchInsertMapper;
|
|
||||||
@Resource
|
|
||||||
private UserRoleMapper userRoleMapper;
|
private UserRoleMapper userRoleMapper;
|
||||||
@Resource
|
|
||||||
private UserRoleBatchInsertMapper userRoleBatchInsertMapper;
|
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private RoleService roleService;
|
private RoleService roleService;
|
||||||
|
@ -71,7 +65,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
|
||||||
private PermissionProducer permissionProducer;
|
private PermissionProducer permissionProducer;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitLocalCacheIfUpdateForRoleMenu() {
|
public void testInitLocalCacheForRoleMenu() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(1L).setMenuId(10L));
|
RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(1L).setMenuId(10L));
|
||||||
roleMenuMapper.insert(roleMenuDO01);
|
roleMenuMapper.insert(roleMenuDO01);
|
||||||
|
@ -79,7 +73,7 @@ public class PermissionServiceTest extends BaseDbUnitTest {
|
||||||
roleMenuMapper.insert(roleMenuDO02);
|
roleMenuMapper.insert(roleMenuDO02);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
permissionService.initLocalCacheIfUpdateForRoleMenu(null);
|
permissionService.initLocalCacheForRoleMenu();
|
||||||
// 断言 roleMenuCache 缓存
|
// 断言 roleMenuCache 缓存
|
||||||
assertEquals(1, permissionService.getRoleMenuCache().keySet().size());
|
assertEquals(1, permissionService.getRoleMenuCache().keySet().size());
|
||||||
assertEquals(asList(10L, 20L), permissionService.getRoleMenuCache().get(1L));
|
assertEquals(asList(10L, 20L), permissionService.getRoleMenuCache().get(1L));
|
||||||
|
@ -87,13 +81,10 @@ public class PermissionServiceTest extends BaseDbUnitTest {
|
||||||
assertEquals(2, permissionService.getMenuRoleCache().size());
|
assertEquals(2, permissionService.getMenuRoleCache().size());
|
||||||
assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(10L));
|
assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(10L));
|
||||||
assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(20L));
|
assertEquals(singletonList(1L), permissionService.getMenuRoleCache().get(20L));
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
LocalDateTime maxUpdateTime = permissionService.getRoleMenuMaxUpdateTime();
|
|
||||||
assertEquals(ObjectUtils.max(roleMenuDO01.getUpdateTime(), roleMenuDO02.getUpdateTime()), maxUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInitLocalCacheIfUpdateForUserRole() {
|
public void testInitLocalCacheForUserRole() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
|
UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L));
|
||||||
userRoleMapper.insert(userRoleDO01);
|
userRoleMapper.insert(userRoleDO01);
|
||||||
|
@ -101,13 +92,10 @@ public class PermissionServiceTest extends BaseDbUnitTest {
|
||||||
userRoleMapper.insert(roleMenuDO02);
|
userRoleMapper.insert(roleMenuDO02);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
permissionService.initLocalCacheIfUpdateForUserRole(null);
|
permissionService.initLocalCacheForUserRole();
|
||||||
// 断言 roleMenuCache 缓存
|
// 断言 roleMenuCache 缓存
|
||||||
assertEquals(1, permissionService.getUserRoleCache().size());
|
assertEquals(1, permissionService.getUserRoleCache().size());
|
||||||
assertEquals(asSet(10L, 20L), permissionService.getUserRoleCache().get(1L));
|
assertEquals(asSet(10L, 20L), permissionService.getUserRoleCache().get(1L));
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
LocalDateTime maxUpdateTime = permissionService.getUserRoleMaxUpdateTime();
|
|
||||||
assertEquals(ObjectUtils.max(userRoleDO01.getUpdateTime(), roleMenuDO02.getUpdateTime()), maxUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
|
@ -59,8 +58,6 @@ public class RoleServiceTest extends BaseDbUnitTest {
|
||||||
Map<Long, RoleDO> roleCache = roleService.getRoleCache();
|
Map<Long, RoleDO> roleCache = roleService.getRoleCache();
|
||||||
assertPojoEquals(roleDO1, roleCache.get(roleDO1.getId()));
|
assertPojoEquals(roleDO1, roleCache.get(roleDO1.getId()));
|
||||||
assertPojoEquals(roleDO2, roleCache.get(roleDO2.getId()));
|
assertPojoEquals(roleDO2, roleCache.get(roleDO2.getId()));
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
assertEquals(max(roleDO1.getUpdateTime(), roleDO2.getUpdateTime()), roleService.getMaxUpdateTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -60,8 +60,6 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
sensitiveWordService.initLocalCache();
|
sensitiveWordService.initLocalCache();
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
assertEquals(max(wordDO1.getUpdateTime(), wordDO2.getUpdateTime()), sensitiveWordService.getMaxUpdateTime());
|
|
||||||
// 断言 sensitiveWordTagsCache 缓存
|
// 断言 sensitiveWordTagsCache 缓存
|
||||||
assertEquals(SetUtils.asSet("论坛", "蔬菜"), sensitiveWordService.getSensitiveWordTags());
|
assertEquals(SetUtils.asSet("论坛", "蔬菜"), sensitiveWordService.getSensitiveWordTags());
|
||||||
// 断言 tagSensitiveWordTries 缓存
|
// 断言 tagSensitiveWordTries 缓存
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
package cn.iocoder.yudao.module.system.service.sms;
|
package cn.iocoder.yudao.module.system.service.sms;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper;
|
|
||||||
import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory;
|
import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper;
|
||||||
|
import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
@ -22,12 +21,11 @@ import java.time.LocalDateTime;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
|
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS;
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN;
|
||||||
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
@ -58,9 +56,6 @@ public class SmsChannelServiceTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
smsChannelService.initLocalCache();
|
smsChannelService.initLocalCache();
|
||||||
// 校验 maxUpdateTime 属性
|
|
||||||
LocalDateTime maxUpdateTime = (LocalDateTime) BeanUtil.getFieldValue(smsChannelService, "maxUpdateTime");
|
|
||||||
assertEquals(max(smsChannelDO01.getUpdateTime(), smsChannelDO02.getUpdateTime()), maxUpdateTime);
|
|
||||||
// 校验调用
|
// 校验调用
|
||||||
verify(smsClientFactory, times(1)).createOrUpdateSmsClient(
|
verify(smsClientFactory, times(1)).createOrUpdateSmsClient(
|
||||||
argThat(properties -> isPojoEquals(smsChannelDO01, properties)));
|
argThat(properties -> isPojoEquals(smsChannelDO01, properties)));
|
||||||
|
|
|
@ -61,7 +61,6 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest {
|
||||||
private SmsProducer smsProducer;
|
private SmsProducer smsProducer;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
void testInitLocalCache() {
|
void testInitLocalCache() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
SmsTemplateDO smsTemplate01 = randomSmsTemplateDO();
|
SmsTemplateDO smsTemplate01 = randomSmsTemplateDO();
|
||||||
|
@ -72,13 +71,10 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest {
|
||||||
// 调用
|
// 调用
|
||||||
smsTemplateService.initLocalCache();
|
smsTemplateService.initLocalCache();
|
||||||
// 断言 deptCache 缓存
|
// 断言 deptCache 缓存
|
||||||
Map<String, SmsTemplateDO> smsTemplateCache = (Map<String, SmsTemplateDO>) getFieldValue(smsTemplateService, "smsTemplateCache");
|
Map<String, SmsTemplateDO> smsTemplateCache = smsTemplateService.getSmsTemplateCache();
|
||||||
assertEquals(2, smsTemplateCache.size());
|
assertEquals(2, smsTemplateCache.size());
|
||||||
assertPojoEquals(smsTemplate01, smsTemplateCache.get(smsTemplate01.getCode()));
|
assertPojoEquals(smsTemplate01, smsTemplateCache.get(smsTemplate01.getCode()));
|
||||||
assertPojoEquals(smsTemplate02, smsTemplateCache.get(smsTemplate02.getCode()));
|
assertPojoEquals(smsTemplate02, smsTemplateCache.get(smsTemplate02.getCode()));
|
||||||
// 断言 maxUpdateTime 缓存
|
|
||||||
LocalDateTime maxUpdateTime = (LocalDateTime) getFieldValue(smsTemplateService, "maxUpdateTime");
|
|
||||||
assertEquals(max(smsTemplate01.getUpdateTime(), smsTemplate02.getUpdateTime()), maxUpdateTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue