eladmin-mp日志系统深度剖析:AOP切面如何实现操作日志与异常日志双记录 eladmin-mp日志系统深度剖析AOP切面如何实现操作日志与异常日志双记录【免费下载链接】eladmin-mpeladmin mybatis-plus版本项目基于 Spring Boot 2.7.18 、MyBatis-Plus、Spring Security、Redis、Vue的前后端分离的后台管理系统 权限控制采用 RBAC支持数据字典与数据权限管理支持一键生成前后端代码支持动态路由项目地址: https://gitcode.com/gh_mirrors/el/eladmin-mp对于任何一套后台管理系统来说日志功能都是最容易被忽视却又最不可或缺的模块。eladmin-mp日志系统基于 Spring Boot 2.7.18 与 MyBatis-Plus 构建通过AOP切面与自定义注解仅需一行Log(描述)就能自动完成操作日志与异常日志的双记录无需侵入任何业务代码。这篇文章将带你从零看懂 eladmin-mp 日志系统的完整工作链路包括日志注解的用法、AOP 环绕通知与异常通知的分工、日志落库与参数脱敏以及前端日志查询页面的使用技巧。为什么选择 AOP 来实现日志记录传统的日志记录方式是在每个业务方法里手动写一遍记录日志的代码。这种方式不仅重复冗余还极易遗漏——一旦某个接口忘了写出问题时便无从追溯。eladmin-mp 日志系统给出的答案是AOP面向切面编程把记录日志这一横切关注点从业务代码中彻底剥离出来集中在一个切面类中统一处理。开发者只需在接口方法上打一个注解标记切面便会在方法执行前后自动插一脚完成信息采集与入库。这是 Spring AOP 最经典的落地场景也是 eladmin-mp 相比传统手动日志方案的最大优势。一行注解触发日志Log 注解的正确用法eladmin-mp 日志系统的入口是一个自定义注解Log。它定义在 Log.java 中通过Target(ElementType.METHOD)限定只能标注在方法上Retention(RetentionPolicy.RUNTIME)保证运行时可以通过反射读取。注解本身极其轻量只有一个可选的value属性用于描述这条日志的含义。在 eladmin-mp 源码中随处可见它的身影例如 AppController.java 中的新增应用 / 修改应用 / 删除应用以及 DatabaseController.java 中的新增数据库 / 执行SQL脚本。Log(新增数据库) PostMapping PreAuthorize(el.check(database:add)) public ResponseEntityObject create(Validated RequestBody Database resources){ databaseService.create(resources); return new ResponseEntity(HttpStatus.CREATED); }使用方式就是这么简单想记录哪个接口就在哪个接口方法上加Log注解。剩下的工作全部交给切面完成。AOP 切面核心LogAspect 的双通知设计真正执行日志记录的是 LogAspect.java 这个切面类。它通过Aspect声明为切面通过Component交给 Spring 容器管理其核心是一个切入点 两个通知的设计。第一步定义切入点Pointcut切面首先用Pointcut(annotation(me.zhengjie.annotation.Log))定义切入点意思非常直白凡是方法上带有Log注解的都是我要拦截的目标。这样既精准又灵活业务代码完全不用修改。第二步环绕通知记录操作日志Around环绕通知对应操作日志的记录。它的执行时序如下进入方法前先把当前时间戳存入ThreadLocal作为计时的起点调用joinPoint.proceed()放行业务方法拿到正常返回结果方法执行完毕后构造一个INFO级别的SysLog用当前时间减去起点时间算出请求耗时从RequestHolder中取出HttpServletRequest采集用户名、浏览器、IP 等信息调用sysLogService.save(...)异步落库最后正常返回业务结果。这里有个非常巧妙的设计请求耗时不是在方法前或方法后单独测量的而是通过ThreadLocal在环绕通知内部包住整个业务方法计算出来的准确又高效。第三步异常通知记录异常日志AfterThrowing异常通知对应异常日志的记录。当被拦截的方法抛出异常时这个通知会被触发构造一个ERROR级别的SysLog此时ThreadLocal中依然保存着方法开始的时间所以耗时信息同样可以记录调用ThrowableUtil.getStackTrace(e)将异常堆栈转为字符串存入exceptionDetail字段同样采集用户、IP、浏览器信息后异步保存。两个通知各司其职正常路径走环绕通知记INFO异常路径走异常通知记ERROR这正是操作日志与异常日志双记录的实现核心。日志落库前的四大细节处理日志信息最终由 SysLogServiceImpl.java 负责组装并保存。在真正写入数据库前它做了四个值得学习的细节处理异步保存save方法标注了Async日志入库不会阻塞业务接口的响应保障系统性能参数过滤getParameter方法会跳过MultipartFile、HttpServletRequest、HttpServletResponse等无需记录的参数只保留真正有意义的请求参数敏感信息脱敏定义SENSITIVE_KEYS {password}常量数组凡是参数中包含 password 等敏感字段一律替换为******防止密码明文落入日志表用户兜底如果当前线程获取不到登录用户例如登录接口本身会自动尝试从请求参数中提取username字段作为补充。另外SysLog.java 中通过TableName(sys_log)映射到数据库表createTime字段配合 MyBatis-Plus 的FieldFill.INSERT自动填充创建时间无需手动赋值。一张表两条链路sys_log 表结构解析日志最终落库到sys_log表建表语句见 sql/eladmin.sql关键字段包括字段说明description日志描述即Log注解中的 valuelog_type日志类型INFO操作日志/ ERROR异常日志method完整方法路径如me.zhengjie.rest.S3StorageController.deleteAllQiNiu()params请求参数 JSONrequest_ip请求方 IPaddressIP 归属地通过 ip2region 离线库解析browser浏览器类型与版本time请求耗时毫秒exception_detail异常堆栈详情仅 ERROR 日志有值username操作人日志查询与导出前端如何展示双日志日志写入后如何查询前端在 views/monitor/log/index.vue 中提供了操作日志列表展示用户名、IP、IP来源、描述、浏览器、耗时等列其中耗时低于 300ms 显示绿色标签、300~1000ms 显示黄色、超过 1000ms 显示红色性能问题一目了然点击行可展开查看请求方法和请求参数详情。而后端的 SysLogController.java 则暴露了一组完整的 REST 接口GET /api/logs查询操作日志INFOGET /api/logs/error查询异常日志ERRORGET /api/logs/error/{id}查看某条异常日志的完整堆栈DELETE /api/logs/del/info与DELETE /api/logs/del/error一键清空对应类型的日志GET /api/logs/download与/error/download将日志导出为 Excel。这套设计让操作日志与异常日志从写入、存储到查询、导出形成了完整闭环无论是日常审计还是故障排查都有据可查。总结eladmin-mp 日志系统的设计启示回顾整个 eladmin-mp 日志系统它的优雅之处在于约定优于配置业务侧只需加Log注解零侵入、零重复代码切面侧用Around与AfterThrowing双通知天然区分操作日志与异常日志保存侧通过异步、过滤、脱敏、兜底四重保障兼顾性能与安全。如果你正在为自研系统设计日志模块或想理解 AOP 在真实项目中的最佳实践这套源码就是一份教科书级的参考。动手 clone 一份 eladmin-mp 源码在任意一个 Controller 方法上加一行Log(我的操作)然后调用接口刷新日志页面——你会亲眼见证一行注解换来一条完整日志的魔法时刻。【免费下载链接】eladmin-mpeladmin mybatis-plus版本项目基于 Spring Boot 2.7.18 、MyBatis-Plus、Spring Security、Redis、Vue的前后端分离的后台管理系统 权限控制采用 RBAC支持数据字典与数据权限管理支持一键生成前后端代码支持动态路由项目地址: https://gitcode.com/gh_mirrors/el/eladmin-mp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考