spring boot使用aop实现一个简易版日志功能

今天我们来使用aop来实现简易版的日志记录,话不多说,直接来上手

  1. 创建日志表log

  2. 创建用户实体类,日志实体类

  3. 创建日志类接口

  4. 创建扫描注解

  5. 创建切面

  6. 测试接口

1.创建日志表log

CREATE TABLE `log`  (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
  `Executor` varchar(64) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL COMMENT '执行人',
  `operation` varchar(64) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL COMMENT '操作描述',
  `method` varchar(2048) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT '' COMMENT '执行方法路径',
  `execution_duration` int(11) NULL DEFAULT NULL COMMENT '执行时间',
  `ip` varchar(64) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT NULL COMMENT 'ip地址',
  `createtime` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 249 CHARACTER SET = gbk COLLATE = gbk_chinese_ci ROW_FORMAT = Dynamic;

2.创建用户实体和日志实体

  1. 用户实体类
/**用户测试实体*/
@Accessors(chain = true)
@Data
public class User {
    private Integer id;
    private String username;
    private String password;
}
  1. 日志实体类
/**日志实体*/
@Accessors(chain = true)
@Data
public class Log {
    /**主键*/
	private Integer id;
    /**执行人*/
	private String executor;
	/**方法描述*/
	private String operation;
	/**执行方法*/
	private String method;
	/**执行时长*/
    private Long executionDuration;
    /**ip*/
	private String ip;
	/**创建时间*/
	private Date createtime;
}

3.创建日志类接口

@Mapper
public interface LogMapper {
    @Insert("insert into log(id,Executor,operation,method,execution_duration,ip,createtime) " +
            "values(null,#{executor},#{operation},#{method},#{executionDuration},#{ip},#{createtime})")
    int insert(Log log);
}

4.创建扫描注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiredPower {
    String value();
}

5.创建切面

@Aspect//定义切面
@Component
@Order(1)//第一层切面
@Slf4j
public class LogAspect {

    @Resource
    private LogMapper logMapper;

    //扫描RequiredLog注解
    @Pointcut("@annotation(com.sise.annotation.RequiredLog)")
    public void doPointCut() {
    }

    @Around("doPointCut()")
    public Object around(ProceedingJoinPoint jp) throws Throwable {
        try {
            //记录方法执行前的时间
            long t1 = System.currentTimeMillis();
            //执行方法
            Object result = jp.proceed();
            //记录方法执行后的时间
            long t2 = System.currentTimeMillis();
            //保存用户行为日志
            log(jp, (t2 - t1));
            return result;
        } catch (Throwable e) {
            log.error(e.getMessage());
            throw e;
        }
    }

    private void log(ProceedingJoinPoint jp, long time) throws Exception {
        //获取目标对象
        Class<?> targetCls = jp.getTarget().getClass();
        //获取目标方法签名信息(包含方法名,参数列表等信息)
        MethodSignature ms = (MethodSignature) jp.getSignature();
        //获取方法对象
        Method interfaceMethod = ms.getMethod();
        //获取方法名
        String methodName = interfaceMethod.getName();
        //拼接包名+类名+方法
        String clsMethodName = targetCls.getName() + "." + methodName;
        //获取注解RequiredLog
        Method targetMethod =
                targetCls.getMethod(methodName, ms.getParameterTypes());
        RequiredLog requiredLog =
                targetMethod.getAnnotation(RequiredLog.class);
        //获取方法描述(注解值)
        String operation = requiredLog.value();

        //获取已登录的用户信息
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpSession session = attr.getRequest().getSession(true);
        User user = (User) session.getAttribute("user");

        //如果是登录操作则获取登录时的用户名作为执行人
        if(user==null&&operation.equals("登录")){
            Object[] args = jp.getArgs();
            for (Object object : args) {
                if (object instanceof User) {
                    user = (User) object;
                }
            }
        }

        //初始化日志实体
        Log entity = new Log()
                .setExecutor(user == null ? "" : user.getUsername())//登录使用的用户名
                .setOperation(operation)
                .setMethod(clsMethodName)//method=类全名+方法名
                .setIp(IPUtils.getIpAddr())
                .setExecutionDuration(time)
                .setCreatetime(new Date());
        //插入日志
        logMapper.insert(entity);
    }
}

6.测试

  1. 创建测试接口

        @RequestMapping("/test7")
        @RequiredLog("登录")
        public CallResult test7(@RequestBody User user,HttpSession session){
            session.setAttribute("user",user);
            return CallResult.success(user);
        }
    
        @RequestMapping("/getUser")
        @RequiredLog("获取用户信息")
        public CallResult getUser(HttpSession session){
            return CallResult.success(session.getAttribute("user"));
        }
    
  2. 模拟登录测试

    在这里插入图片描述

    登录测试日志信息插入成功

    在这里插入图片描述

  3. 模拟操作测试

    在这里插入图片描述

    模拟操作日志插入成功在这里插入图片描述

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页