Pārlūkot izejas kodu

缓存改造:NotifyTemplate 使用 Redis 作为缓存

YunaiV 2 gadi atpakaļ
vecāks
revīzija
d23d72c8bb

+ 8 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java

@@ -66,4 +66,12 @@ public interface RedisKeyConstants {
      */
     String OAUTH_CLIENT = "oauth_client";
 
+    /**
+     * 站内信模版的缓存
+     *
+     * KEY 格式:notify_template::{code}
+     * VALUE 数据格式:String 模版信息
+     */
+    String NOTIFY_TEMPLATE = "notify_template";
+
 }

+ 0 - 29
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/notify/NotifyTemplateRefreshConsumer.java

@@ -1,29 +0,0 @@
-package cn.iocoder.yudao.module.system.mq.consumer.notify;
-
-import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
-import cn.iocoder.yudao.module.system.mq.message.notify.NotifyTemplateRefreshMessage;
-import cn.iocoder.yudao.module.system.service.notify.NotifyTemplateService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * 针对 {@link NotifyTemplateRefreshMessage} 的消费者
- *
- * @author xrcoder
- */
-@Component
-@Slf4j
-public class NotifyTemplateRefreshConsumer extends AbstractChannelMessageListener<NotifyTemplateRefreshMessage> {
-
-    @Resource
-    private NotifyTemplateService notifyTemplateService;
-
-    @Override
-    public void onMessage(NotifyTemplateRefreshMessage message) {
-        log.info("[onMessage][收到 NotifyTemplate 刷新消息]");
-        notifyTemplateService.initLocalCache();
-    }
-
-}

+ 0 - 21
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/notify/NotifyTemplateRefreshMessage.java

@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.system.mq.message.notify;
-
-import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 站内信模板的数据刷新 Message
- *
- * @author xrcoder
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class NotifyTemplateRefreshMessage extends AbstractChannelMessage {
-
-    @Override
-    public String getChannel() {
-        return "system.notify-template.refresh";
-    }
-
-}

+ 0 - 33
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/notify/NotifyProducer.java

@@ -1,33 +0,0 @@
-package cn.iocoder.yudao.module.system.mq.producer.notify;
-
-import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
-import cn.iocoder.yudao.module.system.mq.message.notify.NotifyTemplateRefreshMessage;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * Notify 站内信相关消息的 Producer
- *
- * @author xrcoder
- * @since 2022-08-06
- */
-@Slf4j
-@Component
-public class NotifyProducer {
-
-    @Resource
-    private RedisMQTemplate redisMQTemplate;
-
-
-    /**
-     * 发送 {@link NotifyTemplateRefreshMessage} 消息
-     */
-    public void sendNotifyTemplateRefreshMessage() {
-        NotifyTemplateRefreshMessage message = new NotifyTemplateRefreshMessage();
-        redisMQTemplate.send(message);
-    }
-
-
-}

+ 8 - 13
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateService.java

@@ -16,19 +16,6 @@ import java.util.Map;
  */
 public interface NotifyTemplateService {
 
-    /**
-     * 初始化站内信模板的本地缓存
-     */
-    void initLocalCache();
-
-    /**
-     * 获得站内信模板,从缓存中
-     *
-     * @param code 模板编码
-     * @return 站内信模板
-     */
-    NotifyTemplateDO getNotifyTemplateByCodeFromCache(String code);
-
     /**
      * 创建站内信模版
      *
@@ -59,6 +46,14 @@ public interface NotifyTemplateService {
      */
     NotifyTemplateDO getNotifyTemplate(Long id);
 
+    /**
+     * 获得站内信模板,从缓存中
+     *
+     * @param code 模板编码
+     * @return 站内信模板
+     */
+    NotifyTemplateDO getNotifyTemplateByCodeFromCache(String code);
+
     /**
      * 获得站内信模版分页
      *

+ 17 - 43
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImpl.java

@@ -3,27 +3,28 @@ package cn.iocoder.yudao.module.system.service.notify;
 import cn.hutool.core.util.ReUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateCreateReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO;
 import cn.iocoder.yudao.module.system.convert.notify.NotifyTemplateConvert;
 import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
 import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyTemplateMapper;
-import cn.iocoder.yudao.module.system.mq.producer.notify.NotifyProducer;
+import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
-import javax.annotation.PostConstruct;
 import javax.annotation.Resource;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_CODE_DUPLICATE;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_NOT_EXISTS;
 
 /**
  * 站内信模版 Service 实现类
@@ -43,36 +44,6 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService {
     @Resource
     private NotifyTemplateMapper notifyTemplateMapper;
 
-    @Resource
-    private NotifyProducer notifyProducer;
-
-    /**
-     * 站内信模板缓存
-     * key:站内信模板编码 {@link NotifyTemplateDO#getCode()}
-     * <p>
-     * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
-     */
-    private volatile Map<String, NotifyTemplateDO> notifyTemplateCache;
-
-    /**
-     * 初始化站内信模板的本地缓存
-     */
-    @Override
-    @PostConstruct
-    public void initLocalCache() {
-        // 第一步:查询数据
-        List<NotifyTemplateDO> templates = notifyTemplateMapper.selectList();
-        log.info("[initLocalCache][缓存站内信模版,数量为:{}]", templates.size());
-
-        // 第二步:构建缓存
-        notifyTemplateCache = CollectionUtils.convertMap(templates, NotifyTemplateDO::getCode);
-    }
-
-    @Override
-    public NotifyTemplateDO getNotifyTemplateByCodeFromCache(String code) {
-        return notifyTemplateCache.get(code);
-    }
-
     @Override
     public Long createNotifyTemplate(NotifyTemplateCreateReqVO createReqVO) {
         // 校验站内信编码是否重复
@@ -82,13 +53,12 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService {
         NotifyTemplateDO notifyTemplate = NotifyTemplateConvert.INSTANCE.convert(createReqVO);
         notifyTemplate.setParams(parseTemplateContentParams(notifyTemplate.getContent()));
         notifyTemplateMapper.insert(notifyTemplate);
-
-        // 发送刷新消息
-        notifyProducer.sendNotifyTemplateRefreshMessage();
         return notifyTemplate.getId();
     }
 
     @Override
+    @CacheEvict(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE,
+            allEntries = true) // allEntries 清空所有缓存,因为可能修改到 code 字段,不好清理
     public void updateNotifyTemplate(NotifyTemplateUpdateReqVO updateReqVO) {
         // 校验存在
         validateNotifyTemplateExists(updateReqVO.getId());
@@ -99,9 +69,6 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService {
         NotifyTemplateDO updateObj = NotifyTemplateConvert.INSTANCE.convert(updateReqVO);
         updateObj.setParams(parseTemplateContentParams(updateObj.getContent()));
         notifyTemplateMapper.updateById(updateObj);
-
-        // 发送刷新消息
-        notifyProducer.sendNotifyTemplateRefreshMessage();
     }
 
     @VisibleForTesting
@@ -110,13 +77,13 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService {
     }
 
     @Override
+    @CacheEvict(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE,
+            allEntries = true) // allEntries 清空所有缓存,因为 id 不是直接的缓存 code,不好清理
     public void deleteNotifyTemplate(Long id) {
         // 校验存在
         validateNotifyTemplateExists(id);
         // 删除
         notifyTemplateMapper.deleteById(id);
-        // 发送刷新消息
-        notifyProducer.sendNotifyTemplateRefreshMessage();
     }
 
     private void validateNotifyTemplateExists(Long id) {
@@ -130,13 +97,20 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService {
         return notifyTemplateMapper.selectById(id);
     }
 
+    @Override
+    @Cacheable(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE, key = "#code",
+            unless = "#result == null")
+    public NotifyTemplateDO getNotifyTemplateByCodeFromCache(String code) {
+        return notifyTemplateMapper.selectByCode(code);
+    }
+
     @Override
     public PageResult<NotifyTemplateDO> getNotifyTemplatePage(NotifyTemplatePageReqVO pageReqVO) {
         return notifyTemplateMapper.selectPage(pageReqVO);
     }
 
     @VisibleForTesting
-    public void validateNotifyTemplateCodeDuplicate(Long id, String code) {
+    void validateNotifyTemplateCodeDuplicate(Long id, String code) {
         NotifyTemplateDO template = notifyTemplateMapper.selectByCode(code);
         if (template == null) {
             return;

+ 2 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java

@@ -100,7 +100,8 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
     }
 
     @Override
-    @Cacheable(cacheNames = RedisKeyConstants.OAUTH_CLIENT, key = "#clientId")
+    @Cacheable(cacheNames = RedisKeyConstants.OAUTH_CLIENT, key = "#clientId",
+            unless = "#result == null")
     public OAuth2ClientDO getOAuth2ClientFromCache(String clientId) {
         return oauth2ClientMapper.selectByClientId(clientId);
     }

+ 2 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java

@@ -171,7 +171,8 @@ public class RoleServiceImpl implements RoleService {
     }
 
     @Override
-    @Cacheable(value = RedisKeyConstants.ROLE, key = "#id", unless = "#result == null")
+    @Cacheable(value = RedisKeyConstants.ROLE, key = "#id",
+            unless = "#result == null")
     public RoleDO getRoleFromCache(Long id) {
         return roleMapper.selectById(id);
     }

+ 1 - 11
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImplTest.java

@@ -8,9 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.Notify
 import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO;
 import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyTemplateMapper;
-import cn.iocoder.yudao.module.system.mq.producer.notify.NotifyProducer;
 import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
 
 import javax.annotation.Resource;
@@ -25,7 +23,6 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_NOT_EXISTS;
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.verify;
 
 /**
 * {@link NotifyTemplateServiceImpl} 的单元测试类
@@ -41,9 +38,6 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest {
     @Resource
     private NotifyTemplateMapper notifyTemplateMapper;
 
-    @MockBean
-    private NotifyProducer notifyProducer;
-
     @Test
     public void testCreateNotifyTemplate_success() {
         // 准备参数
@@ -57,7 +51,6 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest {
         // 校验记录的属性是否正确
         NotifyTemplateDO notifyTemplate = notifyTemplateMapper.selectById(notifyTemplateId);
         assertPojoEquals(reqVO, notifyTemplate);
-        verify(notifyProducer).sendNotifyTemplateRefreshMessage();
     }
 
     @Test
@@ -76,7 +69,6 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest {
         // 校验是否更新正确
         NotifyTemplateDO notifyTemplate = notifyTemplateMapper.selectById(reqVO.getId()); // 获取最新的
         assertPojoEquals(reqVO, notifyTemplate);
-        verify(notifyProducer).sendNotifyTemplateRefreshMessage();
     }
 
     @Test
@@ -100,7 +92,6 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest {
         notifyTemplateService.deleteNotifyTemplate(id);
        // 校验数据不存在了
        assertNull(notifyTemplateMapper.selectById(id));
-       verify(notifyProducer).sendNotifyTemplateRefreshMessage();
     }
 
     @Test
@@ -164,7 +155,6 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest {
         // mock 数据
         NotifyTemplateDO dbNotifyTemplate = randomPojo(NotifyTemplateDO.class);
         notifyTemplateMapper.insert(dbNotifyTemplate);
-        notifyTemplateService.initLocalCache();
         // 准备参数
         String code = dbNotifyTemplate.getCode();
 
@@ -173,7 +163,7 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest {
         // 断言
         assertPojoEquals(dbNotifyTemplate, notifyTemplate);
     }
-    
+
     @Test
     public void testFormatNotifyTemplateContent() {
         // 准备参数