MyBatis-Plus和AOP实现数据库操作日志记录

概要

在Spring Boot中结合MyBatis-Plus和AOP实现数据库操作日志记录,可通过以下步骤实现。该方案支持动态获取操作人ID、操作类型及时间,并通过异步处理提升性能:

一、环境准备

1.添加依赖

在pom.xml 中添加MyBatis-Plus和AOP依赖:

<!-- MyBatis-Plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>
<!-- Spring AOP -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.创建操作日志表

CREATE TABLE log (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id VARCHAR(64) COMMENT '操作人ID',
    operation_type VARCHAR(20) COMMENT '操作类型(INSERT/UPDATE/DELETE)',
    method_name VARCHAR(200) COMMENT '执行方法',
    params TEXT COMMENT '方法参数',
    oper_time DATETIME COMMENT '操作时间'
);

二、核心实现步骤

1.定义操作日志实体与Mapper

日志实体类

@Data
@TableName("sys_oper_log")
public class OperLog {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String userId;
    private String operationType;
    private String methodName;
    private String params;
    private Date operTime;
}

Mapper

@Mapper
public interface OperLogMapper extends BaseMapper<OperLog> {}

2.自定义注解标记需记录的方法

在anno包创建动态标识监控增删改方法

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogOperation {
    String type() default ""; // 操作类型:INSERT/UPDATE/DELETE
}

3.实现AOP切面

@Aspect
@Component
@Slf4j
public class OperLogAspect {
    @Autowired
    private OperLogMapper operLogMapper;

    // 拦截所有标记@LogOperation的方法
    @Pointcut("@annotation(com.example.annotation.LogOperation)")
    public void logPointCut() {}

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        LogOperation logAnnotation = method.getAnnotation(LogOperation.class);

        // 执行原方法
        Object result = joinPoint.proceed();
        //异步记录日志可能会影响从线程中读取id
        operLog.setUserId(UserUtils.getCurrentUserId()); // 从线程上下文获取用户ID

        // 异步记录日志
        CompletableFuture.runAsync(() -> {
            OperLog operLog = new OperLog();
            operLog.setOperationType(logAnnotation.type());
            operLog.setMethodName(method.getName());
            operLog.setParams(JSON.toJSONString(joinPoint.getArgs()));
            operLog.setOperTime(new Date());
            operLogMapper.insert(operLog);
        });

        return result;
    }
}

调用MyBatis-Plus中的Mapper方法要成功监控需要在@Pointcut注解中标计
额外添加

@Pointcut(
  			"@annotation(com.pet.user.anno.Log)||"+
            "execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.insert(..)) || " +
            "execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.delete*(..)) || " +
            "execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.update*(..))")

将日志插入数据库的操作需要排除
插入方法最好自己写,然后排除掉,不排除容易死循环

@Pointcut("!execution(* com.pet.user.mapper.LogMapper.*(..))&& "+//排除插入数据库的方法
            "@annotation(com.pet.user.anno.Log)||"+
            "execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.insert(..)) || " +
            "execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.delete*(..)) || " +
            "execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.update*(..))")

4.在MyBatis-Plus的Service层应用注解(或者Mapper层)

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Override
    @LogOperation(type = "INSERT")
    public boolean save(User user) {
        return super.save(user);
    }

    @Override
    @LogOperation(type = "UPDATE")
    public boolean updateById(User user) {
        return super.updateById(user);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值