You've already forked FrameTour-BE
perf(notify): 优化微信订阅消息配置查询性能
- 为微信订阅消息配置接口添加 Redis 缓存支持 - 在 WechatSubscribeNotifyConfigRepository 中实现缓存读写和清除机制 - 修改 Controller 层接口添加 @IgnoreToken 注解支持匿名访问 - 优化查询逻辑,添加 memberId 为空时的提前返回处理 - 在管理服务中添加缓存清除逻辑,确保配置变更时缓存同步更新 - 实现批量缓存清除功能,支持按景区和全局范围清除缓存
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.ycwl.basic.controller.mobile.notify;
|
||||
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import com.ycwl.basic.model.mobile.notify.resp.WechatSubscribeSceneTemplatesResp;
|
||||
import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeTemplateConfigEntity;
|
||||
import com.ycwl.basic.service.notify.WechatSubscribeNotifyConfigService;
|
||||
@@ -41,6 +42,7 @@ public class WechatSubscribeNotifyController {
|
||||
* 获取“场景”下可申请授权的模板列表(支持按 scenicId 覆盖模板ID/开关/文案)
|
||||
*/
|
||||
@GetMapping("/scenic/{scenicId}/scenes/{sceneKey}/templates")
|
||||
@IgnoreToken
|
||||
public ApiResponse<WechatSubscribeSceneTemplatesResp> listSceneTemplates(@PathVariable("scenicId") Long scenicId,
|
||||
@PathVariable("sceneKey") String sceneKey) {
|
||||
if (scenicId == null) {
|
||||
@@ -56,6 +58,9 @@ public class WechatSubscribeNotifyController {
|
||||
WechatSubscribeSceneTemplatesResp resp = new WechatSubscribeSceneTemplatesResp();
|
||||
resp.setScenicId(scenicId);
|
||||
resp.setSceneKey(sceneKey);
|
||||
if (memberId == null) {
|
||||
return ApiResponse.success(resp);
|
||||
}
|
||||
|
||||
List<WechatSubscribeSceneTemplatesResp.TemplateInfo> templates = new ArrayList<>();
|
||||
for (WechatSubscribeTemplateConfigEntity cfg : configs) {
|
||||
|
||||
@@ -1,44 +1,81 @@
|
||||
package com.ycwl.basic.repository;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.ycwl.basic.mapper.WechatSubscribeEventTemplateMapper;
|
||||
import com.ycwl.basic.mapper.WechatSubscribeSceneTemplateMapper;
|
||||
import com.ycwl.basic.mapper.WechatSubscribeTemplateConfigMapper;
|
||||
import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeEventTemplateEntity;
|
||||
import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeSceneTemplateEntity;
|
||||
import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeTemplateConfigEntity;
|
||||
import com.ycwl.basic.utils.JacksonUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 微信订阅消息配置仓库(scenic 覆盖:scenic_id=具体值 > scenic_id=0)
|
||||
* 支持 Redis 缓存,减少数据库查询
|
||||
*
|
||||
* @Author: System
|
||||
* @Date: 2025/12/31
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class WechatSubscribeNotifyConfigRepository {
|
||||
|
||||
private static final long DEFAULT_SCENIC_ID = 0L;
|
||||
|
||||
/**
|
||||
* 场景模板配置缓存KEY
|
||||
*/
|
||||
private static final String SCENE_TEMPLATE_CONFIGS_KEY = "wechat:subscribe:scene:configs:%s:%s";
|
||||
|
||||
/**
|
||||
* 事件模板配置缓存KEY
|
||||
*/
|
||||
private static final String EVENT_TEMPLATE_CONFIGS_KEY = "wechat:subscribe:event:configs:%s:%s";
|
||||
|
||||
/**
|
||||
* 景区所有场景缓存KEY前缀(用于批量清除)
|
||||
*/
|
||||
private static final String SCENE_TEMPLATE_SCENIC_PREFIX = "wechat:subscribe:scene:configs:%s:*";
|
||||
|
||||
/**
|
||||
* 景区所有事件缓存KEY前缀(用于批量清除)
|
||||
*/
|
||||
private static final String EVENT_TEMPLATE_SCENIC_PREFIX = "wechat:subscribe:event:configs:%s:*";
|
||||
|
||||
/**
|
||||
* 缓存过期时间(小时)
|
||||
*/
|
||||
private static final long CACHE_EXPIRE_HOURS = 1;
|
||||
|
||||
private final WechatSubscribeTemplateConfigMapper templateConfigMapper;
|
||||
private final WechatSubscribeSceneTemplateMapper sceneTemplateMapper;
|
||||
private final WechatSubscribeEventTemplateMapper eventTemplateMapper;
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
public WechatSubscribeNotifyConfigRepository(WechatSubscribeTemplateConfigMapper templateConfigMapper,
|
||||
WechatSubscribeSceneTemplateMapper sceneTemplateMapper,
|
||||
WechatSubscribeEventTemplateMapper eventTemplateMapper) {
|
||||
WechatSubscribeEventTemplateMapper eventTemplateMapper,
|
||||
RedisTemplate<String, String> redisTemplate) {
|
||||
this.templateConfigMapper = templateConfigMapper;
|
||||
this.sceneTemplateMapper = sceneTemplateMapper;
|
||||
this.eventTemplateMapper = eventTemplateMapper;
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
public List<WechatSubscribeSceneTemplateEntity> listEffectiveSceneTemplateMappings(Long scenicId, String sceneKey) {
|
||||
@@ -170,4 +207,210 @@ public class WechatSubscribeNotifyConfigRepository {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ==================== 带缓存的配置查询方法 ====================
|
||||
|
||||
/**
|
||||
* 获取场景模板配置列表(带缓存)
|
||||
* 缓存最终的配置列表,避免重复查询和处理覆盖逻辑
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
* @param sceneKey 场景标识
|
||||
* @return 启用的模板配置列表
|
||||
*/
|
||||
public List<WechatSubscribeTemplateConfigEntity> getSceneTemplateConfigsCached(Long scenicId, String sceneKey) {
|
||||
Objects.requireNonNull(scenicId, "scenicId is null");
|
||||
if (StringUtils.isBlank(sceneKey)) {
|
||||
throw new IllegalArgumentException("sceneKey is blank");
|
||||
}
|
||||
|
||||
String cacheKey = String.format(SCENE_TEMPLATE_CONFIGS_KEY, scenicId, sceneKey);
|
||||
|
||||
// 1. 尝试从缓存读取
|
||||
Boolean hasKey = redisTemplate.hasKey(cacheKey);
|
||||
if (Boolean.TRUE.equals(hasKey)) {
|
||||
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
|
||||
if (cacheValue != null) {
|
||||
log.debug("从缓存读取场景模板配置: scenicId={}, sceneKey={}", scenicId, sceneKey);
|
||||
return JacksonUtil.parseObject(cacheValue, new TypeReference<List<WechatSubscribeTemplateConfigEntity>>() {});
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 从数据库查询
|
||||
List<WechatSubscribeTemplateConfigEntity> configs = loadSceneTemplateConfigs(scenicId, sceneKey);
|
||||
|
||||
// 3. 写入缓存
|
||||
String json = JacksonUtil.toJSONString(configs);
|
||||
redisTemplate.opsForValue().set(cacheKey, json, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
|
||||
log.debug("场景模板配置缓存写入: scenicId={}, sceneKey={}, count={}", scenicId, sceneKey, configs.size());
|
||||
|
||||
return configs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取事件模板配置列表(带缓存)
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
* @param eventKey 事件标识
|
||||
* @return 启用的模板配置列表
|
||||
*/
|
||||
public List<WechatSubscribeTemplateConfigEntity> getEventTemplateConfigsCached(Long scenicId, String eventKey) {
|
||||
Objects.requireNonNull(scenicId, "scenicId is null");
|
||||
if (StringUtils.isBlank(eventKey)) {
|
||||
throw new IllegalArgumentException("eventKey is blank");
|
||||
}
|
||||
|
||||
String cacheKey = String.format(EVENT_TEMPLATE_CONFIGS_KEY, scenicId, eventKey);
|
||||
|
||||
// 1. 尝试从缓存读取
|
||||
Boolean hasKey = redisTemplate.hasKey(cacheKey);
|
||||
if (Boolean.TRUE.equals(hasKey)) {
|
||||
String cacheValue = redisTemplate.opsForValue().get(cacheKey);
|
||||
if (cacheValue != null) {
|
||||
log.debug("从缓存读取事件模板配置: scenicId={}, eventKey={}", scenicId, eventKey);
|
||||
return JacksonUtil.parseObject(cacheValue, new TypeReference<List<WechatSubscribeTemplateConfigEntity>>() {});
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 从数据库查询
|
||||
List<WechatSubscribeTemplateConfigEntity> configs = loadEventTemplateConfigs(scenicId, eventKey);
|
||||
|
||||
// 3. 写入缓存
|
||||
String json = JacksonUtil.toJSONString(configs);
|
||||
redisTemplate.opsForValue().set(cacheKey, json, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
|
||||
log.debug("事件模板配置缓存写入: scenicId={}, eventKey={}, count={}", scenicId, eventKey, configs.size());
|
||||
|
||||
return configs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载场景模板配置(内部方法,处理覆盖逻辑)
|
||||
*/
|
||||
private List<WechatSubscribeTemplateConfigEntity> loadSceneTemplateConfigs(Long scenicId, String sceneKey) {
|
||||
List<WechatSubscribeSceneTemplateEntity> mappings = listEffectiveSceneTemplateMappings(scenicId, sceneKey);
|
||||
if (CollectionUtils.isEmpty(mappings)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Set<String> templateKeys = mappings.stream()
|
||||
.map(WechatSubscribeSceneTemplateEntity::getTemplateKey)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String, WechatSubscribeTemplateConfigEntity> configMap = getEffectiveTemplateConfigs(scenicId, templateKeys);
|
||||
|
||||
List<WechatSubscribeTemplateConfigEntity> result = new ArrayList<>();
|
||||
for (WechatSubscribeSceneTemplateEntity mapping : mappings) {
|
||||
WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey());
|
||||
if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) {
|
||||
continue;
|
||||
}
|
||||
result.add(cfg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载事件模板配置(内部方法,处理覆盖逻辑)
|
||||
*/
|
||||
private List<WechatSubscribeTemplateConfigEntity> loadEventTemplateConfigs(Long scenicId, String eventKey) {
|
||||
List<WechatSubscribeEventTemplateEntity> mappings = listEffectiveEventTemplateMappings(scenicId, eventKey);
|
||||
if (CollectionUtils.isEmpty(mappings)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Set<String> templateKeys = mappings.stream()
|
||||
.map(WechatSubscribeEventTemplateEntity::getTemplateKey)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String, WechatSubscribeTemplateConfigEntity> configMap = getEffectiveTemplateConfigs(scenicId, templateKeys);
|
||||
|
||||
List<WechatSubscribeTemplateConfigEntity> result = new ArrayList<>();
|
||||
for (WechatSubscribeEventTemplateEntity mapping : mappings) {
|
||||
WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey());
|
||||
if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) {
|
||||
continue;
|
||||
}
|
||||
result.add(cfg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ==================== 缓存清除方法 ====================
|
||||
|
||||
/**
|
||||
* 清除指定场景的模板配置缓存
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
* @param sceneKey 场景标识
|
||||
*/
|
||||
public void clearSceneTemplateConfigsCache(Long scenicId, String sceneKey) {
|
||||
if (scenicId == null || StringUtils.isBlank(sceneKey)) {
|
||||
return;
|
||||
}
|
||||
String cacheKey = String.format(SCENE_TEMPLATE_CONFIGS_KEY, scenicId, sceneKey);
|
||||
redisTemplate.delete(cacheKey);
|
||||
log.debug("清除场景模板配置缓存: scenicId={}, sceneKey={}", scenicId, sceneKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除指定事件的模板配置缓存
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
* @param eventKey 事件标识
|
||||
*/
|
||||
public void clearEventTemplateConfigsCache(Long scenicId, String eventKey) {
|
||||
if (scenicId == null || StringUtils.isBlank(eventKey)) {
|
||||
return;
|
||||
}
|
||||
String cacheKey = String.format(EVENT_TEMPLATE_CONFIGS_KEY, scenicId, eventKey);
|
||||
redisTemplate.delete(cacheKey);
|
||||
log.debug("清除事件模板配置缓存: scenicId={}, eventKey={}", scenicId, eventKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除景区下所有订阅消息配置缓存
|
||||
* 在景区配置变更时调用
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
*/
|
||||
public void clearAllConfigsCacheByScenic(Long scenicId) {
|
||||
if (scenicId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 清除场景配置缓存
|
||||
String scenePattern = String.format(SCENE_TEMPLATE_SCENIC_PREFIX, scenicId);
|
||||
deleteByPattern(scenePattern);
|
||||
|
||||
// 清除事件配置缓存
|
||||
String eventPattern = String.format(EVENT_TEMPLATE_SCENIC_PREFIX, scenicId);
|
||||
deleteByPattern(eventPattern);
|
||||
|
||||
log.info("清除景区所有订阅消息配置缓存: scenicId={}", scenicId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有订阅消息配置缓存
|
||||
* 在全局配置变更时调用(如默认配置修改)
|
||||
*/
|
||||
public void clearAllConfigsCache() {
|
||||
deleteByPattern("wechat:subscribe:scene:configs:*");
|
||||
deleteByPattern("wechat:subscribe:event:configs:*");
|
||||
log.warn("清除所有订阅消息配置缓存");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模式删除缓存
|
||||
*/
|
||||
private void deleteByPattern(String pattern) {
|
||||
try {
|
||||
var keys = redisTemplate.keys(pattern);
|
||||
if (keys != null && !keys.isEmpty()) {
|
||||
redisTemplate.delete(keys);
|
||||
log.debug("删除缓存: pattern={}, count={}", pattern, keys.size());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("删除缓存失败: pattern={}", pattern, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
package com.ycwl.basic.service.notify;
|
||||
|
||||
import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeEventTemplateEntity;
|
||||
import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeSceneTemplateEntity;
|
||||
import com.ycwl.basic.model.pc.notify.entity.WechatSubscribeTemplateConfigEntity;
|
||||
import com.ycwl.basic.repository.WechatSubscribeNotifyConfigRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 微信订阅消息配置查询服务(仅负责“配置解析”,不包含授权/发送逻辑)
|
||||
* 微信订阅消息配置查询服务(仅负责"配置解析",不包含授权/发送逻辑)
|
||||
* 底层通过 Repository 实现 Redis 缓存
|
||||
*
|
||||
* @Author: System
|
||||
* @Date: 2025/12/31
|
||||
@@ -29,53 +22,53 @@ public class WechatSubscribeNotifyConfigService {
|
||||
this.configRepository = configRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取场景下的模板配置列表(带缓存)
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
* @param sceneKey 场景标识
|
||||
* @return 启用的模板配置列表
|
||||
*/
|
||||
public List<WechatSubscribeTemplateConfigEntity> listSceneTemplateConfigs(Long scenicId, String sceneKey) {
|
||||
List<WechatSubscribeSceneTemplateEntity> mappings =
|
||||
configRepository.listEffectiveSceneTemplateMappings(scenicId, sceneKey);
|
||||
if (CollectionUtils.isEmpty(mappings)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Set<String> templateKeys = mappings.stream()
|
||||
.map(WechatSubscribeSceneTemplateEntity::getTemplateKey)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String, WechatSubscribeTemplateConfigEntity> configMap =
|
||||
configRepository.getEffectiveTemplateConfigs(scenicId, templateKeys);
|
||||
|
||||
List<WechatSubscribeTemplateConfigEntity> result = new ArrayList<>();
|
||||
for (WechatSubscribeSceneTemplateEntity mapping : mappings) {
|
||||
WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey());
|
||||
if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) {
|
||||
continue;
|
||||
}
|
||||
result.add(cfg);
|
||||
}
|
||||
return result;
|
||||
return configRepository.getSceneTemplateConfigsCached(scenicId, sceneKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取事件下的模板配置列表(带缓存)
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
* @param eventKey 事件标识
|
||||
* @return 启用的模板配置列表
|
||||
*/
|
||||
public List<WechatSubscribeTemplateConfigEntity> listEventTemplateConfigs(Long scenicId, String eventKey) {
|
||||
List<WechatSubscribeEventTemplateEntity> mappings =
|
||||
configRepository.listEffectiveEventTemplateMappings(scenicId, eventKey);
|
||||
if (CollectionUtils.isEmpty(mappings)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return configRepository.getEventTemplateConfigsCached(scenicId, eventKey);
|
||||
}
|
||||
|
||||
Set<String> templateKeys = mappings.stream()
|
||||
.map(WechatSubscribeEventTemplateEntity::getTemplateKey)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<String, WechatSubscribeTemplateConfigEntity> configMap =
|
||||
configRepository.getEffectiveTemplateConfigs(scenicId, templateKeys);
|
||||
/**
|
||||
* 清除指定场景的配置缓存
|
||||
*/
|
||||
public void clearSceneConfigsCache(Long scenicId, String sceneKey) {
|
||||
configRepository.clearSceneTemplateConfigsCache(scenicId, sceneKey);
|
||||
}
|
||||
|
||||
List<WechatSubscribeTemplateConfigEntity> result = new ArrayList<>();
|
||||
for (WechatSubscribeEventTemplateEntity mapping : mappings) {
|
||||
WechatSubscribeTemplateConfigEntity cfg = configMap.get(mapping.getTemplateKey());
|
||||
if (cfg == null || !Objects.equals(cfg.getEnabled(), 1)) {
|
||||
continue;
|
||||
}
|
||||
result.add(cfg);
|
||||
}
|
||||
return result;
|
||||
/**
|
||||
* 清除指定事件的配置缓存
|
||||
*/
|
||||
public void clearEventConfigsCache(Long scenicId, String eventKey) {
|
||||
configRepository.clearEventTemplateConfigsCache(scenicId, eventKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除景区下所有订阅消息配置缓存
|
||||
*/
|
||||
public void clearAllConfigsCacheByScenic(Long scenicId) {
|
||||
configRepository.clearAllConfigsCacheByScenic(scenicId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有订阅消息配置缓存(全局配置变更时调用)
|
||||
*/
|
||||
public void clearAllConfigsCache() {
|
||||
configRepository.clearAllConfigsCache();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.ycwl.basic.model.pc.notify.req.WechatSubscribeSceneTemplateSaveReq;
|
||||
import com.ycwl.basic.model.pc.notify.req.WechatSubscribeSendLogPageReq;
|
||||
import com.ycwl.basic.model.pc.notify.req.WechatSubscribeTemplateConfigPageReq;
|
||||
import com.ycwl.basic.model.pc.notify.req.WechatSubscribeTemplateConfigSaveReq;
|
||||
import com.ycwl.basic.service.notify.WechatSubscribeNotifyConfigService;
|
||||
import com.ycwl.basic.service.pc.WechatSubscribeNotifyAdminService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.JacksonUtil;
|
||||
@@ -47,15 +48,18 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
private final WechatSubscribeSceneTemplateMapper sceneTemplateMapper;
|
||||
private final WechatSubscribeEventTemplateMapper eventTemplateMapper;
|
||||
private final WechatSubscribeSendLogMapper sendLogMapper;
|
||||
private final WechatSubscribeNotifyConfigService configService;
|
||||
|
||||
public WechatSubscribeNotifyAdminServiceImpl(WechatSubscribeTemplateConfigMapper templateConfigMapper,
|
||||
WechatSubscribeSceneTemplateMapper sceneTemplateMapper,
|
||||
WechatSubscribeEventTemplateMapper eventTemplateMapper,
|
||||
WechatSubscribeSendLogMapper sendLogMapper) {
|
||||
WechatSubscribeSendLogMapper sendLogMapper,
|
||||
WechatSubscribeNotifyConfigService configService) {
|
||||
this.templateConfigMapper = templateConfigMapper;
|
||||
this.sceneTemplateMapper = sceneTemplateMapper;
|
||||
this.eventTemplateMapper = eventTemplateMapper;
|
||||
this.sendLogMapper = sendLogMapper;
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,29 +127,33 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
entity.setDescription(StringUtils.trimToNull(req.getDescription()));
|
||||
entity.setUpdateTime(new Date());
|
||||
|
||||
boolean success;
|
||||
if (req.getId() != null) {
|
||||
WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectById(req.getId());
|
||||
if (existing == null) {
|
||||
return ApiResponse.fail("记录不存在");
|
||||
}
|
||||
entity.setId(req.getId());
|
||||
int updated = templateConfigMapper.updateById(entity);
|
||||
return ApiResponse.success(updated > 0);
|
||||
success = templateConfigMapper.updateById(entity) > 0;
|
||||
} else {
|
||||
// upsert by (template_key, scenic_id)
|
||||
WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectOne(new QueryWrapper<WechatSubscribeTemplateConfigEntity>()
|
||||
.eq("template_key", entity.getTemplateKey())
|
||||
.eq("scenic_id", entity.getScenicId()));
|
||||
if (existing != null) {
|
||||
entity.setId(existing.getId());
|
||||
success = templateConfigMapper.updateById(entity) > 0;
|
||||
} else {
|
||||
entity.setCreateTime(new Date());
|
||||
success = templateConfigMapper.insert(entity) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
// upsert by (template_key, scenic_id)
|
||||
WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectOne(new QueryWrapper<WechatSubscribeTemplateConfigEntity>()
|
||||
.eq("template_key", entity.getTemplateKey())
|
||||
.eq("scenic_id", entity.getScenicId()));
|
||||
if (existing != null) {
|
||||
entity.setId(existing.getId());
|
||||
int updated = templateConfigMapper.updateById(entity);
|
||||
return ApiResponse.success(updated > 0);
|
||||
// 清除缓存:模板配置变更影响场景和事件查询
|
||||
if (success) {
|
||||
clearConfigCacheByScenic(req.getScenicId());
|
||||
}
|
||||
|
||||
entity.setCreateTime(new Date());
|
||||
int inserted = templateConfigMapper.insert(entity);
|
||||
return ApiResponse.success(inserted > 0);
|
||||
return ApiResponse.success(success);
|
||||
} catch (DuplicateKeyException e) {
|
||||
return ApiResponse.fail("保存失败:唯一键冲突(templateKey+scenicId已存在)");
|
||||
} catch (Exception e) {
|
||||
@@ -160,7 +168,17 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
if (id == null) {
|
||||
return ApiResponse.fail("id不能为空");
|
||||
}
|
||||
return ApiResponse.success(templateConfigMapper.deleteById(id) > 0);
|
||||
// 先查询获取 scenicId 用于清除缓存
|
||||
WechatSubscribeTemplateConfigEntity existing = templateConfigMapper.selectById(id);
|
||||
if (existing == null) {
|
||||
return ApiResponse.success(false);
|
||||
}
|
||||
boolean success = templateConfigMapper.deleteById(id) > 0;
|
||||
// 清除缓存
|
||||
if (success) {
|
||||
clearConfigCacheByScenic(existing.getScenicId());
|
||||
}
|
||||
return ApiResponse.success(success);
|
||||
} catch (Exception e) {
|
||||
log.error("订阅消息|模板配置删除失败 id={}", id, e);
|
||||
return ApiResponse.fail("模板配置删除失败: " + e.getMessage());
|
||||
@@ -228,29 +246,33 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
entity.setSortOrder(Objects.requireNonNullElse(req.getSortOrder(), 0));
|
||||
entity.setUpdateTime(new Date());
|
||||
|
||||
boolean success;
|
||||
if (req.getId() != null) {
|
||||
WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectById(req.getId());
|
||||
if (existing == null) {
|
||||
return ApiResponse.fail("记录不存在");
|
||||
}
|
||||
entity.setId(req.getId());
|
||||
int updated = sceneTemplateMapper.updateById(entity);
|
||||
return ApiResponse.success(updated > 0);
|
||||
success = sceneTemplateMapper.updateById(entity) > 0;
|
||||
} else {
|
||||
WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectOne(new QueryWrapper<WechatSubscribeSceneTemplateEntity>()
|
||||
.eq("scene_key", entity.getSceneKey())
|
||||
.eq("template_key", entity.getTemplateKey())
|
||||
.eq("scenic_id", entity.getScenicId()));
|
||||
if (existing != null) {
|
||||
entity.setId(existing.getId());
|
||||
success = sceneTemplateMapper.updateById(entity) > 0;
|
||||
} else {
|
||||
entity.setCreateTime(new Date());
|
||||
success = sceneTemplateMapper.insert(entity) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectOne(new QueryWrapper<WechatSubscribeSceneTemplateEntity>()
|
||||
.eq("scene_key", entity.getSceneKey())
|
||||
.eq("template_key", entity.getTemplateKey())
|
||||
.eq("scenic_id", entity.getScenicId()));
|
||||
if (existing != null) {
|
||||
entity.setId(existing.getId());
|
||||
int updated = sceneTemplateMapper.updateById(entity);
|
||||
return ApiResponse.success(updated > 0);
|
||||
// 清除场景配置缓存
|
||||
if (success) {
|
||||
configService.clearSceneConfigsCache(req.getScenicId(), req.getSceneKey().trim());
|
||||
}
|
||||
|
||||
entity.setCreateTime(new Date());
|
||||
int inserted = sceneTemplateMapper.insert(entity);
|
||||
return ApiResponse.success(inserted > 0);
|
||||
return ApiResponse.success(success);
|
||||
} catch (DuplicateKeyException e) {
|
||||
return ApiResponse.fail("保存失败:唯一键冲突(sceneKey+templateKey+scenicId已存在)");
|
||||
} catch (Exception e) {
|
||||
@@ -265,7 +287,17 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
if (id == null) {
|
||||
return ApiResponse.fail("id不能为空");
|
||||
}
|
||||
return ApiResponse.success(sceneTemplateMapper.deleteById(id) > 0);
|
||||
// 先查询获取 scenicId 和 sceneKey 用于清除缓存
|
||||
WechatSubscribeSceneTemplateEntity existing = sceneTemplateMapper.selectById(id);
|
||||
if (existing == null) {
|
||||
return ApiResponse.success(false);
|
||||
}
|
||||
boolean success = sceneTemplateMapper.deleteById(id) > 0;
|
||||
// 清除场景配置缓存
|
||||
if (success) {
|
||||
configService.clearSceneConfigsCache(existing.getScenicId(), existing.getSceneKey());
|
||||
}
|
||||
return ApiResponse.success(success);
|
||||
} catch (Exception e) {
|
||||
log.error("订阅消息|场景映射删除失败 id={}", id, e);
|
||||
return ApiResponse.fail("场景映射删除失败: " + e.getMessage());
|
||||
@@ -335,29 +367,33 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
entity.setDedupSeconds(Objects.requireNonNullElse(req.getDedupSeconds(), 0));
|
||||
entity.setUpdateTime(new Date());
|
||||
|
||||
boolean success;
|
||||
if (req.getId() != null) {
|
||||
WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectById(req.getId());
|
||||
if (existing == null) {
|
||||
return ApiResponse.fail("记录不存在");
|
||||
}
|
||||
entity.setId(req.getId());
|
||||
int updated = eventTemplateMapper.updateById(entity);
|
||||
return ApiResponse.success(updated > 0);
|
||||
success = eventTemplateMapper.updateById(entity) > 0;
|
||||
} else {
|
||||
WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectOne(new QueryWrapper<WechatSubscribeEventTemplateEntity>()
|
||||
.eq("event_key", entity.getEventKey())
|
||||
.eq("template_key", entity.getTemplateKey())
|
||||
.eq("scenic_id", entity.getScenicId()));
|
||||
if (existing != null) {
|
||||
entity.setId(existing.getId());
|
||||
success = eventTemplateMapper.updateById(entity) > 0;
|
||||
} else {
|
||||
entity.setCreateTime(new Date());
|
||||
success = eventTemplateMapper.insert(entity) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectOne(new QueryWrapper<WechatSubscribeEventTemplateEntity>()
|
||||
.eq("event_key", entity.getEventKey())
|
||||
.eq("template_key", entity.getTemplateKey())
|
||||
.eq("scenic_id", entity.getScenicId()));
|
||||
if (existing != null) {
|
||||
entity.setId(existing.getId());
|
||||
int updated = eventTemplateMapper.updateById(entity);
|
||||
return ApiResponse.success(updated > 0);
|
||||
// 清除事件配置缓存
|
||||
if (success) {
|
||||
configService.clearEventConfigsCache(req.getScenicId(), req.getEventKey().trim());
|
||||
}
|
||||
|
||||
entity.setCreateTime(new Date());
|
||||
int inserted = eventTemplateMapper.insert(entity);
|
||||
return ApiResponse.success(inserted > 0);
|
||||
return ApiResponse.success(success);
|
||||
} catch (DuplicateKeyException e) {
|
||||
return ApiResponse.fail("保存失败:唯一键冲突(eventKey+templateKey+scenicId已存在)");
|
||||
} catch (Exception e) {
|
||||
@@ -372,7 +408,17 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
if (id == null) {
|
||||
return ApiResponse.fail("id不能为空");
|
||||
}
|
||||
return ApiResponse.success(eventTemplateMapper.deleteById(id) > 0);
|
||||
// 先查询获取 scenicId 和 eventKey 用于清除缓存
|
||||
WechatSubscribeEventTemplateEntity existing = eventTemplateMapper.selectById(id);
|
||||
if (existing == null) {
|
||||
return ApiResponse.success(false);
|
||||
}
|
||||
boolean success = eventTemplateMapper.deleteById(id) > 0;
|
||||
// 清除事件配置缓存
|
||||
if (success) {
|
||||
configService.clearEventConfigsCache(existing.getScenicId(), existing.getEventKey());
|
||||
}
|
||||
return ApiResponse.success(success);
|
||||
} catch (Exception e) {
|
||||
log.error("订阅消息|事件映射删除失败 id={}", id, e);
|
||||
return ApiResponse.fail("事件映射删除失败: " + e.getMessage());
|
||||
@@ -529,5 +575,23 @@ public class WechatSubscribeNotifyAdminServiceImpl implements WechatSubscribeNot
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除景区相关的配置缓存
|
||||
* 模板配置变更会影响场景和事件的查询结果,需要清除该景区下所有缓存
|
||||
*
|
||||
* @param scenicId 景区ID
|
||||
*/
|
||||
private void clearConfigCacheByScenic(Long scenicId) {
|
||||
if (scenicId == null) {
|
||||
return;
|
||||
}
|
||||
// scenicId=0 表示默认配置,变更时需要清除所有缓存
|
||||
if (scenicId == 0L) {
|
||||
configService.clearAllConfigsCache();
|
||||
} else {
|
||||
configService.clearAllConfigsCacheByScenic(scenicId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user