SpringBoot中使用Aop统一拦截MQ消息处理

SpringBoot中使用Aop统一拦截MQ消息处理

   背景

   在日常开发中,我们经常使用mq来实现异步处理等功能,这个过程就涉及到追踪日志链路以便于排查问题,这时候就可以用 Spring AOP 来优雅地解决这些问题。

   项目中代码示例:

 1 @Slf4j
 2 @Aspect
 3 @Component
 4 public class RocketMqMdcAspect {
 5 
 6     @Pointcut("execution(* org.apache.rocketmq.spring.core.RocketMQListener+.onMessage(..))")
 7     public void rocketMQListenerMethods() {}
 8 
 9     @Around("rocketMQListenerMethods()")
10     public Object aroundOnMessage(ProceedingJoinPoint joinPoint) throws Throwable {
11         // 获取消息体
12         Object arg = joinPoint.getArgs()[0];
13         String originMessage = arg != null ? arg.toString() : "null";
14 
15         // 长消息截断,避免日志过长
16         String message = originMessage.length() > 1000
17                 ? "消息过长,展示前1000个字符," + originMessage.substring(0, 1000)
18                 : originMessage;
19 
20         try {
21             // 设置日志追踪 ID
22             String requestId = UUID.randomUUID().toString();
23             MDC.put("requestId", "mq:" + requestId);
24 
25             log.info("收到消息 ====> body:{}", message);
26             Object result = joinPoint.proceed(); // 执行目标方法
27             log.info("处理消息结束 ====> body:{}", message);
28             return result;
29         } catch (Exception e) {
30             log.error("处理消息异常 ====> body:{}", originMessage, e);
31             throw e; // 向上抛出异常
32         } finally {
33             MDC.clear(); // 清理上下文,避免内存泄漏
34         }
35     }
36 }

 

    通过上面的代码示例,说明以下几个关键点:

    1.  拦截表达式

@Pointcut("execution(* org.apache.rocketmq.spring.core.RocketMQListener+.onMessage(..))")

   匹配所有实现了 RocketMQListener 接口的类中,名为 onMessage 的方法,无论参数是什么、返回值是什么。

   2. 日志链路追踪

MDC.put("requestId", "mq:" + UUID.randomUUID());

   利用 SLF4J 的 MDC 机制,把 requestId 注入到日志上下文;

   配合 logback 配置中的 %X{requestId},实现链路追踪。

   3. 异常处理封装

   将所有异常集中处理,并做“非致命业务异常跳过”的容错逻辑。

   4. 依赖和配置提示

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
</dependency>

   logback配置片段 (logback-spring.xml)

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" debug="false">

    //...
    <!-- 日志格式, 参考:https://logback.qos.ch/manual/layouts.html -->
    <property name="currentLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [requestId=%X{requestId}] [%logger{15}] [%method,%line] - %msg%n" />

</configuration>

    总结

    使用 Spring AOP 拦截 RocketMQ 消息消费逻辑,有以下几个好处:

    1. 日志增强:让日志统一、结构化、可追踪;

    2. 异常集中处理:便于容错和告警;

    3. 消息无侵入:业务代码无感知,维护成本低;

    4.  通用性强:拦截逻辑复用性高,适用于多 topic、多业务。

    这也是服务中间件接入时比较推荐的一种做法,特别适合用在日志链路追踪、故障排查、消息埋点等场景,既统一又方便后期定位问题。

posted @ 2025-05-21 15:47  欢乐豆123  阅读(71)  评论(0)    收藏  举报