mzt-biz-logSpringBoot应用操作日志管理的终极解决方案【免费下载链接】mzt-biz-log支持Springboot基于注解的可使用变量、可以自定义函数的通用操作日志组件项目地址: https://gitcode.com/gh_mirrors/mz/mzt-biz-logmzt-biz-log是一款基于SpringBoot注解驱动的通用操作日志组件通过声明式注解和强大的表达式引擎彻底解决了企业级应用中谁在什么时间对什么做了什么的日志记录难题。该组件采用非侵入式设计支持灵活的变量解析、自定义函数扩展和智能对象差异比对让开发者能够以最简洁的方式实现完整的操作日志体系。 核心价值与适用场景为什么需要专业的操作日志组件在复杂的业务系统中操作日志不仅是问题排查的依据更是业务审计、用户行为分析、数据变更追踪的关键基础设施。传统的手动日志记录方式存在以下痛点代码侵入性强业务逻辑与日志记录代码混杂维护困难格式不统一不同开发者记录的日志格式各异难以标准化信息不完整关键业务信息遗漏无法满足审计需求性能影响大频繁的日志IO操作影响系统响应速度mzt-biz-log通过注解驱动的方式将操作日志的记录逻辑从业务代码中完全解耦提供了一套标准化的日志记录方案。典型应用场景电商系统订单追踪记录用户下单、支付、发货、退款全流程操作CRM客户关系管理追踪客户信息变更、跟进记录、合同状态变化权限管理系统记录用户权限分配、角色变更、数据访问行为财务系统审计满足合规要求记录所有财务数据变更历史配置管理中心追踪系统配置变更快速定位配置问题️ 架构设计与核心原理整体架构概览mzt-biz-log采用经典的AOP面向切面编程架构核心模块包括bizlog-sdk/ ├── starter/ # SpringBoot自动配置 │ ├── annotation/ # 核心注解定义 │ ├── configuration/ # 自动配置类 │ ├── diff/ # 对象差异比对 │ └── support/ # AOP切面支持 ├── service/ # 服务接口与实现 │ ├── impl/ # 默认实现 │ └── interfaces/ # 扩展接口 └── beans/ # 核心数据模型核心注解解析LogRecord注解是整个组件的核心其设计充分考虑了实际业务需求Repeatable(LogRecords.class) Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) public interface LogRecord { String success(); // 成功日志模板 String fail() default ; // 失败日志模板 String operator() default ; // 操作人 String type(); // 日志类型 String subType() default ; // 子类型 String bizNo(); // 业务标识 String extra() default ; // 额外信息 String condition() default ; // 记录条件 String successCondition() default ; // 成功条件 }AOP拦截机制实现组件通过BeanFactoryLogRecordAdvisor和LogRecordInterceptor实现方法拦截// 关键拦截器实现 public class LogRecordInterceptor implements MethodInterceptor { Override public Object invoke(MethodInvocation invocation) throws Throwable { // 1. 解析注解配置 CollectionLogRecordOperation operations logRecordOperationSource.computeLogRecordOperations( invocation.getMethod(), invocation.getThis().getClass()); // 2. 执行业务方法 Object result invocation.proceed(); // 3. 记录操作日志 for (LogRecordOperation operation : operations) { logRecordService.record(buildLogRecord(operation, result)); } return result; } } 三步集成与基础配置第一步添加Maven依赖dependency groupIdio.github.mouzt/groupId artifactIdbizlog-sdk/artifactId version3.0.7-SNAPSHOT/version /dependency第二步启用日志记录功能在SpringBoot启动类上添加EnableLogRecord注解SpringBootApplication EnableTransactionManagement(order 0) // 确保事务优先级 EnableLogRecord( tenant your-app-name, // 租户标识 joinTransaction true // 与业务事务一起回滚 ) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }第三步基础配置文件在application.yml中配置基本参数mzt: log: record: enabled: true diff-log: false # 对象无变化时不记录日志 update-template: __fieldName从__sourceValue修改为__targetValue use-equals-method: java.time.LocalDate,java.time.Instant 高级功能与自定义扩展智能对象差异比对mzt-biz-log提供了强大的对象差异比对功能能够自动识别对象字段变化并生成易读的日志Data DiffLogAllFields // 自动记录所有字段变化 public class User { private Long id; DiffLogField(name 用户姓名) private String name; DIffLogIgnore // 忽略此字段的差异记录 private String password; DiffLogField(name 性别, function SEX) // 使用自定义函数处理 private String gender; private Address address; Data public static class Address { DiffLogField(name 省份) private String province; DiffLogField(name 城市) private String city; } } // 业务方法中使用 LogRecord( success 更新了用户信息{_DIFF{#oldUser, #newUser}}, type USER, bizNo {{#newUser.id}} ) public void updateUser(User oldUser, User newUser) { userRepository.update(newUser); }生成的日志示例更新了用户信息【用户姓名】从【张三】修改为【李四】【性别】从【男】修改为【女】【地址的城市】从【北京】修改为【上海】自定义函数扩展机制组件支持灵活的自定义函数扩展满足复杂业务场景需求Component public class DepartmentParseFunction implements IParseFunction { Autowired Lazy // 解决循环依赖问题 private DepartmentService departmentService; Override public String functionName() { return DEPARTMENT; } Override public boolean executeBefore() { return false; // 方法执行后调用 } Override public String apply(Object value) { if (value null) return 未知部门; Long deptId Long.parseLong(value.toString()); Department dept departmentService.findById(deptId); return dept ! null ? dept.getName() ( deptId ) : 部门不存在; } } // 使用自定义函数 LogRecord( success 调整了用户部门{DEPARTMENT{#deptId}}, type USER_MANAGE, bizNo {{#userId}} ) public void changeUserDepartment(Long userId, Long deptId) { // 业务逻辑 }上下文变量与跨方法传递组件支持灵活的上下文变量管理可以在方法间传递变量LogRecord( success {{#operator}}创建了项目{{#project.name}}负责人{USER{#project.ownerId}}, type PROJECT, bizNo {{#project.id}} ) public Project createProject(Project project) { // 设置操作人上下文 LogRecordContext.putVariable(operator, getCurrentUser().getName()); // 设置全局变量跨方法可用 LogRecordContext.putGlobalVariable(tenantId, getCurrentTenantId()); // 业务逻辑 return projectRepository.save(project); } // 在其他方法中可以访问全局变量 LogRecord( success 为项目{{#project.name}}添加了成员{USER{#userId}}, type PROJECT, bizNo {{#project.id}} ) public void addProjectMember(Long projectId, Long userId) { // 可以访问之前设置的全局变量 String tenantId LogRecordContext.getGlobalVariable(tenantId); // 业务逻辑 } 场景化用例实战用例一电商订单全链路追踪Service public class OrderServiceImpl implements OrderService { LogRecord( success 用户{{#user.name}}创建了订单商品{{#order.items}}总金额{{#order.amount}}元, fail 创建订单失败{{#_errorMsg}}, type ORDER_CREATE, bizNo {{#order.orderNo}}, extra {{#order.toJson()}} ) public Order createOrder(Order order, User user) { // 订单创建逻辑 return orderRepository.save(order); } LogRecord( success 订单状态从{ORDER_STATUS{#oldStatus}}变更为{ORDER_STATUS{#newStatus}}, type ORDER_UPDATE, bizNo {{#orderNo}}, condition {{#oldStatus ! #newStatus}} // 仅状态变化时记录 ) public void updateOrderStatus(String orderNo, String oldStatus, String newStatus) { // 状态更新逻辑 } LogRecord( success {{#operator}}处理了退款申请退款金额{{#refund.amount}}元原因{{#refund.reason}}, type ORDER_REFUND, bizNo {{#refund.orderNo}} ) public void processRefund(Refund refund, User operator) { // 退款处理逻辑 } }用例二权限管理系统审计Service public class PermissionServiceImpl implements PermissionService { LogRecord( success {{#operator}}为用户{USER{#userId}}分配了角色{ROLE{#roleId}}, type PERMISSION_ASSIGN, bizNo {{#userId}} ) public void assignRole(Long userId, Long roleId, User operator) { // 角色分配逻辑 LogRecordContext.putVariable(operator, operator.getName()); } LogRecord( success {{#operator}}修改了数据权限{_DIFF{#oldPermission, #newPermission}}, type PERMISSION_UPDATE, bizNo {{#newPermission.resourceId}} ) public void updateDataPermission(DataPermission oldPermission, DataPermission newPermission, User operator) { // 权限更新逻辑 } }⚡ 性能优化与监控策略性能监控接口组件提供了性能监控接口可以实时监控日志记录性能Component Slf4j public class CustomLogRecordPerformanceMonitor implements ILogRecordPerformanceMonitor { Override public void print(String processName, long timeUsed) { // 记录性能指标 log.debug(操作日志处理性能 - 过程: {}, 耗时: {}ns, processName, timeUsed); // 可以集成到监控系统 Metrics.counter(bizlog.performance) .tag(process, processName) .increment(timeUsed); } Override public void startRecord() { // 开始监控 } Override public void endRecord() { // 结束监控 } }配置性能监控logging: level: com.mzt.logapi.service.impl: debug # 开启性能监控日志监控日志输出示例--------------------------------------------- ns % Task name --------------------------------------------- 000111278 003% before-execute 003277960 097% after-execute批量操作优化对于批量操作场景建议使用异步记录策略Component public class AsyncLogRecordService implements ILogRecordService { Autowired private ThreadPoolTaskExecutor logExecutor; Override Async(logExecutor) public void record(LogRecord logRecord) { // 异步保存日志 logRecordRepository.save(logRecord); } Override public ListLogRecord queryLog(String bizKey, CollectionString types) { return logRecordRepository.findByBizNoAndTypeIn(bizKey, types); } }存储优化建议分表存储按时间或业务类型分表避免单表过大索引优化为bizNo、type、operator、createTime建立复合索引归档策略定期归档历史日志到冷存储异步写入使用消息队列缓冲日志写入压力️ 故障排查与调试指南常见问题排查问题1注解未生效可能原因Bean生命周期问题确保相关Bean在BeanFactoryLogRecordAdvisor之后加载未正确启用EnableLogRecord注解方法访问权限问题private方法无法拦截解决方案Configuration public class LogRecordConfig { Bean DependsOn(logRecordAdvisor) // 确保在切面之后加载 public SomeService someService() { return new SomeService(); } }问题2SpEL表达式解析失败可能原因变量名拼写错误访问了不存在的属性或方法权限问题导致无法访问私有属性调试方法// 开启SpEL调试日志 logging: level: org.springframework.expression: debug问题3自定义函数未调用检查清单确保自定义函数类被Spring管理Component或Service函数名与注解中使用的名称完全一致没有循环依赖问题函数实现类已正确实现IParseFunction接口调试技巧启用详细日志logging: level: com.mzt.logapi: debug org.springframework.aop: debug使用测试工具验证SpringBootTest class LogRecordTest { Autowired private LogRecordExpressionEvaluator evaluator; Test void testSpELExpression() { StandardEvaluationContext context new StandardEvaluationContext(); context.setVariable(user, new User(张三, 25)); String result evaluator.parseExpression( 用户{{#user.name}}年龄{{#user.age}}, context ); assertEquals(用户张三年龄25, result); } } 最佳实践与推荐用法日志类型规范化管理建议在项目中统一管理日志类型常量// bizlog-server/src/main/java/com/mzt/logserver/infrastructure/constants/LogRecordType.java public class LogRecordType { public static final String ORDER ORDER; public static final String USER USER; public static final String PRODUCT PRODUCT; public static final String INVENTORY INVENTORY; public static final String PAYMENT PAYMENT; // 子类型定义 public static final String SUB_TYPE_USER USER_VIEW; public static final String SUB_TYPE_ADMIN ADMIN_VIEW; }敏感信息处理策略对于敏感字段使用DIffLogIgnore注解进行保护Data public class User { private Long id; private String name; DIffLogIgnore // 不记录密码差异 private String password; DIffLogIgnore // 不记录身份证号 private String idCard; DiffLogField(name 手机号, function PHONE_MASK) // 使用脱敏函数 private String phone; } // 手机号脱敏函数 Component public class PhoneMaskParseFunction implements IParseFunction { Override public String functionName() { return PHONE_MASK; } Override public String apply(Object value) { if (value null) return ; String phone value.toString(); return phone.length() 7 ? phone.substring(0, 3) **** phone.substring(7) : phone; } }事务一致性保障对于需要强一致性的业务场景启用事务一致性SpringBootApplication EnableTransactionManagement(order 0) // 事务优先级最高 EnableLogRecord( tenant order-system, joinTransaction true // 日志与业务同事务 ) public class OrderApplication { // 应用启动类 }多租户支持在多租户系统中合理使用租户标识Configuration public class MultiTenantLogConfig { Bean public IOperatorGetService operatorGetService() { return () - { User currentUser SecurityContext.getCurrentUser(); Tenant currentTenant TenantContext.getCurrentTenant(); OperatorDO operator new OperatorDO(); operator.setOperatorId(currentUser.getId()); operator.setOperatorName(currentUser.getName()); operator.setTenantId(currentTenant.getId()); return operator; }; } Bean public ILogRecordService logRecordService() { return new MultiTenantLogRecordService(); } } // 多租户日志服务实现 Service public class MultiTenantLogRecordService implements ILogRecordService { Override public void record(LogRecord logRecord) { // 根据租户ID路由到不同的存储 String tenantId logRecord.getTenant(); LogStorage storage getStorageByTenant(tenantId); storage.save(logRecord); } } 未来演进方向当前架构优势轻量级设计核心SDK仅依赖Spring框架无额外重量级依赖高度可扩展所有核心接口均可自定义实现性能优异基于AOP的轻量级拦截对业务性能影响极小学习成本低注解式开发符合Spring开发者习惯演进规划建议云原生支持集成Spring Cloud、Kubernetes等云原生生态流式处理支持Kafka等消息队列的日志流式处理智能分析集成机器学习算法进行异常操作检测可视化配置提供Web界面进行日志模板配置和管理多语言支持扩展支持其他JVM语言Kotlin、Scala社区生态建设mzt-biz-log已经建立了完善的技术社区支持技术交流群二维码 - 加入社区获取最新技术支持和最佳实践分享 总结mzt-biz-log通过创新的注解驱动设计和强大的表达式引擎为SpringBoot应用提供了一套完整的操作日志解决方案。其核心价值体现在开发效率提升声明式注解减少80%的日志记录代码维护成本降低统一的标准和格式便于后续维护业务价值增强完整的操作审计能力满足合规要求系统性能优化智能的日志记录策略最小化性能影响无论是初创企业还是大型互联网公司mzt-biz-log都能为您的系统提供可靠、高效、可扩展的操作日志管理能力。通过本文的完整指南您可以快速掌握组件的核心功能并将其成功应用于实际生产环境中。【免费下载链接】mzt-biz-log支持Springboot基于注解的可使用变量、可以自定义函数的通用操作日志组件项目地址: https://gitcode.com/gh_mirrors/mz/mzt-biz-log创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考