fix(sensitive-word): 配置缓存改存 JSON 避免 L2 ClassCast

- PlatformSensitiveWordConfig 缓存字符串后 toBean,避开 LinkedHashMap
- MapperScan 补齐;试检命中来源识别 /client/;List 用 getFirst
This commit is contained in:
DaxPay Dev
2026-07-16 10:21:44 +08:00
parent 357ee494ee
commit eba797dd71
3 changed files with 27 additions and 6 deletions

View File

@@ -1,11 +1,14 @@
package cn.daxpay.open.platform.capability.sensitiveword;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
/// # 敏感词能力自动配置
///
@ComponentScan
@MapperScan(annotationClass = Mapper.class)
@AutoConfiguration
public class SensitiveWordAutoConfiguration {
}

View File

@@ -84,7 +84,7 @@ public class SensitiveWordCheckService {
if (CollUtil.isEmpty(hits)) {
return;
}
String hitWord = hits.get(0);
String hitWord = hits.getFirst();
SensitiveWordSceneEnum sc = scene == null ? SensitiveWordSceneEnum.GENERAL : scene;
if (sensitiveWordPolicy.isRecordHit()) {
try {
@@ -106,7 +106,7 @@ public class SensitiveWordCheckService {
List<String> hits = findHits(text, false);
if (recordHit && CollUtil.isNotEmpty(hits)) {
try {
recordHit(text, hits.get(0), SensitiveWordSceneEnum.MANUAL_CHECK);
recordHit(text, hits.getFirst(), SensitiveWordSceneEnum.MANUAL_CHECK);
} catch (Exception e) {
log.warn("试检写命中失败: {}", e.getMessage());
}
@@ -171,7 +171,7 @@ public class SensitiveWordCheckService {
if (path.startsWith("/app-admin/")) {
return SensitiveWordSourceEnum.APP_ADMIN.getCode();
}
if (path.startsWith("/unipay/") || path.startsWith("/gateway/")) {
if (path.startsWith("/unipay/") || path.startsWith("/client/")) {
return SensitiveWordSourceEnum.UNIPAY.getCode();
}
} catch (Exception ignored) {

View File

@@ -1,12 +1,14 @@
package cn.daxpay.open.platform.system.service.config.infra;
import cn.daxpay.open.platform.capability.sensitiveword.policy.SensitiveWordPolicy;
import cn.daxpay.open.platform.common.json.util.JacksonUtil;
import cn.daxpay.open.platform.system.convert.config.infra.PlatformSensitiveWordConfigConvert;
import cn.daxpay.open.platform.system.entity.config.platform.infra.PlatformSensitiveWordConfig;
import cn.daxpay.open.platform.system.enums.PlatformConfigTypeEnum;
import cn.daxpay.open.platform.system.param.config.infra.PlatformSensitiveWordConfigParam;
import cn.daxpay.open.platform.system.result.config.infra.PlatformSensitiveWordConfigResult;
import cn.daxpay.open.platform.system.service.config.SystemPlatformConfigService;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
@@ -17,6 +19,9 @@ import org.springframework.stereotype.Service;
/// # 平台敏感词策略服务
///
/// 同时实现 [SensitiveWordPolicy],供 capability 运行时读取.
///
/// 缓存存 **JSON 字符串** 而非实体Redis 缓存反序列化为 `Object.class`
/// JSON 对象 → LinkedHashMap直接缓存 POJO 会在 L2 回填后 ClassCastException.
@Slf4j
@Primary
@Service
@@ -36,13 +41,26 @@ public class PlatformSensitiveWordConfigService implements SensitiveWordPolicy {
this.self = self;
}
/// 获取配置实体(带默认
@Cacheable(value = CACHE_NAME, key = "'current'")
public PlatformSensitiveWordConfig getConfig() {
/// 缓存配置 JSONL2 安全类型Stringkey 带 :json 避免命中旧版 POJO 缓存
@Cacheable(value = CACHE_NAME, key = "'current:json'")
public String getConfigJson() {
PlatformSensitiveWordConfig config = systemConfigService.getOrCreateConfig(
PlatformConfigTypeEnum.SENSITIVE_WORD,
PlatformSensitiveWordConfig.class,
new PlatformSensitiveWordConfig());
if (config == null) {
config = new PlatformSensitiveWordConfig();
}
return JacksonUtil.toJson(config);
}
/// 获取配置实体(带默认);从缓存 JSON 显式还原类型
public PlatformSensitiveWordConfig getConfig() {
String json = self.getConfigJson();
if (StrUtil.isBlank(json)) {
return new PlatformSensitiveWordConfig();
}
PlatformSensitiveWordConfig config = JacksonUtil.toBean(json, PlatformSensitiveWordConfig.class);
return config == null ? new PlatformSensitiveWordConfig() : config;
}