Springboot使用Aop保存接口请求日志到mysql

1、添加aop依赖

        
        
            org.springframework.boot
            spring-boot-starter-aop
        

2、新建接口保存数据库的实体类RequestLog.java

package com.example.springboot.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;

/**
 * 

* 请求日志 *

* * @author Sca_jie * @since 2023-09-28 */ @Getter @Setter @TableName("request_log") public class RequestLog implements Serializable { private static final long serialVersionUID = 1L; // 主键-自增 @TableId(value = "number", type = IdType.AUTO) private Integer number; // 用户账号 private String id; // 携带token private String token; // 接口路径 private String url; // 请求类型 private String method; // 携带参数 private String params; // ip地址 private String ip; // 结果 private String result; // 接口发起时间 private LocalDateTime startDate; // 接口结束时间 private LocalDateTime endDate; // 响应耗时 private String responseTime; }

3、新建一个注解RequestLogAnnotation.java

package com.example.springboot.annotation;

import java.lang.annotation.*;

/**
 * 请求记录日志注解
 */
@Target({ElementType.TYPE, ElementType.METHOD}) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface RequestLogAnnotation {
    String value() default "";
}

4、(核心)新建aop面切类RequestLogAspect.java拦截请求并保存日志

package com.example.springboot.common;

import cn.hutool.core.net.NetUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.springboot.annotation.RequestLogAnnotation;
import com.example.springboot.entity.RequestLog;
import com.example.springboot.mapper.RequestLogMapper;
import com.example.springboot.utils.CookieUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 日志记录
 *
 */
@Aspect
@Component
public class RequestLogAspect {

    @Autowired(required = false)
    RequestLogMapper requestLogMapper;

    @Pointcut("@annotation(com.example.springboot.annotation.RequestLogAnnotation)")
    public void logPointCut() {

    }

    // 请求的开始处理时间(不同类型)
    Long startTime = null;
    LocalDateTime startDate;

    @Before("logPointCut()")
    public void beforeRequest() {
        startTime = System.currentTimeMillis();
        startDate = LocalDateTime.now();
    }

    @AfterReturning(value = "logPointCut()", returning = "result")
    public void saveLog(JoinPoint joinPoint, Object result) {

        // 获取请求头
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        HttpServletResponse response = requestAttributes.getResponse();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        //获取切入点所在的方法
        Method method = signature.getMethod();

        // 初始化日志表的实体类
        RequestLog requestLog = new RequestLog();

        //获取操作
        RequestLogAnnotation requestLogAnnotation = method.getAnnotation(RequestLogAnnotation.class);

//        // 获取@SystemLogAnnotation(value = "用户登录")中的注解value
//        if (systemLogAnnotation != null) {
//            String value = systemLogAnnotation.value();
//            requestLog.setSName(value);
//        }

        // 获取cookies
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            // 获取token
            for(Cookie cookie : cookies){
                if(cookie.getName().equals("token")){
                    requestLog.setToken(cookie.getValue());
                }
            }

            // 获取id
            String id = CookieUtil.getid(cookies);
            if (id != "" | id != null) {
                requestLog.setId(id);
            }
        }

        // 区分get和post获取参数
        String params = "{}";
        if (request.getMethod().equals("GET")) {
            params = JSONObject.toJSONString(request.getParameterMap());
        } else if (request.getMethod().equals("POST")) {
            params = JSONUtil.toJsonStr(joinPoint.getArgs());
        }

        // 用户Ip
        requestLog.setIp(NetUtil.getLocalhostStr());
        // 接口请求类型
        requestLog.setMethod(request.getMethod());
        // 请求参数(区分get和post)
        requestLog.setParams(params);
        // 请求接口路径
        requestLog.setUrl(request.getRequestURI().toString());
        // 返回结果
        requestLog.setResult(JSONObject.toJSONString(result));
        // 请求开始时间
        requestLog.setStartDate(startDate);
        // 请求结束时间
        requestLog.setEndDate(LocalDateTime.now());
        // 请求共计时间(ms)
        requestLog.setResponseTime(String.valueOf(System.currentTimeMillis() - startTime));

        // 保存日志到mysql
        requestLogMapper.insert(requestLog);
    }
}

5、在对应接口添加注解@RequestLogAnnotation

    @RequestLogAnnotation(value = "获取上传记录")
    @GetMapping("/getlist")
    public Result getlist (@RequestParam(required = false) String id) {
        if (id == null) {
            return Result.success(404, "参数缺失");
        } else {
            List page = uploadLogService.getlist(id);
            return Result.success(200, page.toString());
        }

    }

效果如下

你可能感兴趣的:(springboot,spring,boot,mysql,后端,aop,日志)