# 缓存序列化结构检测 — 配置说明 > **双层配置**:工具 jar 内置 `default-config.yaml`(默认) + 业务仓库 `.gitea/config/cache-schema-check-config.yaml`(覆盖) > 工具坐标:`com.codechecker:cache-schema-checker:1.0.0` > 主类:`com.codechecker.cache.cli.CacheSchemaCheckerMain` --- ## 1. 配置合并机制 ```text jar 内 default-config.yaml(工具仓维护) ↓ 深度合并 业务仓 cache-schema-check-config.yaml(业务仓维护) ↓ 最终生效配置 ``` - 业务配置**仅需写差异项**,不必复制全部默认规则 - 升级 jar 时,默认忽略规则/检测模式自动跟随工具版本演进 - 业务仓必须存在 `--config` 指定的配置文件(可为仅含 `mode` 的最小文件) ### 1.1 业务仓最小配置示例 ```yaml # jnpf-java-cloud/.gitea/config/cache-schema-check-config.yaml enabled: true mode: notify notify: enabled: true # 推荐直接写完整 Webhook;也可用环境变量在流水线注入 webhook_url: "" include_modules: - jnpf-tenant ``` 流水线通常把 Secret 注入环境或配置文件中的 `webhook_url`。兼容旧字段:`webhook_env`(值为 `http` 开头时当作 URL 使用)。 ### 1.2 工具内置默认配置(jar 内 default-config.yaml) 由 `redisCheck` 仓库维护,随 jar 发布,默认包含: - `detection.patterns`:**W01~W05**(JSON 字符串写入 + Template 直写 + Hash) - `ignore.key_patterns`(锁 / 计数器 / token) - `detection.min_confidence`、`max_field_depth` - `mode: notify`、`enabled: true` --- ## 2. 业务仓完整配置示例 ```yaml # 总开关:false 时不执行检测、不发通知、流水线直接通过 enabled: true # 运行模式 # notify - 仅通知,不阻断流水线 # block - 检测到结构变更即阻断流水线(exit 1) mode: notify # 是否扫描测试代码(已确认:不扫描) scan_test_sources: false # 源码扫描根目录(仅 main,不含 test) source_roots: - "src/main/java" # 通知配置 notify: enabled: true # Webhook 完整 URL(优先) webhook_url: "" # 兼容旧字段:值为 http 开头时视为 URL # webhook_env: WECOM_ROBOT_WEBHOOK # 无变更时是否也发通知(一般 false) notify_on_clean: false # 消息标题前缀 title_prefix: "[缓存结构变更]" # 忽略规则 ignore: # 忽略的 key 模式(glob) key_patterns: - "*:lock" - "*:lock:*" - "*lock*" - "loginCount:*" - "Authorization:*" # 忽略的文件路径模式 file_patterns: - "**/test/**" # 忽略的写入方法(类全名#方法名) writer_methods: [] # 检测规则 detection: # 启用的写入模式(默认已全部开启) patterns: - W01 # redisUtil.insert + JSON.toJSONString - W02 # redisTemplate.opsForValue().set + JSON.toJSONString - W03 # stringRedisTemplate + JsonUtil.getObjectToString - W04 # redisTemplate 直写对象 - W05 # opsForHash().put # 类型推断最低置信度,低于此值仅输出 P2 提示 min_confidence: 0.6 # 字段展开最大深度(防止循环引用死循环) max_field_depth: 8 # 严重级别覆盖(可选) severity_overrides: FIELD_ADDED: P1 WRITE_POINT_ADDED: P2 # 人工补充映射(自动推断失败或需精确指定时使用) manual_mappings: - id: tenant-db-content writer_method: "jnpf.util.TenantDbContentCacheHelper#cacheSuccess" key_pattern: "tenant:db:content:*" value_type: "jnpf.util.TenantDbContentCacheHelper.CacheEnvelope" description: "租户库信息缓存" - id: attendance-base-setting writer_method: "jnpf.attendance.service.impl.AttendanceBaseSettingServiceImpl#getStringAttendanceBaseSettingMap" key_pattern: "fbt:attendance:base_setting:cache:*" value_type: "java.util.Map" description: "考勤基础设置缓存(Map)" # 抑制规则(已知误报) suppressions: - id: ignore-export-progress key_pattern: "file:download:user:progress:*" reason: "导出进度缓存,结构变更不影响业务读取" # 模块过滤(可选,默认扫描全部模块) include_modules: - jnpf-tenant - jnpf-ftb - jnpf-file - fantaibao-data-analysis # exclude_modules: [] ``` --- ## 3. 配置项说明 ### 3.1 enabled 总开关。默认 `true`。 | 值 | 行为 | |----|------| | `true` | 正常执行检测(再按 `mode` / `notify` 行为) | | `false` | 跳过检测与通知,流水线 `exit 0`(与 `notify.enabled` 无关) | 临时关闭时可仅改此项,无需删除 workflow。 ### 3.2 mode | 值 | 行为 | |----|------| | `notify` | 检测到变更 → 发企微 → `exit 0` | | `block` | 检测到任意结构变更 → 发企微 → `exit 1` | 建议上线初期仍使用 `mode: notify` 观察误报情况,确认稳定后再切换: ```yaml mode: block ``` ### 3.3 notify | 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `enabled` | boolean | true | 是否发企微 | | `webhook_url` | string | `""` | 企微机器人 Webhook 完整 URL(优先) | | `webhook_env` | string | — | 兼容旧字段;值为 `http` 开头时当作 URL | | `notify_on_clean` | boolean | false | 无变更时是否通知 | | `title_prefix` | string | [缓存结构变更] | 消息标题前缀 | ### 3.4 ignore.key_patterns 支持 glob: - `*` 匹配单层 - `**` 匹配多层 内置/代码层常见过滤: - 分布式锁 key(配置 glob + 方法名忽略) - 登录计数、session/token - 琐碎 value:字面量、`"1"`、`UUID.randomUUID()` 等 - 方法:`setIfAbsent` / `increment` / `delete` / `expire` 等 ### 3.5 detection.patterns | 模式 | 说明 | 状态 | |------|------|------| | W01 | `redisUtil.insert(key, JSON.toJSONString(x), ttl)` | 已启用 | | W02 | `redisTemplate.opsForValue().set(key, JSON.toJSONString(x), ...)` | 已启用 | | W03 | `stringRedisTemplate.opsForValue().set(key, JsonUtil.getObjectToString(x), ...)` | 已启用 | | W04 | `redisTemplate.opsForValue().set(key, obj, ...)` 直写对象 | 已启用(Phase 2) | | W05 | `redisTemplate.opsForHash().put(key, field, obj)` | 已启用(Phase 2) | 业务仓可通过只声明子集暂时关闭某些模式,例如仅保留 JSON 写入: ```yaml detection: patterns: [W01, W02, W03] ``` ### 3.6 manual_mappings 当自动推断不准确时使用。匹配优先级 **高于** 自动推断(按 `类全名#方法名` 覆盖 key 模式与 value 类型)。 | 字段 | 必填 | 说明 | |------|------|------| | `id` | 是 | 唯一标识 | | `writer_method` | 否 | `类全名#方法名`,精确匹配写入点 | | `key_pattern` | 否 | 精确 key 模式 | | `value_type` | 否 | 强制指定 value 类型 | | `description` | 否 | 备注 | ### 3.7 suppressions 用于屏蔽已知可接受的变更: ```yaml suppressions: - id: my-suppression key_pattern: "file:download:user:progress:*" change_types: - FIELD_ADDED reason: "新增字段向后兼容" ``` ### 3.8 include_modules / exclude_modules | 字段 | 说明 | |------|------| | `include_modules` | 非空时仅扫描列出的顶层模块;空表示全仓 | | `exclude_modules` | 始终排除的顶层模块 | 顶层模块取路径第一段,例如 `jnpf-tenant/jnpf-tenant-biz/src/main/java/...` → `jnpf-tenant`。 --- ## 4. 环境变量 / Secret | 变量 | 必填 | 说明 | |------|------|------| | `WECOM_ROBOT_WEBHOOK` | 视流水线写法 | 可将 Secret 写入配置中的 `webhook_url`,或在启动前注入 | 在 Gitea 仓库 Settings → Secrets 中配置。 --- ## 5. 企微消息格式 ### 5.1 结构说明 - 抬头:仓库、分支、提交、提交人、时间(**不再**展示 mode / P0P1P2 汇总) - 正文:按 **一个 Redis Key 一块**,展示位置、类型与前后序列化骨架 - 超长(UTF-8 > 4096 字节)时按 key **拆成多条**消息依次发送 - CI 控制台另打「字段明细」(含 P0/P1/P2),企微侧不分级别 ### 5.2 字段高亮颜色 | 变更 | 企微颜色 | Markdown | |------|----------|----------| | 字段删除(标在旧骨架) | 橙色 | `` | | 字段新增 / 包装层(标在新骨架) | 绿色 | `` | | 路径迁移 | 旧橙 / 新绿 | 同上 | | key 未解析提示 | 灰色 | `(key 未解析)` | ### 5.3 示例(已解析 key) ```markdown ## [缓存结构变更] jnpf-java-cloud > **分支**: code/redis_change_detection_v1.0 > **提交**: cedd161c → 67c8a6eb > **提交人**: dongzi > **时间**: 2026-07-13 16:54:17 - Key --> `tenant:db:content:*` > **位置**: `TenantDbContentCacheHelper#cacheSuccess:92` > **类型**: `CacheEnvelope` > **value值由:** “{"dbName":"","linkList":[{"id":""}]}” > **变更为:** “…(仅新增/迁移字段片段带 绿色)…” ``` 实际发送时仅对改动属性片段染色:新增 → `info`(绿),删除 → `warning`(橙)。 ### 5.4 示例(key 未解析) ```markdown - Key --> `req.getKey()` (key 未解析) > **位置**: `ClockInXxxService#export:128` > **类型**: `List` > **value值由:** “{"a":""}” > **变更为:** “…新增字段带绿色高亮…” ``` 未解析时按「写入位置 + key 表达式」拆分聚合,避免多个未知 key 串在一起。 --- ## 6. 推荐上线配置 ### 6.1 观察期(第 1 周) 业务仓默认配置: ```yaml enabled: true mode: notify notify: enabled: true webhook_url: "" # 由流水线写入真实 Webhook include_modules: - jnpf-tenant ``` 观察满 1 周、确认误报可接受后,手动切换: ```yaml mode: block include_modules: [] # 扩至全仓 ``` ### 6.2 全量启用(观察期结束后) ```yaml enabled: true mode: block include_modules: [] # 空表示全部模块 detection: patterns: [W01, W02, W03, W04, W05] ```