通过AOP实现系统日志管理(2)

388 阅读2分钟

这是我参与 8 月更文挑战的第 15 天,活动详情查看: 8月更文挑战

接上文通过AOP实现系统日志管理(1)

5. mapper层

LogMapper

package com.tjm.mapper;


import com.tjm.pojo.SysLog;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface LogMapper {

    int insertLog(SysLog log);

}

然后在resources/mapper下新建一个LogMapper.xml,代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.tjm.mapper.LogMapper">

    <insert id="insertLog" parameterType="SysLog" >
        insert into "SysLog"("log_id","username","class_name","method_name","args")
        values(#{log_id},#{username},#{class_name},#{method_name},#{args})
    </insert>

</mapper>

6. 自定义操作日志记录的注解

config目录下新建一个名为LogAnnotation文件。

package com.tjm.config;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    String value() default "";
}

之后,我们在类的前面@Log就可以使用这个我们自定义的注解。

7. 自定义操作日志切面类

同样在config目录下,新建一个LogAsPect.java,代码如下:

package com.tjm.config;
import com.tjm.pojo.SysLog;
import com.tjm.pojo.User;
import com.tjm.service.SysLogService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.StringUtils;
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.Logger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.Arrays;

@Aspect
@Component
public class LogAsPect {

    private final static Logger log = org.slf4j.LoggerFactory.getLogger(LogAsPect.class);

    @Autowired
    private SysLogService sysLogService;

    //表示匹配带有自定义注解的方法
    @Pointcut("@annotation(com.tjm.config.Log)")
    public void pointcut()
    {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) {
        Object result = null;
        long beginTime = System.currentTimeMillis();

        try {
            log.info("我在目标方法之前执行!");
            result = point.proceed();
            //log.info((String) result);
            long endTime = System.currentTimeMillis();
            insertLog(point,endTime-beginTime);
        } catch (Throwable e) {
        }
        return result;
    }

    //主健自增!
    private static int initId = 1;
    private void insertLog(ProceedingJoinPoint point,long time) {
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature)point.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        SysLog sys_log = new SysLog();
        
        //请求的类名
        String className = point.getTarget().getClass().getName();
        //请求的方法名
        String methodName = signature.getName();
        //请求的方法参数值
        String args = Arrays.toString(point.getArgs());

        //从session中获取当前登录的人id
       User user = (User) SecurityUtils.getSubject().getPrincipal();
       String username = user.getUsername();

        sys_log.setLog_id(initId++);
        
        sys_log.setUsername(username);
        sys_log.setClass_name(className);
        sys_log.setMethod_name(methodName);
        sys_log.setArgs(args);

        log.info("当前登陆人:{},类名:{},方法名:{},参数:{},执行时间:{}",username, className, methodName, args, time);

        sysLogService.insertLog(sys_log);
    }
}

8.测试

在任一个Controller文件中的方法前添加一个@Log,如在登录方法前添加@Log。

截屏2021-08-15 下午11.53.43

执行登录方法,控制台得到如下输出:

INFO 19283 --- [nio-8080-exec-4] com.tjm.config.LogAsPect : 当前登陆人:六六,类名:com.tjm.controller.LoginController,方法名:login,参数:[六六, 123, {}],执行时间:56

数据库中数据也同步更新:

截屏2021-08-15 下午11.56.02