Springboot-AOP记录用户操作日志

276 阅读2分钟

引入依赖

  <!-- aop依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

数据库创建表

CREATE TABLE `sys_log`  (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(23) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户id',
  `user_name` varchar(23) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户昵称',
  `module` varchar(35) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' 访问模块',
  `method` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' 访问方法',
  `parameter` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' 访问参数',
  `response_time` varchar(35) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' 响应时间ms',
  `date` varchar(35) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' 时间',
  `commit` varchar(35) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT ' 相应状况(成功or失败)',
  `ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'ip地址',
  PRIMARY KEY (`id`) USING BTREE
) 

同时创建Model实体类

自定义注解

定义一个方法级别的@Log注解,用于标注需要监控的方法:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemLog {
    String module() default "";    //模块
}

切面和切点

定义一个LogAspect类,使用@Aspect标注让其成为一个切面,切点为使用@Log注解标注的方法,使用@Around环绕通知:

package com.demo.aop;


import com.demo.dao.LogMapper;
import com.demo.model.Log;
import com.demo.model.User;
import com.demo.utils.GetIp;
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.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 切面类
 *
 * @author 苏若墨
 */
@Aspect
@Component
public class LogAspect {
    @Resource
    private LogMapper logMapper;
    private GetIp getIp = new GetIp();

    @Pointcut("@annotation(com.demo.aop.SystemLog)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object result = null;
        //模块开始时间
        long start = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Log sysLog = new Log();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        // 设置请求的方法名
        sysLog.setMethod(className + "." + methodName + "()");
        // 请求的方法参数值
        Object[] args = joinPoint.getArgs();
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);
        if (args != null && paramNames != null) {
            String params = "";
            for (int i = 0; i < args.length; i++) {
                params += "  " + paramNames[i] + ": " + args[i];
            }
            // 设置请求的方法参数名称
            sysLog.setParameter(params);
        }
        // 获取request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 设置IP地址
        sysLog.setIp(getIp.getIpAddr(request));
        // 获取用户
        User user = (User) request.getSession().getAttribute("user");
        sysLog.setUserName(user.getUserName());
        sysLog.setUserId(user.getUserId());
        //获取系统时间
        String date = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date());
        sysLog.setDate(date);
        SystemLog logAnnotation = method.getAnnotation(SystemLog.class);
        if (logAnnotation != null) {
            // 注解上的描述
            try {
                sysLog.setModule(logAnnotation.module());
                result = joinPoint.proceed();
                long end = System.currentTimeMillis();
                //将计算好的时间保存在实体中
                sysLog.setResponseTime("" + (end - start));
                sysLog.setCommit("执行成功");
                //保存进数据库
                logMapper.insert(sysLog);
            } catch (Throwable e) {
                // TODO Auto-generated catch block
                sysLog.setModule(logAnnotation.module());
                long end = System.currentTimeMillis();
                sysLog.setResponseTime("" + (end - start));
                sysLog.setCommit("执行失败");
                //保存进数据库
                logMapper.insert(sysLog);
            }
        }
        return result;
    }
}