利用AOP记录操作日志并保存在数据库表里面

操作日志包括:操作人、操作时间、执行方法得全类名、执行方法名、方法运行时的参数、返回值、方法执行时长

主要使用环绕通知@Around,以及@Annotation

思路分析:

如果要保存到数据库里面,首先需要一个数据库表:

-- 操作日志表
create table operate_log(
    id int unsigned primary key auto_increment comment 'ID',
    operate_user int unsigned comment '操作人ID',
    operate_username varchar(100) comment '操作人姓名',
    operate_time datetime comment '操作时间',
    class_name varchar(100) comment '操作的类名',
    method_name varchar(100) comment '操作的方法名',
    method_params varchar(1000) comment '方法参数',
    return_value varchar(2000) comment '返回值',
    cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';

有了一个数据库表以后,我们需要创建对应的Mapper文件(这里使用的是注解insert),放到Mapper层即可

public interface OperateLogMapper {

    //插入日志数据
    @Insert("insert into operate_log (operate_user,operate_username ,operate_time, class_name, method_name, method_params, return_value, cost_time) " +
            "values (#{operateUser},#{operateUsername} ,#{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")
    public void insert(OperateLog log);

}

紧接着创建一个我们自己的自定义注解Log:里面不需要写功能性代码,Log仅仅起到标明作用:

//单纯起到标识作用
@Retention(RetentionPolicy.RUNTIME)//这个注解什么时候生效?运行的时候
@Target(ElementType.METHOD)//注解作用在什么地方?这里是方法上
public @interface Log {
}

新创建一个实体类:OperateLog

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id; //ID
    private Integer operateUser; //操作人ID
    private String operateUsername; //操作人姓名
    private LocalDateTime operateTime; //操作时间
    private String className; //操作类名
    private String methodName; //操作方法名
    private String methodParams; //操作方法参数
    private String returnValue; //操作方法返回值
    private Long costTime; //操作耗时
}

以上工作都完成以后,创建aop切面:

@Component
@Slf4j
@Aspect
public class LogAspect {

    //需求:将增删改的相关接口的操作日志记录保存到数据库表里面

    //获取请求头
    @Autowired
    private HttpServletRequest servletRequest;

    @Autowired
    private OperateLogMapper operateLogMapper;

    @Around("@annotation(com.example.anno.Log)")
    public Object LogAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //1.执行前
        //1.1获取操作人ID
          //利用jwt令牌进行获取 -- 首先获取到请求头 --- 然后解析jwt令牌
        String jwt = servletRequest.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        Integer operateUser =(Integer) claims.get("id");
        String operateUsername =(String) claims.get("username");
        //1.2获取操作时间
        LocalDateTime LocalDateTime = java.time.LocalDateTime.now();
        //1.3获取操作类名
        String className = joinPoint.getTarget().getClass().getName();
        //1.4获取操作方法名
        String methodName = joinPoint.getSignature().getName();
        //1.5获取操作方法参数
        Object[] args = joinPoint.getArgs();
        String methodParams = Arrays.toString(args);

        long begin = System.currentTimeMillis();
        //2.执行原方法
        Object proceed = joinPoint.proceed();

        long end = System.currentTimeMillis();
        //1.6获取操作方法返回值
        String returnValue = JSONObject.toJSONString(proceed);
        //1.7获取操作耗时
        long costTime = end - begin;

        //2.1记录日志 -- 调用对应的Mapper方法
        OperateLog operateLog = new OperateLog(null,operateUser,operateUsername,LocalDateTime,className,methodName,methodParams,returnValue,costTime);
        operateLogMapper.insert(operateLog);

        log.info("记录日志操作:{}",operateLog);
        //3.返回值
        return proceed;
    }
}

这里使用到了工具类JwtUtils:也就是1.1

public class JwtUtils {

    private static String signKey = "itxiaoli";
    private static Long expire = 43200000L;

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map<String, Object> claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}

1.6部分是将数据转换为json格式,使用到的是alibaba依赖:pom文件添加依赖:

<!--        fastJson 手动转换json格式数据-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

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

结构如下:(只看对应的即可)

效果如下:

 

 

  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值