【mzt-biz-log】-「谁」在「什么时间」对「什么」做了「什么事」
一、组件简介与核心场景
mzt-biz-log 是开源的轻量级操作日志组件,通过注解驱动实现 “谁在何时对何事执行何种操作” 的全链路记录,适配微服务架构,支持租户隔离、条件记录、自定义存储等核心能力。
典型应用场景:接口调用日志追踪、用户 / 运营操作审计、业务数据变更记录。
二、基础场景实战:场馆分区管理系统日志记录
1. 环境准备(Spring Boot 项目)
(1)引入依赖
<dependency> <groupId>io.github.mouzt</groupId> <artifactId>bizlog-sdk</artifactId> <version>3.0.6</version> </dependency>
(2)激活组件
在服务启动类添加注解,设置租户标识(建议与服务名一致):
@SpringBootApplication
@EnableLogRecord(tenant = "venue-service") // 租户标识:场馆服务
public class VenueApplication {
public static void main(String[] args) {
SpringApplication.run(VenueApplication.class, args);
}
}
2. 接口日志配置:分区新增接口
针对/partition/save接口,记录操作人、分区信息、执行结果:
@RestController
@RequestMapping("/partition")
public class PartitionController {
@Autowired
private PartitionService partitionService;
/**
* 新增场馆分区
* 日志记录:操作人、分区详情、成功/失败状态
*/
@PostMapping("/save")
@LogRecord(
bizNo = "{{#id}}", // 业务ID:分区ID(动态获取)
type = "PARTITION_CREATE", // 日志类型:分区创建
subType = "ADMIN", // 子类型:管理员操作
operator = "{{T(com.venue.context.UserContext).getUsername()}}", // 操作人
success = """
管理员{{#operator}}创建分区成功:
场馆ID:{{#partitionDO.venueId}},
分区名称:{{#partitionDO.name}},
分区类型:{PartitionTypeEnumParse{#partitionDO.type}},
场数量:{{#partitionDO.num}}
""", // 成功模板(含枚举解析)
fail = "管理员{{#operator}}创建分区失败,原因:{{#_errorMsg}}", // 失败模板
extra = "{{#toJsonString(partitionDO)}}", // 额外信息:请求参数JSON
condition = "#partitionDO.num > 0" // 条件记录:仅记录场数量>0的请求
)
public Result save(@RequestBody PartitionDO partitionDO) {
partitionService.save(partitionDO);
// 动态设置bizNo(分区ID由数据库生成)
LogRecordContext.putVariable("id", partitionDO.getId());
return Result.success();
}
}
3. 高级功能:枚举解析器
将分区类型数值(1/2/3)转换为业务语义文本(篮球 / 足球 / 羽毛球):
// 1. 定义枚举
@Getter
public enum PartitionTypeEnum {
BASKETBALL(1, "篮球"),
FOOTBALL(2, "足球"),
BADMINTON(3, "羽毛球");
private final int type;
private final String name;
// 省略构造器与查找方法
}
// 2. 实现自定义解析器
@Component
public class PartitionTypeEnumParse implements IParseFunction {
@Override
public String functionName() {
return "PartitionTypeEnumParse"; // 解析器名称(与模板对应)
}
@Override
public String apply(Object value) {
int type = Integer.parseInt(value.toString());
return PartitionTypeEnum.findNameByType(type);
}
}
三、进阶场景:自定义日志存储与查询
1. 设计日志表结构
CREATE TABLE `mt_biz_log` ( `id` bigint AUTO_INCREMENT PRIMARY KEY, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `tenant` varchar(50) COMMENT '租户标识', `type` varchar(50) COMMENT '日志类型', `sub_type` varchar(50) COMMENT '日志子类型', `operator` varchar(50) COMMENT '操作人', `biz_no` varchar(64) COMMENT '业务ID(分区ID/订单ID)', `action` longtext COMMENT '操作描述', `extra` longtext COMMENT '额外信息', `status` tinyint DEFAULT 0 COMMENT '0成功 1失败' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. 实现存储服务
继承ILogRecordService接口,自定义持久化逻辑:
@Service
public class VenueBizLogService implements ILogRecordService {
@Autowired
private MtBizLogMapper logMapper;
// 日志持久化
@Override
public void record(LogRecord logRecord) {
MtBizLog log = new MtBizLog();
log.setTenant(logRecord.getTenant());
log.setType(logRecord.getType());
log.setSubType(logRecord.getSubType());
log.setOperator(logRecord.getOperator());
log.setBizNo(logRecord.getBizNo());
log.setAction(logRecord.getAction());
log.setExtra(logRecord.getExtra());
log.setStatus(logRecord.isFail() ? 1 : 0);
logMapper.insert(log);
}
// 按业务ID查询日志
@Override
public List<MtBizLog> queryLogByBizNo(String bizNo, String type, String subType) {
return logMapper.selectByBizNoAndType(bizNo, type, subType);
}
// 其他查询方法省略...
}
四、效果验证
1. 成功场景日志输出
当管理员admin创建 “篮球场 A 区”(场数量 4)时,日志表记录如下:
| tenant | type | operator | biz_no | action | status |
|---|---|---|---|---|---|
| venue-service | PARTITION_CREATE | admin | 1868205198032568320 | 管理员 admin 创建分区成功:场馆 ID:12345,分区名称:篮球场 A 区,分区类型:篮球,场数量:4 | 0 |
2. 失败场景日志输出
当请求参数num=-1(触发条件过滤)或抛出异常时:
-
条件不满足:不生成日志;
-
系统异常:action字段记录 “管理员 admin 创建分区失败,原因:数据库连接超时”,status=1。
五、核心特性总结
-
极简集成:2 步激活(依赖 + 启动类注解),无需侵入业务逻辑;
-
动态模板:SpEL 表达式支持变量、解析器、JSON 序列化;
-
多维管控:租户隔离、条件记录、类型分层满足复杂场景;
-
高度扩展:自定义存储(MySQL/ES)、解析器适配业务需求。
1235

被折叠的 条评论
为什么被折叠?



