当前位置: 首页 > news >正文

Spring AOP + RocketMQ 实现企业级操作日志异步采集(实战全流程)

Spring AOP + RocketMQ 实现企业级操作日志异步采集(实战全流程)

📌 项目背景

在企业级微服务架构中,记录操作日志是一项刚需。传统方式常使用数据库直接写入或通过 Feign 调用日志微服务,但这样存在耦合高、主流程阻塞、扩展性差等问题。

为此,我们将使用:

  • Spring AOP 实现非侵入式日志采集
  • RocketMQ 实现异步解耦投递
  • Redis 实现消息幂等控制
  • DLQ 死信队列保障日志消息最终可达

🧱 技术选型

模块 技术
日志采集 Spring AOP + 自定义注解
消息中间件 RocketMQ + Spring Cloud Stream
幂等控制 Redis
安全框架 Sa-Token
监控 & 补偿 RocketMQ DLQ、自定义消费处理

🚦 实现目标

  • 通过 @Log 注解拦截业务方法
  • 捕获操作人、IP、请求参数、响应结果、执行耗时等日志信息
  • 使用 RocketMQ 异步投递日志消息
  • 使用 Redis 做幂等处理,防止重复消费
  • 消费失败自动重试,最终由 DLQ 消费者处理

📦 Maven 依赖

确保主业务系统和日志服务都引入 RocketMQ 依赖:

<!-- RocketMQ Stream -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>

1️⃣ 日志注解定义

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
   
    String title() default "";
    BusinessType businessType() default BusinessType.OTHER;
    OperatorType operatorType() default OperatorType.MANAGE;
    boolean isSaveRequestData() default true;
    boolean isSaveResponseData() default true;
    String[] excludeParamNames() default {
   };
}

2️⃣ AOP 切面实现(LogAspect)

  • 使用 @Before/@AfterReturning/@AfterThrowing 统一处理日志
  • 日志采集后调用 logMqService.saveSysLog() 异步发送到 MQ
  • 使用 ThreadLocal 计算执行耗时
@Aspect
@Component
public class LogAspect {
   
    private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<>("Cost Time");
    private static final String[] EXCLUDE_PROPERTIES = {
   "password", "oldPassword", "newPassword", "confirmPassword", "credentials"};

    @Resource private HttpServletRequest request;
    @Resource private LogMqService logMqService;

    @Before("@annotation(controllerLog)")
    public void boBefore(JoinPoint joinPoint, Log controllerLog) {
   
        TIME_THREADLOCAL.set(System.currentTimeMillis());
    }

    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
   
        handleLog(joinPoint, controllerLog, null, jsonResult);
    }

    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
   
        handleLog(joinPoint, controllerLog, e, null);
    }

    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, 

相关文章:

  • linux 备份工具,常用的Linux备份工具及其备份数据的语法
  • Apache漏洞再现
  • 每日算法-250323
  • 常见中间件漏洞攻略-Weblogic篇
  • Jenkins最新版,配置Gitee私人令牌和Gitee凭证
  • 2025年中国AI搜索的行业洞察报告
  • 如何使用SystemVerilog SVA检查跨时钟域信号?
  • C++多线程编程:从创建到管理的终极指南
  • VLAN章节学习
  • 万象更新(一)VTK 坐标轴、相机方向坐标轴、立方体坐标轴
  • 基于 C++ 类的程序设计模式与应用研究
  • Python个人学习笔记(19):模块(正则表达式)
  • JVM类加载过程详解
  • 浙江大学DeepSeek公开课第二季第二期将于下周一直播!
  • 【redis】主从复制:全量复制、部分复制、实时复制详解
  • extern关键字的用法
  • 机器人的手眼标定——机器人抓取系统基础系列(五)
  • Unity Animation的其中一种运用方式
  • 【吾爱出品】【阿修】兔子vCard editor by(通讯录编辑工具)
  • 【RH124】 第五章 创建、查看文本文件
  • 朝鲜新型驱逐舰“崔贤”号进行多项武器试验
  • 北京银行一季度净赚超76亿降逾2%,不良贷款率微降
  • 俄宣布停火三天,外交部:希望各方继续通过对话谈判解决危机
  • 费高云调研党的建设工作:营造风清气正劲足的政治生态
  • 幸福航空五一前三天航班取消:客服称目前是锁舱状态,无法确认何时恢复
  • 牛市早报|今年国内核电项目审批首次开闸,离境退税起退点下调