SpringBoot-Auto-Trace-Data-Change
在企业级应用中,关键配置、业务数据变更的审计追踪是一个常见需求。无论是金融系统、电商平台还是配置管理,都需要回答 几个基本问题:谁改了数据、什么时候改的、改了什么。
背景痛点
传统手工审计的问题
最直接的实现方式是在每个业务方法中手动记录审计日志:
public void updatePrice(Long productId, BigDecimal newPrice) {
Product old = productRepository.findById(productId).get();
productRepository.updatePrice(productId, newPrice);
// 手动记录变更
auditService.save("价格从 " + old.getPrice() + " 改为 " + newPrice);
}
这种做法在项目初期还能应付,但随着业务复杂度增加,会暴露出几个明显问题:
- 代码重复 :每个需要审计的方法都要写类似逻辑
- 维护困难 :业务字段变更时,审计逻辑需要同步修改
- 格式不统一 :不同开发者写的审计格式可能不一致
- 查询不便 :字符串拼接的日志难以进行结构化查询
- 业务代码污染 :审计逻辑与业务逻辑耦合在一起
实际遇到的问题
- 产品价格改错了,查了半天日志才找到是谁改的
- 配置被误删了,想恢复时发现没有详细的变更记录
- 审计要求越来越严格,手工记录的日志格式不规范
需求分析
基于实际需求,审计功能应具备以下特性:
核心需求
- 零侵入性 :业务代码不需要关心审计逻辑
- 自动化 :通过配置或注解就能启用审计功能
- 精确记录 :字段级别的变更追踪
- 结构化存储 :便于查询和分析的格式
- 完整信息 :包含操作人、时间、操作类型等元数据
技术选型
考虑本方案选择使用 Javers 作为核心组件,主要考虑:
- 专业的对象差异比对算法
- Spring Boot 集成简单
- 支持多种存储后端
- JSON 输出友好
设计思路
整体架构
我们采用 AOP + 注解的设计模式:
┌─────────────────┐
│ Controller │
└─────────┬───────┘
│ AOP 拦截
┌─────────▼───────┐
│ Service │ ← 业务逻辑保持不变
└─────────┬───────┘
│
┌─────────▼───────┐
│ AuditAspect │ ← 统一处理审计逻辑
└─────────┬───────┘
│
┌─────────▼───────┐
│ Javers Core │ ← 对象差异比对
└─────────┬───────┘
│
┌─────────▼───────┐
│ Audit Storage │ ← 结构化存储