面向切面编程:获取操作日志

很多数据库都有操作日志这张表,所以,在访问方法以后自动将操作日志放入数据库是非常重要的一点:
面向切面编程 AOP:其实就是切面与切入点,下文描述了如果设置简单的切面:

首先,自定义注解:

在这里插入图片描述
自定义注解里的字段最好包含数据库,操作日志表里的字段。

然后定义切面:

package com.qcby.demo0816.aspect;

import com.qcby.demo0816.anno.SelfLog;
import com.qcby.demo0816.common.context.QcbyContext;
import com.qcby.demo0816.entity.OperateLog;
import com.qcby.demo0816.util.JwtUtil;
import com.qcby.demo0816.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @className: SelfLogApsect
 * @description: 操作日志切面
 * @author: thx
 * @create: 2021-09-09
 **/
@Aspect
@Component
@Slf4j
public class SelfLogApsect {

	// request 用于获取 token
    @Autowired
    private HttpServletRequest httpServletRequest;

    /**
     * 定义切入点,就是刚刚定义的 注解,只要方法有注解,就切入
     */
     
    @Pointcut("@annotation(com.qcby.demo0816.anno.SelfLog)")
    public void  selfLogPonitCut(){

    }

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before("selfLogPonitCut()")
    public void testBefore(JoinPoint joinPoint){
        log.info("我是一个前置通知");
    }


    @After("selfLogPonitCut()")
    public void after(){
        log.info("After................通知");
    }

    @AfterReturning("selfLogPonitCut()")
    public void afterReturning(){
        log.info("AfterReturning................通知");
    }

    @AfterThrowing("selfLogPonitCut()")
    public void afterThrowing(){
        log.info("AfterThrowing................通知");
    }

    /**
     * 可控制目标函数是否执行
     */
    @Around("selfLogPonitCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("Around................通知");
        log.info("进入Around通知....");
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        String token = httpServletRequest.getHeader("token");
        log.info("请求令牌:token:{}",token);
        Long userId = null;
        if(!StringUtil.isEmpty(token)){
            String audience = JwtUtil.getAudience(token);
            if(!StringUtil.isEmpty(audience)){
                // 获取到用户id
                userId = Long.valueOf(audience);
            }
        }


        //获取注解信息
        SelfLog selfLog = method.getAnnotation(SelfLog.class);
        log.info("selfLog:{}",selfLog);

        OperateLog operateLog = new OperateLog();
        operateLog.setCreateTime(LocalDateTime.now());
        operateLog.setType(selfLog.type());
        operateLog.setModule(selfLog.module());
        operateLog.setUserId(userId);
        // 操作日志入库
        log.info("操作日志:operateLog=>{}",operateLog);

        String nameValue = selfLog.name();
        log.info("nameValue的值为:{}",nameValue);
        String name = null;

        //获取切入点方法参数
        Object[] objects = joinPoint.getArgs();
        String[] paramNames =  signature.getParameterNames();
        for (int i =0;i<paramNames.length;i++){
            if (Objects.equals(nameValue,paramNames[i]) && objects[i] != null){
                name = objects[i].toString();
            }
        }
        log.info("name的值为:{}",name);
        log.info("model的类型:{}",operateLog.getModule());

        /**
         *  这是目标方法执行的代码
         */
        Object r = joinPoint.proceed();

        log.info("结束Around通知....");
        return r;
    }
}

在这里插入图片描述
此时只需要将 OperateLog 对象放入数据库即可,完成 每次访问功能,自动入库

在这里插入图片描述
完成自动获取操作日志:注:代码不需要掌握,只需理解什么意思即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_努力努力再努力_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值