Commit d16f873521d24892f1148cfa9b43f01e94514e04
1 parent
bb78a580
站内信模板功能完善。
Showing
9 changed files
with
290 additions
and
16 deletions
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| @@ -144,6 +144,7 @@ public interface ErrorCodeConstants { | @@ -144,6 +144,7 @@ public interface ErrorCodeConstants { | ||
| 144 | 144 | ||
| 145 | // ========== 站内信模版 1002023000 ========== | 145 | // ========== 站内信模版 1002023000 ========== |
| 146 | ErrorCode NOTIFY_TEMPLATE_NOT_EXISTS = new ErrorCode(1002023000, "站内信模版不存在"); | 146 | ErrorCode NOTIFY_TEMPLATE_NOT_EXISTS = new ErrorCode(1002023000, "站内信模版不存在"); |
| 147 | + ErrorCode NOTIFY_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002023001, "已经存在编码为【{}】的站内信模板"); | ||
| 147 | 148 | ||
| 148 | // ========== 站内信 1002024000 ========== | 149 | // ========== 站内信 1002024000 ========== |
| 149 | ErrorCode NOTIFY_MESSAGE_NOT_EXISTS = new ErrorCode(1002024000, "站内信不存在"); | 150 | ErrorCode NOTIFY_MESSAGE_NOT_EXISTS = new ErrorCode(1002024000, "站内信不存在"); |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateRespVO.java
| @@ -13,6 +13,9 @@ public class NotifyTemplateRespVO extends NotifyTemplateBaseVO { | @@ -13,6 +13,9 @@ public class NotifyTemplateRespVO extends NotifyTemplateBaseVO { | ||
| 13 | @ApiModelProperty(value = "ID", required = true) | 13 | @ApiModelProperty(value = "ID", required = true) |
| 14 | private Long id; | 14 | private Long id; |
| 15 | 15 | ||
| 16 | + @ApiModelProperty(value = "参数数组", example = "name,code") | ||
| 17 | + private List<String> params; | ||
| 18 | + | ||
| 16 | @ApiModelProperty(value = "创建时间", required = true) | 19 | @ApiModelProperty(value = "创建时间", required = true) |
| 17 | private Date createTime; | 20 | private Date createTime; |
| 18 | 21 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/notify/NotifyTemplateDO.java
| 1 | package cn.iocoder.yudao.module.system.dal.dataobject.notify; | 1 | package cn.iocoder.yudao.module.system.dal.dataobject.notify; |
| 2 | 2 | ||
| 3 | -import lombok.*; | ||
| 4 | -import java.util.*; | ||
| 5 | -import com.baomidou.mybatisplus.annotation.*; | 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | +import com.baomidou.mybatisplus.annotation.KeySequence; | ||
| 6 | +import com.baomidou.mybatisplus.annotation.TableField; | ||
| 7 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 8 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 9 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | ||
| 10 | +import lombok.*; | ||
| 11 | + | ||
| 12 | +import java.util.List; | ||
| 7 | 13 | ||
| 8 | /** | 14 | /** |
| 9 | * 站内信模版 DO | 15 | * 站内信模版 DO |
| 10 | * | 16 | * |
| 11 | * @author xrcoder | 17 | * @author xrcoder |
| 12 | */ | 18 | */ |
| 13 | -@TableName("system_notify_template") | 19 | +@TableName(value = "system_notify_template", autoResultMap = true) |
| 14 | @KeySequence("system_notify_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | 20 | @KeySequence("system_notify_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 |
| 15 | @Data | 21 | @Data |
| 16 | @EqualsAndHashCode(callSuper = true) | 22 | @EqualsAndHashCode(callSuper = true) |
| @@ -25,28 +31,35 @@ public class NotifyTemplateDO extends BaseDO { | @@ -25,28 +31,35 @@ public class NotifyTemplateDO extends BaseDO { | ||
| 25 | */ | 31 | */ |
| 26 | @TableId | 32 | @TableId |
| 27 | private Long id; | 33 | private Long id; |
| 34 | + | ||
| 28 | /** | 35 | /** |
| 29 | * 模版编码 | 36 | * 模版编码 |
| 30 | */ | 37 | */ |
| 31 | private String code; | 38 | private String code; |
| 39 | + | ||
| 32 | /** | 40 | /** |
| 33 | * 模版标题 | 41 | * 模版标题 |
| 34 | */ | 42 | */ |
| 35 | private String title; | 43 | private String title; |
| 44 | + | ||
| 36 | /** | 45 | /** |
| 37 | * 模版内容 | 46 | * 模版内容 |
| 38 | */ | 47 | */ |
| 39 | private String content; | 48 | private String content; |
| 49 | + | ||
| 40 | /** | 50 | /** |
| 41 | * 参数数组 | 51 | * 参数数组 |
| 42 | */ | 52 | */ |
| 43 | - private String params; | 53 | + @TableField(typeHandler = JacksonTypeHandler.class) |
| 54 | + private List<String> params; | ||
| 55 | + | ||
| 44 | /** | 56 | /** |
| 45 | * 状态:1-启用 0-禁用 | 57 | * 状态:1-启用 0-禁用 |
| 46 | - * | ||
| 47 | - * 枚举 {@link TODO common_status 对应的类} | 58 | + * <p> |
| 59 | + * 枚举 {@link CommonStatusEnum} | ||
| 48 | */ | 60 | */ |
| 49 | private String status; | 61 | private String status; |
| 62 | + | ||
| 50 | /** | 63 | /** |
| 51 | * 备注 | 64 | * 备注 |
| 52 | */ | 65 | */ |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/notify/NotifyTemplateMapper.java
| @@ -8,7 +8,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | @@ -8,7 +8,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 8 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateExportReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateExportReqVO; |
| 9 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; | 9 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; |
| 11 | +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | ||
| 11 | import org.apache.ibatis.annotations.Mapper; | 12 | import org.apache.ibatis.annotations.Mapper; |
| 13 | +import org.apache.ibatis.annotations.Select; | ||
| 12 | 14 | ||
| 13 | /** | 15 | /** |
| 14 | * 站内信模版 Mapper | 16 | * 站内信模版 Mapper |
| @@ -18,6 +20,13 @@ import org.apache.ibatis.annotations.Mapper; | @@ -18,6 +20,13 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 18 | @Mapper | 20 | @Mapper |
| 19 | public interface NotifyTemplateMapper extends BaseMapperX<NotifyTemplateDO> { | 21 | public interface NotifyTemplateMapper extends BaseMapperX<NotifyTemplateDO> { |
| 20 | 22 | ||
| 23 | + @Select("SELECT COUNT(*) FROM system_notify_template WHERE update_time > #{maxUpdateTime}") | ||
| 24 | + Long selectCountByUpdateTimeGt(Date maxUpdateTime); | ||
| 25 | + | ||
| 26 | + default NotifyTemplateDO selectByCode(String code) { | ||
| 27 | + return selectOne(NotifyTemplateDO::getCode, code); | ||
| 28 | + } | ||
| 29 | + | ||
| 21 | default PageResult<NotifyTemplateDO> selectPage(NotifyTemplatePageReqVO reqVO) { | 30 | default PageResult<NotifyTemplateDO> selectPage(NotifyTemplatePageReqVO reqVO) { |
| 22 | return selectPage(reqVO, new LambdaQueryWrapperX<NotifyTemplateDO>() | 31 | return selectPage(reqVO, new LambdaQueryWrapperX<NotifyTemplateDO>() |
| 23 | .eqIfPresent(NotifyTemplateDO::getCode, reqVO.getCode()) | 32 | .eqIfPresent(NotifyTemplateDO::getCode, reqVO.getCode()) |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/notify/NotifyTemplateRefreshConsumer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.consumer.notify; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; | ||
| 4 | +import cn.iocoder.yudao.module.system.mq.message.notify.NotifyTemplateRefreshMessage; | ||
| 5 | +import cn.iocoder.yudao.module.system.service.notify.NotifyTemplateService; | ||
| 6 | +import lombok.extern.slf4j.Slf4j; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 针对 {@link NotifyTemplateRefreshMessage} 的消费者 | ||
| 13 | + * | ||
| 14 | + * @author xrcoder | ||
| 15 | + */ | ||
| 16 | +@Component | ||
| 17 | +@Slf4j | ||
| 18 | +public class NotifyTemplateRefreshConsumer extends AbstractChannelMessageListener<NotifyTemplateRefreshMessage> { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private NotifyTemplateService notifyTemplateService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void onMessage(NotifyTemplateRefreshMessage message) { | ||
| 25 | + log.info("[onMessage][收到 NotifyTemplate 刷新消息]"); | ||
| 26 | + notifyTemplateService.initLocalCache(); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/notify/NotifyTemplateRefreshMessage.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.message.notify; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 站内信模板的数据刷新 Message | ||
| 9 | + * | ||
| 10 | + * @author xrcoder | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode(callSuper = true) | ||
| 14 | +public class NotifyTemplateRefreshMessage extends AbstractChannelMessage { | ||
| 15 | + | ||
| 16 | + @Override | ||
| 17 | + public String getChannel() { | ||
| 18 | + return "system.notify-template.refresh"; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/notify/NotifyProducer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.producer.notify; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; | ||
| 4 | +import cn.iocoder.yudao.module.system.mq.message.notify.NotifyTemplateRefreshMessage; | ||
| 5 | +import lombok.extern.slf4j.Slf4j; | ||
| 6 | +import org.springframework.stereotype.Component; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Notify 站内信相关消息的 Producer | ||
| 12 | + * | ||
| 13 | + * @author xrcoder | ||
| 14 | + * @since 2022-08-06 | ||
| 15 | + */ | ||
| 16 | +@Slf4j | ||
| 17 | +@Component | ||
| 18 | +public class NotifyProducer { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private RedisMQTemplate redisMQTemplate; | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 发送 {@link NotifyTemplateRefreshMessage} 消息 | ||
| 26 | + */ | ||
| 27 | + public void sendNotifyTemplateRefreshMessage() { | ||
| 28 | + NotifyTemplateRefreshMessage message = new NotifyTemplateRefreshMessage(); | ||
| 29 | + redisMQTemplate.send(message); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateService.java
| @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.Notify | @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.Notify | ||
| 9 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; | 9 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; |
| 11 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 11 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 12 | +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | ||
| 12 | 13 | ||
| 13 | /** | 14 | /** |
| 14 | * 站内信模版 Service 接口 | 15 | * 站内信模版 Service 接口 |
| @@ -18,6 +19,29 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -18,6 +19,29 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 18 | public interface NotifyTemplateService { | 19 | public interface NotifyTemplateService { |
| 19 | 20 | ||
| 20 | /** | 21 | /** |
| 22 | + * 初始化站内信模板的本地缓存 | ||
| 23 | + */ | ||
| 24 | + void initLocalCache(); | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 获得站内信模板,从缓存中 | ||
| 28 | + * | ||
| 29 | + * @param code 模板编码 | ||
| 30 | + * @return 站内信模板 | ||
| 31 | + */ | ||
| 32 | + NotifyTemplateDO getNotifyTemplateByCodeFromCache(String code); | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 格式化站内信内容 | ||
| 37 | + * | ||
| 38 | + * @param content 站内信模板的内容 | ||
| 39 | + * @param params 站内信内容的参数 | ||
| 40 | + * @return 格式化后的内容 | ||
| 41 | + */ | ||
| 42 | + String formatNotifyTemplateContent(String content, Map<String, Object> params); | ||
| 43 | + | ||
| 44 | + /** | ||
| 21 | * 创建站内信模版 | 45 | * 创建站内信模版 |
| 22 | * | 46 | * |
| 23 | * @param createReqVO 创建信息 | 47 | * @param createReqVO 创建信息 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.notify; | 1 | package cn.iocoder.yudao.module.system.service.notify; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.util.ReUtil; | ||
| 5 | +import cn.hutool.core.util.StrUtil; | ||
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 7 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 3 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateCreateReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateCreateReqVO; |
| 4 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateExportReqVO; | 9 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateExportReqVO; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; | 10 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; |
| 6 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; | 11 | import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; |
| 12 | +import cn.iocoder.yudao.module.system.convert.notify.NotifyTemplateConvert; | ||
| 13 | +import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; | ||
| 14 | +import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyTemplateMapper; | ||
| 15 | +import cn.iocoder.yudao.module.system.mq.producer.notify.NotifyProducer; | ||
| 16 | +import com.google.common.annotations.VisibleForTesting; | ||
| 17 | +import lombok.extern.slf4j.Slf4j; | ||
| 18 | +import org.springframework.scheduling.annotation.Scheduled; | ||
| 7 | import org.springframework.stereotype.Service; | 19 | import org.springframework.stereotype.Service; |
| 8 | -import javax.annotation.Resource; | ||
| 9 | import org.springframework.validation.annotation.Validated; | 20 | import org.springframework.validation.annotation.Validated; |
| 10 | 21 | ||
| 11 | -import java.util.*; | ||
| 12 | - | ||
| 13 | -import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; | ||
| 14 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 15 | - | ||
| 16 | -import cn.iocoder.yudao.module.system.convert.notify.NotifyTemplateConvert; | ||
| 17 | -import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyTemplateMapper; | 22 | +import javax.annotation.Resource; |
| 23 | +import java.util.Collection; | ||
| 24 | +import java.util.Date; | ||
| 25 | +import java.util.List; | ||
| 26 | +import java.util.Map; | ||
| 27 | +import java.util.regex.Pattern; | ||
| 18 | 28 | ||
| 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 20 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | 30 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_CODE_DUPLICATE; |
| 31 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_NOT_EXISTS; | ||
| 21 | 32 | ||
| 22 | /** | 33 | /** |
| 23 | * 站内信模版 Service 实现类 | 34 | * 站内信模版 Service 实现类 |
| @@ -26,16 +37,123 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | @@ -26,16 +37,123 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | ||
| 26 | */ | 37 | */ |
| 27 | @Service | 38 | @Service |
| 28 | @Validated | 39 | @Validated |
| 40 | +@Slf4j | ||
| 29 | public class NotifyTemplateServiceImpl implements NotifyTemplateService { | 41 | public class NotifyTemplateServiceImpl implements NotifyTemplateService { |
| 30 | 42 | ||
| 43 | + /** | ||
| 44 | + * 定时执行 {@link #schedulePeriodicRefresh()} 的周期 | ||
| 45 | + * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高 | ||
| 46 | + */ | ||
| 47 | + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 正则表达式,匹配 {} 中的变量 | ||
| 51 | + */ | ||
| 52 | + private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}"); | ||
| 53 | + | ||
| 31 | @Resource | 54 | @Resource |
| 32 | private NotifyTemplateMapper notifyTemplateMapper; | 55 | private NotifyTemplateMapper notifyTemplateMapper; |
| 33 | 56 | ||
| 57 | + @Resource | ||
| 58 | + private NotifyProducer notifyProducer; | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 站内信模板缓存 | ||
| 62 | + * key:站内信模板编码 {@link NotifyTemplateDO#getCode()} | ||
| 63 | + * <p> | ||
| 64 | + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | ||
| 65 | + */ | ||
| 66 | + private volatile Map<String, NotifyTemplateDO> notifyTemplateCache; | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * 缓存站内信模板的最大更新时间,用于后续的增量轮询,判断是否有更新 | ||
| 70 | + */ | ||
| 71 | + private volatile Date maxUpdateTime; | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * 初始化站内信模板的本地缓存 | ||
| 75 | + */ | ||
| 76 | + @Override | ||
| 77 | + public void initLocalCache() { | ||
| 78 | + // 获取站内信模板列表,如果有更新 | ||
| 79 | + List<NotifyTemplateDO> notifyTemplateList = this.loadNotifyTemplateIfUpdate(maxUpdateTime); | ||
| 80 | + if (CollUtil.isEmpty(notifyTemplateList)) { | ||
| 81 | + return; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + // 写入缓存 | ||
| 85 | + notifyTemplateCache = CollectionUtils.convertMap(notifyTemplateList, NotifyTemplateDO::getCode); | ||
| 86 | + maxUpdateTime = CollectionUtils.getMaxValue(notifyTemplateList, NotifyTemplateDO::getUpdateTime); | ||
| 87 | + log.info("[initLocalCache][初始化 NotifyTemplate 数量为 {}]", notifyTemplateList.size()); | ||
| 88 | + | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * 如果站内信模板发生变化,从数据库中获取最新的全量站内信模板。 | ||
| 93 | + * 如果未发生变化,则返回空 | ||
| 94 | + * | ||
| 95 | + * @param maxUpdateTime 当前站内信模板的最大更新时间 | ||
| 96 | + * @return 站内信模板列表 | ||
| 97 | + */ | ||
| 98 | + private List<NotifyTemplateDO> loadNotifyTemplateIfUpdate(Date maxUpdateTime) { | ||
| 99 | + // 第一步,判断是否要更新。 | ||
| 100 | + if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 | ||
| 101 | + log.info("[loadNotifyTemplateIfUpdate][首次加载全量站内信模板]"); | ||
| 102 | + } else { // 判断数据库中是否有更新的站内信模板 | ||
| 103 | + if (notifyTemplateMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { | ||
| 104 | + return null; | ||
| 105 | + } | ||
| 106 | + log.info("[loadNotifyTemplateIfUpdate][增量加载全量站内信模板]"); | ||
| 107 | + } | ||
| 108 | + // 第二步,如果有更新,则从数据库加载所有站内信模板 | ||
| 109 | + return notifyTemplateMapper.selectList(); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) | ||
| 113 | + public void schedulePeriodicRefresh() { | ||
| 114 | + initLocalCache(); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * 获得站内信模板,从缓存中 | ||
| 120 | + * | ||
| 121 | + * @param code 模板编码 | ||
| 122 | + * @return 站内信模板 | ||
| 123 | + */ | ||
| 124 | + @Override | ||
| 125 | + public NotifyTemplateDO getNotifyTemplateByCodeFromCache(String code) { | ||
| 126 | + return notifyTemplateCache.get(code); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + /** | ||
| 130 | + * 格式化站内信内容 | ||
| 131 | + * | ||
| 132 | + * @param content 站内信模板的内容 | ||
| 133 | + * @param params 站内信内容的参数 | ||
| 134 | + * @return 格式化后的内容 | ||
| 135 | + */ | ||
| 136 | + @Override | ||
| 137 | + public String formatNotifyTemplateContent(String content, Map<String, Object> params) { | ||
| 138 | + return StrUtil.format(content, params); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + @VisibleForTesting | ||
| 142 | + public List<String> parseTemplateContentParams(String content) { | ||
| 143 | + return ReUtil.findAllGroup1(PATTERN_PARAMS, content); | ||
| 144 | + } | ||
| 145 | + | ||
| 34 | @Override | 146 | @Override |
| 35 | public Long createNotifyTemplate(NotifyTemplateCreateReqVO createReqVO) { | 147 | public Long createNotifyTemplate(NotifyTemplateCreateReqVO createReqVO) { |
| 148 | + // 校验站内信编码是否重复 | ||
| 149 | + checkNotifyTemplateCodeDuplicate(null, createReqVO.getCode()); | ||
| 150 | + | ||
| 36 | // 插入 | 151 | // 插入 |
| 37 | NotifyTemplateDO notifyTemplate = NotifyTemplateConvert.INSTANCE.convert(createReqVO); | 152 | NotifyTemplateDO notifyTemplate = NotifyTemplateConvert.INSTANCE.convert(createReqVO); |
| 153 | + notifyTemplate.setParams(parseTemplateContentParams(notifyTemplate.getContent())); | ||
| 38 | notifyTemplateMapper.insert(notifyTemplate); | 154 | notifyTemplateMapper.insert(notifyTemplate); |
| 155 | + // 发送刷新消息 | ||
| 156 | + notifyProducer.sendNotifyTemplateRefreshMessage(); | ||
| 39 | // 返回 | 157 | // 返回 |
| 40 | return notifyTemplate.getId(); | 158 | return notifyTemplate.getId(); |
| 41 | } | 159 | } |
| @@ -44,9 +162,16 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { | @@ -44,9 +162,16 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { | ||
| 44 | public void updateNotifyTemplate(NotifyTemplateUpdateReqVO updateReqVO) { | 162 | public void updateNotifyTemplate(NotifyTemplateUpdateReqVO updateReqVO) { |
| 45 | // 校验存在 | 163 | // 校验存在 |
| 46 | this.validateNotifyTemplateExists(updateReqVO.getId()); | 164 | this.validateNotifyTemplateExists(updateReqVO.getId()); |
| 165 | + // 校验站内信编码是否重复 | ||
| 166 | + checkNotifyTemplateCodeDuplicate(updateReqVO.getId(), updateReqVO.getCode()); | ||
| 167 | + | ||
| 47 | // 更新 | 168 | // 更新 |
| 48 | NotifyTemplateDO updateObj = NotifyTemplateConvert.INSTANCE.convert(updateReqVO); | 169 | NotifyTemplateDO updateObj = NotifyTemplateConvert.INSTANCE.convert(updateReqVO); |
| 170 | + updateObj.setParams(parseTemplateContentParams(updateObj.getContent())); | ||
| 171 | + | ||
| 49 | notifyTemplateMapper.updateById(updateObj); | 172 | notifyTemplateMapper.updateById(updateObj); |
| 173 | + // 发送刷新消息 | ||
| 174 | + notifyProducer.sendNotifyTemplateRefreshMessage(); | ||
| 50 | } | 175 | } |
| 51 | 176 | ||
| 52 | @Override | 177 | @Override |
| @@ -55,6 +180,8 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { | @@ -55,6 +180,8 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { | ||
| 55 | this.validateNotifyTemplateExists(id); | 180 | this.validateNotifyTemplateExists(id); |
| 56 | // 删除 | 181 | // 删除 |
| 57 | notifyTemplateMapper.deleteById(id); | 182 | notifyTemplateMapper.deleteById(id); |
| 183 | + // 发送刷新消息 | ||
| 184 | + notifyProducer.sendNotifyTemplateRefreshMessage(); | ||
| 58 | } | 185 | } |
| 59 | 186 | ||
| 60 | private void validateNotifyTemplateExists(Long id) { | 187 | private void validateNotifyTemplateExists(Long id) { |
| @@ -83,4 +210,18 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { | @@ -83,4 +210,18 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { | ||
| 83 | return notifyTemplateMapper.selectList(exportReqVO); | 210 | return notifyTemplateMapper.selectList(exportReqVO); |
| 84 | } | 211 | } |
| 85 | 212 | ||
| 213 | + @VisibleForTesting | ||
| 214 | + public void checkNotifyTemplateCodeDuplicate(Long id, String code) { | ||
| 215 | + NotifyTemplateDO template = notifyTemplateMapper.selectByCode(code); | ||
| 216 | + if (template == null) { | ||
| 217 | + return; | ||
| 218 | + } | ||
| 219 | + // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 | ||
| 220 | + if (id == null) { | ||
| 221 | + throw exception(NOTIFY_TEMPLATE_CODE_DUPLICATE, code); | ||
| 222 | + } | ||
| 223 | + if (!template.getId().equals(id)) { | ||
| 224 | + throw exception(NOTIFY_TEMPLATE_CODE_DUPLICATE, code); | ||
| 225 | + } | ||
| 226 | + } | ||
| 86 | } | 227 | } |