利用【AOP+自定义注解】实现项目中【日志记录】

发布于:2024-12-09 ⋅ 阅读:(113) ⋅ 点赞:(0)

利用AOP+自定义注解实现日志记录

需求: 日志记录

操作日志记录,类似如下

image-20241203092116822

思路:AOP+自定义注解

AOP面向切面编程,利用 一种称为"横切"的技术,剖开封装的对象内部,并将那些影响了 多个类的公共行为抽取出封装到一个可重用模块,并将其命名 为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

在每个目标方法上,加上自定义注解@MyLog(“查询全部订单”) 或者 @MyLog(“模块描述”)


利用AOP读取注解内的数据

步骤:

1.数据日志表

CREATE TABLE `log` (
  `id` int(11) NOT NULL AUTO_INCREMENT comment '日志编号',
  `log_time` datetime DEFAULT NULL comment '时间',
  `log` varchar(255) DEFAULT NULL comment '日志信息',
  `ip` varchar(255) DEFAULT NULL comment '操作ip',
  `name` varchar(255) DEFAULT NULL comment '操作人员',
  `method` varchar(255) DEFAULT NULL comment '请求方式',
  `type` varchar(255) DEFAULT NULL comment '操作类型',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

项目中要设计实体类…

2.自定义日志注解

package com.taotie.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @date 2024/12/3
 * @desc 自定义日志注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})
public @interface MyLog {

    /**
     * 日志内容
     */
    String log() default "";

    /**
     * 日志类型
     */
    String type() default "";
}

3.创建AOP读取注解值,记录日志

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
package com.taotie.aspect;

import com.taotie.annotation.MyLog;
import com.taotie.entity.SysLog;
import com.taotie.entity.SysUser;
import com.taotie.service.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @date 2024/12/3
 * @desc 日志切面类
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private SysLogService sysLogService;

    /**
     * 定义后置增强方法,在目标方法调用后执行
     * 特殊的!!!!! 此处的目标对象是注解!!!
     * 即MyLog注解加在哪个方法,哪个方法就会被增强
     */
    @After("@annotation(com.qf.annotation.MyLog)")
    public void after(JoinPoint joinPoint) {
        // 获取ip
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes( )).getRequest( );
        String ip = request.getRemoteAddr( );

        // 获取操作人名
        String userName = "未登录";
        HttpSession session = request.getSession( );
        SysUser user = (SysUser) session.getAttribute( "sysUser" );
        if (user!= null){
           userName = user.getUserName( );
        }

        // 获取请求方式
        String method = request.getMethod( );

        // 获取注解参数: 1) 日志内容 2) 日志类型
        HashMap<String, String> map = getAnnoLog(joinPoint);

        String log = map.get("log");
        String type = map.get("type");

        // 封装日志对象
        // 开始记录日志
        SysLog sysLog = new SysLog( );
        sysLog.setLogTime(new Date(  ));
        sysLog.setIp(ip);
        sysLog.setName(userName);
        sysLog.setMethod(method);
        sysLog.setLog(log);
        sysLog.setType(type);

        // 调用service层方法,保存日志
        sysLogService.insert(sysLog);
    }

    /**
     * 封装的方法,通过反射技术获得目标方法上的注解的值
     */
    public static HashMap<String, String> getAnnoLog(JoinPoint joinPoint) {
        HashMap<String, String> map = new HashMap<>( );
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature( );
            // 获得目标方法对象
            Method method = signature.getMethod( );
            // 获得目标方法对象上的日志注解
            MyLog myLog = method.getDeclaredAnnotation(MyLog.class);
            // 获得日志注解上的值
            String log = myLog.log( );
            String type = myLog.type( );

            map.put("log", log);
            map.put("type", type);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return map;
    }
}

5.插入日志到数据库

image-20241203104540514

ps: 这里需要自己实现LogService和LogMapper,即插入到数据库的动作,此处代码没有粘贴出来

6.在需要记录日志的方法上加注解即可

image-20241203104609043

7.启动测试

发请求,测试,查看数据库记录的日志

image-20241203104632855

后续

需要在项目设置 【日志模块】,将日志从数据库查询展现在前端即可,类似下面这样

image-20241203092116822


网站公告

今日签到

点亮在社区的每一天
去签到