springboot使用aop切面,记录日志

技术说明:

springboot:2.1.4.RELEASE
jQuery
Ajax
mysql:8.0.32

业务背景:

当我们在操作网页的时候,我们后台需要记录每个用户,什么时候操作了哪些记录。比如注册了,还是登录了,还是查询了,我们把这些记录全部储存起来,方便管理员查看。

pom.xml

        <!--日志记录-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.25.1</version>
        </dependency>
        <!--aop切面,方便记录日志-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

首先定义一个AopContextUtil工具类,里面包含一些常用方法,比如记录用户访问的ip

public class AopContextUtil {
    /**
     * 入参数据
     * @param joinPoint
     * @param request
     * @return
     */
    public static String preHandle(JoinPoint joinPoint, HttpServletRequest request) {

        String reqParam = "";
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        Annotation[] annotations = targetMethod.getAnnotations();
        for (Annotation annotation : annotations) {
            //此处可以改成自定义的注解
            if (annotation.annotationType().equals(RequestMapping.class)) {
                reqParam = JSON.toJSONString(request.getParameterMap());
                break;
            }
        }
        return reqParam;
    }

    /**
     * 获取IP地址的方法
     *
     * @param request 传一个request对象下来
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
}

定义切面类,就是哪些类哪些方法,需要被记录

@Aspect
@Component
@Slf4j
public class CommonAspect {

    @Autowired
    private LogsService logsService;//这是一个日志service层,用来插入到日志数据表里面

    /**
     *  定义切点 @Pointcut
     */
    @Pointcut("execution(* com.yuanshengrong.springbootyuanshengrong.controller.*.*(..))")//这里定义的是在这个目录下的controller包下的所有类,所有方法都被记录,就是当用户触发了这个类,这个方法,那就记录下来,用户发起了什么请求。
    public void log(){
    }

    /**
     * ProceedingJoinPoint仅支持@Around
     */
    @AfterReturning("log()")
    public void saveOperation(JoinPoint joinPoint){
        log.info("---------------接口日志记录---------------");
        // 创建一个日志对象(准备记录日志)
        LogsDo logsDo = new LogsDo();

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //IP地址
        String ipAddr = AopContextUtil.getIpAddress(request);//AopContextUtil前面有定义,获取ip的
        logsDo.setClientip(ipAddr);
        //url
        String url = request.getRequestURL().toString();//用户发起的请求链接
        logsDo.setOperurl(url);
        //请求参数
       /* String reqParam =AopContextUtil.preHandle(joinPoint,request);
        logsDo.setReqparam(reqParam);*/
        // 1.方法执行前的处理,相当于前置通知
        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        // 获取方法上面的注解
        LogAnno logAnno = method.getAnnotation(LogAnno.class);
        if (logAnno !=null){
        // 获取操作描述的属性值
        String operateType = logAnno.operateType();
        // 保存操作说明
        logsDo.setOpertype(operateType);
        }
        //TODO 设置操作人,从session中获取。
        String username = (String)request.getSession().getAttribute("username");//从session中获取用户名,记录是哪个用户操作的
         //保存用户名到数据库
        logsDo.setUsername(username);
        // 设置操作日期
        logsDo.setOpertime(new Date());
        logsService.insertSelective(logsDo);
    }
}
@Target(ElementType.METHOD) // 方法注解
@Retention(RetentionPolicy.RUNTIME) // 运行时可见
public @interface LogAnno {
    String operateType();// 记录日志的操作类型
}

上面这个代码,是用来记录日志的,我们只需要在方法上加上@LogAnno(operateType = "导出面试信息Excel记录"),用来记录操作的日志类型即可

posted @ 2025-10-20 13:19  姜飞祥  阅读(14)  评论(0)    收藏  举报