diff --git a/pom.xml b/pom.xml
index c99717e461a1ab112703cb2f799447bb88b147c1..3f208eb6dff1ff21873b7498b2b084d2e33691be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,7 @@
1.18.28
31.1-jre
3.12.0
+ 2.15.2
@@ -68,6 +69,18 @@
commons-lang3
${commons-lang3.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ ${jackson.version}
+
diff --git a/weblog-module-common/pom.xml b/weblog-module-common/pom.xml
index f0b3996eaa9592412289696642f6ebab1959a2be..926bebb316e57e798a6e3d467d47bfd03530fbc8 100644
--- a/weblog-module-common/pom.xml
+++ b/weblog-module-common/pom.xml
@@ -32,6 +32,22 @@
spring-boot-starter-test
test
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
diff --git a/weblog-module-common/src/main/java/com/qianyong/weblog/common/aspect/ApiOperationLog.java b/weblog-module-common/src/main/java/com/qianyong/weblog/common/aspect/ApiOperationLog.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd622f8c60b28215224f1d2f6c775e050568fc2e
--- /dev/null
+++ b/weblog-module-common/src/main/java/com/qianyong/weblog/common/aspect/ApiOperationLog.java
@@ -0,0 +1,15 @@
+package com.qianyong.weblog.common.aspect;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Documented
+public @interface ApiOperationLog {
+
+ /**
+ * 操作描述
+ * @return
+ */
+ String description() default "";
+}
diff --git a/weblog-module-common/src/main/java/com/qianyong/weblog/common/aspect/ApiOperationLogAspect.java b/weblog-module-common/src/main/java/com/qianyong/weblog/common/aspect/ApiOperationLogAspect.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6ba4f5ed76611680aa86ed2bf038c6326dedc52
--- /dev/null
+++ b/weblog-module-common/src/main/java/com/qianyong/weblog/common/aspect/ApiOperationLogAspect.java
@@ -0,0 +1,109 @@
+package com.qianyong.weblog.common.aspect;
+
+import com.qianyong.weblog.common.utils.JsonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * Created with IntelliJ IDEA.
+ *
+ * @author :xiaoduoduo
+ * @date :2025/07/20
+ * @description:定义日志切面类
+ * @version:1.0
+ */
+@Aspect
+@Component
+@Slf4j
+public class ApiOperationLogAspect {
+ /** 以自定义 @ApiOperationLog 注解为切点,凡是添加 @ApiOperationLog 的方法,都会执行环绕中的代码 */
+ @Pointcut("@annotation(com.qianyong.weblog.common.aspect.ApiOperationLog)")
+ public void apiOperationLog() {}
+
+ /**
+ * 环绕
+ * @param joinPoint
+ * @return
+ * @throws Throwable
+ */
+ @Around("apiOperationLog()")
+ public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ try {
+ // 请求开始时间
+ long startTime = System.currentTimeMillis();
+
+ // MDC
+ MDC.put("traceId", UUID.randomUUID().toString());
+
+ // 获取被请求的类和方法
+ String className = joinPoint.getTarget().getClass().getSimpleName();
+ String methodName = joinPoint.getSignature().getName();
+
+ // 请求入参
+ Object[] args = joinPoint.getArgs();
+ // 入参转 JSON 字符串
+ String argsJsonStr = Arrays.stream(args).map(toJsonStr()).collect(Collectors.joining(", "));
+
+ // 功能描述信息
+ String description = getApiOperationLogDescription(joinPoint);
+
+ // 打印请求相关参数
+ log.info("====== 请求开始: [{}], 入参: {}, 请求类: {}, 请求方法: {} =================================== ",
+ description, argsJsonStr, className, methodName);
+
+ // 执行切点方法
+ Object result = joinPoint.proceed();
+
+ // 执行耗时
+ long executionTime = System.currentTimeMillis() - startTime;
+
+ // 打印出参等相关信息
+ log.info("====== 请求结束: [{}], 耗时: {}ms, 出参: {} =================================== ",
+ description, executionTime, JsonUtil.toJsonString(result));
+
+ return result;
+ } finally {
+ MDC.clear();
+ }
+ }
+
+ /**
+ * 获取注解的描述信息
+ * @param joinPoint
+ * @return
+ */
+ private String getApiOperationLogDescription(ProceedingJoinPoint joinPoint) {
+ // 1. 从 ProceedingJoinPoint 获取 MethodSignature
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+
+ // 2. 使用 MethodSignature 获取当前被注解的 Method
+ Method method = signature.getMethod();
+
+ // 3. 从 Method 中提取 LogExecution 注解
+ ApiOperationLog apiOperationLog = method.getAnnotation(ApiOperationLog.class);
+
+ // 4. 从 LogExecution 注解中获取 description 属性
+ return apiOperationLog.description();
+ }
+
+ /**
+ * 转 JSON 字符串
+ * @return
+ */
+ private Function