feat: 新增操作日志插件模块

- 创建操作日志插件模块,实现可插拔式日志记录功能
- 添加@EnableOperLog注解实现插件自动配置
- 添加@OperLog注解支持方法级别的操作日志记录
- 实现AOP切面处理,自动拦截并记录操作信息
- 配置异步日志记录服务,提升系统性能
- 更新插件父模块POM配置,纳入构建管理
This commit is contained in:
Leo 2025-07-07 22:42:00 +08:00
parent d0312ea461
commit 16fbe7dc09
7 changed files with 70 additions and 42 deletions

View File

@ -6,15 +6,36 @@
<parent> <parent>
<groupId>org.leocoder.thin</groupId> <groupId>org.leocoder.thin</groupId>
<artifactId>coder-common-thin-plugins</artifactId> <artifactId>coder-common-thin-plugins</artifactId>
<version>1.0.0</version> <version>${revision}</version>
</parent> </parent>
<name>coder-common-thin-oper-logs</name>
<artifactId>coder-common-thin-oper-logs</artifactId> <artifactId>coder-common-thin-oper-logs</artifactId>
<description>异步操作日志功能插件支持AOP切面自动记录操作日志</description>
<properties> <dependencies>
<maven.compiler.source>17</maven.compiler.source> <!-- 全局公共模块 -->
<maven.compiler.target>17</maven.compiler.target> <dependency>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <groupId>org.leocoder.thin</groupId>
</properties> <artifactId>coder-common-thin-common</artifactId>
<version>${revision}</version>
</dependency>
<!-- 模型模块 -->
<dependency>
<groupId>org.leocoder.thin</groupId>
<artifactId>coder-common-thin-model</artifactId>
<version>${revision}</version>
</dependency>
<!-- SpringBoot Aop 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
</project> </project>

View File

@ -1,9 +1,10 @@
package org.leocoder.operlog.annotation; package org.leocoder.thin.operlog.annotation;
import org.leocoder.operlog.aspect.OperLogAspect; import org.leocoder.thin.operlog.aspect.OperLogAspect;
import org.leocoder.operlog.config.OperLogAsyncConfig; import org.leocoder.thin.operlog.config.OperLogAsyncConfig;
import org.leocoder.operlog.service.OperLogAsyncService; import org.leocoder.thin.operlog.service.OperLogAsyncService;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import java.lang.annotation.*; import java.lang.annotation.*;
/** /**

View File

@ -1,7 +1,9 @@
package org.leocoder.operlog.annotation; package org.leocoder.thin.operlog.annotation;
import org.leocoder.thin.domain.enums.oper.OperType;
import org.leocoder.thin.domain.enums.oper.SystemType;
import org.leocoder.domain.enums.oper.OperType;
import org.leocoder.domain.enums.oper.SystemType;
import java.lang.annotation.*; import java.lang.annotation.*;
/** /**

View File

@ -1,4 +1,4 @@
package org.leocoder.operlog.aspect; package org.leocoder.thin.operlog.aspect;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -12,15 +12,15 @@ import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature; import org.aspectj.lang.reflect.MethodSignature;
import org.leocoder.common.satoken.CoderLoginUtil; import org.leocoder.thin.common.satoken.CoderLoginUtil;
import org.leocoder.common.utils.date.DateUtil; import org.leocoder.thin.common.utils.date.DateUtil;
import org.leocoder.common.utils.ip.IpAddressUtil; import org.leocoder.thin.common.utils.ip.IpAddressUtil;
import org.leocoder.common.utils.ip.IpUtil; import org.leocoder.thin.common.utils.ip.IpUtil;
import org.leocoder.common.utils.json.JsonUtil; import org.leocoder.thin.common.utils.json.JsonUtil;
import org.leocoder.common.utils.string.StringUtil; import org.leocoder.thin.common.utils.string.StringUtil;
import org.leocoder.domain.pojo.system.SysOperLog; import org.leocoder.thin.domain.pojo.system.SysOperLog;
import org.leocoder.operlog.annotation.OperLog; import org.leocoder.thin.operlog.annotation.OperLog;
import org.leocoder.operlog.service.OperLogAsyncService; import org.leocoder.thin.operlog.service.OperLogAsyncService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
@ -46,7 +46,7 @@ public class OperLogAspect {
* @description [配置切入点] * @description [配置切入点]
* @author Leocoder * @author Leocoder
*/ */
@Pointcut("@annotation(org.leocoder.operlog.annotation.OperLog)") @Pointcut("@annotation(org.leocoder.thin.operlog.annotation.OperLog)")
public void operLogPointcut() { public void operLogPointcut() {
} }
@ -390,7 +390,8 @@ public class OperLogAspect {
if (obj.getClass().isArray()) { if (obj.getClass().isArray()) {
Object[] array = (Object[]) obj; Object[] array = (Object[]) obj;
StringBuilder sb = new StringBuilder("["); StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < array.length && i < 3; i++) { // 最多显示3个元素 // 最多显示3个元素
for (int i = 0; i < array.length && i < 3; i++) {
if (i > 0) sb.append(", "); if (i > 0) sb.append(", ");
sb.append(createObjectString(array[i], excludeFields)); sb.append(createObjectString(array[i], excludeFields));
} }
@ -408,8 +409,8 @@ public class OperLogAspect {
} }
// 对于Map // 对于Map
if (obj instanceof java.util.Map) { if (obj instanceof Map) {
java.util.Map<?, ?> map = (java.util.Map<?, ?>) obj; Map<?, ?> map = (Map<?, ?>) obj;
return "[Map, size=" + map.size() + "]"; return "[Map, size=" + map.size() + "]";
} }
@ -441,8 +442,8 @@ public class OperLogAspect {
return DateUtil.format((java.util.Date) obj, "yyyy-MM-dd HH:mm:ss"); return DateUtil.format((java.util.Date) obj, "yyyy-MM-dd HH:mm:ss");
} }
if (obj instanceof java.time.LocalDateTime) { if (obj instanceof LocalDateTime) {
java.time.LocalDateTime ldt = (java.time.LocalDateTime) obj; LocalDateTime ldt = (LocalDateTime) obj;
return ldt.toString(); return ldt.toString();
} }
@ -511,13 +512,13 @@ public class OperLogAspect {
valueStr = value.toString(); valueStr = value.toString();
} else if (value instanceof java.util.Date) { } else if (value instanceof java.util.Date) {
valueStr = DateUtil.format((java.util.Date) value, "yyyy-MM-dd HH:mm:ss"); valueStr = DateUtil.format((java.util.Date) value, "yyyy-MM-dd HH:mm:ss");
} else if (value instanceof java.time.LocalDateTime || value instanceof java.time.LocalDate) { } else if (value instanceof LocalDateTime || value instanceof java.time.LocalDate) {
valueStr = value.toString(); valueStr = value.toString();
} else if (value instanceof java.util.Collection) { } else if (value instanceof java.util.Collection) {
java.util.Collection<?> collection = (java.util.Collection<?>) value; java.util.Collection<?> collection = (java.util.Collection<?>) value;
valueStr = "[Collection, size=" + collection.size() + "]"; valueStr = "[Collection, size=" + collection.size() + "]";
} else if (value instanceof java.util.Map) { } else if (value instanceof Map) {
java.util.Map<?, ?> map = (java.util.Map<?, ?>) value; Map<?, ?> map = (Map<?, ?>) value;
valueStr = "[Map, size=" + map.size() + "]"; valueStr = "[Map, size=" + map.size() + "]";
} else { } else {
valueStr = value.toString(); valueStr = value.toString();

View File

@ -1,10 +1,11 @@
package org.leocoder.operlog.config; package org.leocoder.thin.operlog.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.beans.factory.annotation.Value;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
/** /**

View File

@ -1,14 +1,14 @@
package org.leocoder.operlog.service; package org.leocoder.thin.operlog.service;
import org.leocoder.domain.pojo.system.SysOperLog; import lombok.RequiredArgsConstructor;
import org.leocoder.common.exception.coder.YUtil; import lombok.extern.slf4j.Slf4j;
import org.leocoder.common.utils.cache.RedisUtil; import org.leocoder.thin.common.exception.coder.YUtil;
import org.leocoder.common.utils.date.DateUtil; import org.leocoder.thin.common.utils.cache.RedisUtil;
import org.leocoder.thin.common.utils.date.DateUtil;
import org.leocoder.thin.domain.pojo.system.SysOperLog;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -139,7 +139,8 @@ public class OperLogAsyncService {
// 用户操作统计 // 用户操作统计
String userKey = "oper:stat:user:" + operLog.getOperMan() + ":" + today; String userKey = "oper:stat:user:" + operLog.getOperMan() + ":" + today;
redisUtil.add1(userKey); redisUtil.add1(userKey);
redisUtil.setCacheObjectHours(userKey, 1, 25); // 25小时过期 // 25小时过期
redisUtil.setCacheObjectHours(userKey, 1, 25);
// 操作类型统计 // 操作类型统计
String typeKey = "oper:stat:type:" + operLog.getOperType() + ":" + today; String typeKey = "oper:stat:type:" + operLog.getOperType() + ":" + today;

View File

@ -21,6 +21,7 @@
<module>coder-common-thin-easyexcel</module> <module>coder-common-thin-easyexcel</module>
<module>coder-common-thin-repect</module> <module>coder-common-thin-repect</module>
<module>coder-common-thin-limit</module> <module>coder-common-thin-limit</module>
<module>coder-common-thin-oper-logs</module>
</modules> </modules>
</project> </project>