Răsfoiți Sursa

缓存改造:MailTemplate、MailAccount 使用 Redis 作为缓存

YunaiV 2 ani în urmă
părinte
comite
5dda7a3c05
11 a modificat fișierele cu 54 adăugiri și 219 ștergeri
  1. 15 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java
  2. 0 31
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailAccountRefreshConsumer.java
  3. 0 29
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailTemplateRefreshConsumer.java
  4. 0 21
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailAccountRefreshMessage.java
  5. 0 21
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailTemplateRefreshMessage.java
  6. 0 18
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/mail/MailProducer.java
  7. 8 13
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountService.java
  8. 12 41
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java
  9. 0 5
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java
  10. 16 40
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java
  11. 3 0
      yudao-server/src/main/resources/application.yaml

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

@@ -74,4 +74,19 @@ public interface RedisKeyConstants {
      */
     String NOTIFY_TEMPLATE = "notify_template";
 
+    /**
+     * 邮件账号的缓存
+     *
+     * KEY 格式:sms_template::{id}
+     * VALUE 数据格式:String 账号信息
+     */
+    String MAIL_ACCOUNT = "mail_account";
+
+    /**
+     * 邮件模版的缓存
+     *
+     * KEY 格式:mail_template::{code}
+     * VALUE 数据格式:String 模版信息
+     */
+    String MAIL_TEMPLATE = "mail_template";
 }

+ 0 - 31
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailAccountRefreshConsumer.java

@@ -1,31 +0,0 @@
-package cn.iocoder.yudao.module.system.mq.consumer.mail;
-
-import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
-import cn.iocoder.yudao.module.system.mq.message.mail.MailAccountRefreshMessage;
-import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage;
-import cn.iocoder.yudao.module.system.service.mail.MailAccountService;
-import cn.iocoder.yudao.module.system.service.mail.MailTemplateService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * 针对 {@link MailAccountRefreshMessage} 的消费者
- *
- * @author wangjingyi
- */
-@Component
-@Slf4j
-public class MailAccountRefreshConsumer extends AbstractChannelMessageListener<MailAccountRefreshMessage> {
-
-    @Resource
-    private MailAccountService mailAccountService;
-
-    @Override
-    public void onMessage(MailAccountRefreshMessage message) {
-        log.info("[onMessage][收到 Mail Account 刷新信息]");
-        mailAccountService.initLocalCache();
-    }
-
-}

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

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

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

@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.system.mq.message.mail;
-
-import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- * 邮箱账号的数据刷新 Message
- *
- * @author wangjingyi
- */
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class MailAccountRefreshMessage extends AbstractChannelMessage {
-
-    @Override
-    public String getChannel() {
-        return "system.mail-account.refresh";
-    }
-
-}

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

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

+ 0 - 18
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/mail/MailProducer.java

@@ -1,9 +1,7 @@
 package cn.iocoder.yudao.module.system.mq.producer.mail;
 
 import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
-import cn.iocoder.yudao.module.system.mq.message.mail.MailAccountRefreshMessage;
 import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
-import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
@@ -22,22 +20,6 @@ public class MailProducer {
     @Resource
     private RedisMQTemplate redisMQTemplate;
 
-    /**
-     * 发送 {@link MailTemplateRefreshMessage} 消息
-     */
-    public void sendMailTemplateRefreshMessage() {
-        MailTemplateRefreshMessage message = new MailTemplateRefreshMessage();
-        redisMQTemplate.send(message);
-    }
-
-    /**
-     * 发送 {@link MailAccountRefreshMessage} 消息
-     */
-    public void sendMailAccountRefreshMessage() {
-        MailAccountRefreshMessage message = new MailAccountRefreshMessage();
-        redisMQTemplate.send(message);
-    }
-
     /**
      * 发送 {@link MailSendMessage} 消息
      *

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

@@ -17,19 +17,6 @@ import java.util.List;
  */
 public interface MailAccountService {
 
-    /**
-     * 初始化邮箱账号的本地缓存
-     */
-    void initLocalCache();
-
-    /**
-     * 从缓存中获取邮箱账号
-     *
-     * @param id 编号
-     * @return 邮箱账号
-     */
-    MailAccountDO getMailAccountFromCache(Long id);
-
     /**
      * 创建邮箱账号
      *
@@ -60,6 +47,14 @@ public interface MailAccountService {
      */
     MailAccountDO getMailAccount(Long id);
 
+    /**
+     * 从缓存中获取邮箱账号
+     *
+     * @param id 编号
+     * @return 邮箱账号
+     */
+    MailAccountDO getMailAccountFromCache(Long id);
+
     /**
      * 获取邮箱账号分页信息
      *

+ 12 - 41
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java

@@ -7,20 +7,18 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccou
 import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert;
 import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
 import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper;
-import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
-import lombok.Getter;
+import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
 import lombok.extern.slf4j.Slf4j;
+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 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.module.system.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_NOT_EXISTS;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS;
 
 /**
  * 邮箱账号 Service 实现类
@@ -39,46 +37,16 @@ public class MailAccountServiceImpl implements MailAccountService {
     @Resource
     private MailTemplateService mailTemplateService;
 
-    @Resource
-    private MailProducer mailProducer;
-
-    /**
-     * 邮箱账号缓存
-     * key:邮箱账号编码 {@link MailAccountDO#getId()}
-     *
-     * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
-     */
-    @Getter
-    private volatile Map<Long, MailAccountDO> mailAccountCache;
-
-    @Override
-    @PostConstruct
-    public void initLocalCache() {
-        // 第一步:查询数据
-        List<MailAccountDO> accounts = mailAccountMapper.selectList();
-        log.info("[initLocalCache][缓存邮箱账号,数量:{}]", accounts.size());
-
-        // 第二步:构建缓存
-        mailAccountCache = convertMap(accounts, MailAccountDO::getId);
-    }
-
-    @Override
-    public MailAccountDO getMailAccountFromCache(Long id) {
-        return mailAccountCache.get(id);
-    }
-
     @Override
     public Long createMailAccount(MailAccountCreateReqVO createReqVO) {
         // 插入
         MailAccountDO account = MailAccountConvert.INSTANCE.convert(createReqVO);
         mailAccountMapper.insert(account);
-
-        // 发送刷新消息
-        mailProducer.sendMailAccountRefreshMessage();
         return account.getId();
     }
 
     @Override
+    @Cacheable(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#updateReqVO.id")
     public void updateMailAccount(MailAccountUpdateReqVO updateReqVO) {
         // 校验是否存在
         validateMailAccountExists(updateReqVO.getId());
@@ -86,11 +54,10 @@ public class MailAccountServiceImpl implements MailAccountService {
         // 更新
         MailAccountDO updateObj = MailAccountConvert.INSTANCE.convert(updateReqVO);
         mailAccountMapper.updateById(updateObj);
-        // 发送刷新消息
-        mailProducer.sendMailAccountRefreshMessage();
     }
 
     @Override
+    @Cacheable(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#id")
     public void deleteMailAccount(Long id) {
         // 校验是否存在账号
         validateMailAccountExists(id);
@@ -101,8 +68,6 @@ public class MailAccountServiceImpl implements MailAccountService {
 
         // 删除
         mailAccountMapper.deleteById(id);
-        // 发送刷新消息
-        mailProducer.sendMailAccountRefreshMessage();
     }
 
     private void validateMailAccountExists(Long id) {
@@ -116,6 +81,12 @@ public class MailAccountServiceImpl implements MailAccountService {
         return mailAccountMapper.selectById(id);
     }
 
+    @Override
+    @Cacheable(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#id", unless = "#result == null")
+    public MailAccountDO getMailAccountFromCache(Long id) {
+        return getMailAccount(id);
+    }
+
     @Override
     public PageResult<MailAccountDO> getMailAccountPage(MailAccountPageReqVO pageReqVO) {
         return mailAccountMapper.selectPage(pageReqVO);

+ 0 - 5
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java

@@ -18,11 +18,6 @@ import java.util.Map;
  */
 public interface MailTemplateService {
 
-    /**
-     * 初始化邮件模版的本地缓存
-     */
-    void initLocalCache();
-
     /**
      * 邮件模版创建
      *

+ 16 - 40
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java

@@ -10,14 +10,14 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemp
 import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert;
 import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
-import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
+import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
 import com.google.common.annotations.VisibleForTesting;
-import lombok.Getter;
 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 javax.validation.Valid;
 import java.util.List;
@@ -25,8 +25,8 @@ 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.framework.common.util.collection.CollectionUtils.convertMap;
-import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_CODE_EXISTS;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_NOT_EXISTS;
 
 /**
  * 邮箱模版 Service 实现类
@@ -47,29 +47,6 @@ public class MailTemplateServiceImpl implements MailTemplateService {
     @Resource
     private MailTemplateMapper mailTemplateMapper;
 
-    @Resource
-    private MailProducer mailProducer;
-
-    /**
-     * 邮件模板缓存
-     * key:邮件模版标识 {@link MailTemplateDO#getCode()}
-     *
-     * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
-     */
-    @Getter
-    private volatile Map<String, MailTemplateDO> mailTemplateCache;
-
-    @Override
-    @PostConstruct
-    public void initLocalCache() {
-        // 第一步:查询数据
-        List<MailTemplateDO> templates = mailTemplateMapper.selectList();
-        log.info("[initLocalCache][缓存邮件模版,数量:{}]", templates.size());
-
-        // 第二步:构建缓存
-        mailTemplateCache = convertMap(templates, MailTemplateDO::getCode);
-    }
-
     @Override
     public Long createMailTemplate(MailTemplateCreateReqVO createReqVO) {
         // 校验 code 是否唯一
@@ -79,12 +56,12 @@ public class MailTemplateServiceImpl implements MailTemplateService {
         MailTemplateDO template = MailTemplateConvert.INSTANCE.convert(createReqVO)
                 .setParams(parseTemplateContentParams(createReqVO.getContent()));
         mailTemplateMapper.insert(template);
-        // 发送刷新消息
-        mailProducer.sendMailTemplateRefreshMessage();
         return template.getId();
     }
 
     @Override
+    @CacheEvict(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE,
+            allEntries = true) // allEntries 清空所有缓存,因为可能修改到 code 字段,不好清理
     public void updateMailTemplate(@Valid MailTemplateUpdateReqVO updateReqVO) {
         // 校验是否存在
         validateMailTemplateExists(updateReqVO.getId());
@@ -95,12 +72,10 @@ public class MailTemplateServiceImpl implements MailTemplateService {
         MailTemplateDO updateObj = MailTemplateConvert.INSTANCE.convert(updateReqVO)
                 .setParams(parseTemplateContentParams(updateReqVO.getContent()));
         mailTemplateMapper.updateById(updateObj);
-        // 发送刷新消息
-        mailProducer.sendMailTemplateRefreshMessage();
     }
 
     @VisibleForTesting
-    public void validateCodeUnique(Long id, String code) {
+    void validateCodeUnique(Long id, String code) {
         MailTemplateDO template = mailTemplateMapper.selectByCode(code);
         if (template == null) {
             return;
@@ -113,14 +88,14 @@ public class MailTemplateServiceImpl implements MailTemplateService {
     }
 
     @Override
+    @CacheEvict(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE,
+            allEntries = true) // allEntries 清空所有缓存,因为 id 不是直接的缓存 code,不好清理
     public void deleteMailTemplate(Long id) {
         // 校验是否存在
         validateMailTemplateExists(id);
 
         // 删除
         mailTemplateMapper.deleteById(id);
-        // 发送刷新消息
-        mailProducer.sendMailTemplateRefreshMessage();
     }
 
     private void validateMailTemplateExists(Long id) {
@@ -132,6 +107,12 @@ public class MailTemplateServiceImpl implements MailTemplateService {
     @Override
     public MailTemplateDO getMailTemplate(Long id) {return mailTemplateMapper.selectById(id);}
 
+    @Override
+    @Cacheable(value = RedisKeyConstants.MAIL_TEMPLATE, key = "#code", unless = "#result == null")
+    public MailTemplateDO getMailTemplateByCodeFromCache(String code) {
+        return mailTemplateMapper.selectByCode(code);
+    }
+
     @Override
     public PageResult<MailTemplateDO> getMailTemplatePage(MailTemplatePageReqVO pageReqVO) {
         return mailTemplateMapper.selectPage(pageReqVO);
@@ -140,11 +121,6 @@ public class MailTemplateServiceImpl implements MailTemplateService {
     @Override
     public List<MailTemplateDO> getMailTemplateList() {return mailTemplateMapper.selectList();}
 
-    @Override
-    public MailTemplateDO getMailTemplateByCodeFromCache(String code) {
-        return mailTemplateCache.get(code);
-    }
-
     @Override
     public String formatMailTemplateContent(String content, Map<String, Object> params) {
         return StrUtil.format(content, params);

+ 3 - 0
yudao-server/src/main/resources/application.yaml

@@ -192,6 +192,9 @@ yudao:
     ignore-caches:
       - permission_menu_ids
       - oauth_client
+      - notify_template
+      - mail_account
+      - mail_template
   sms-code: # 短信验证码相关的配置项
     expire-times: 10m
     send-frequency: 1m