【工具类】AOP记录接口访问日志

该博客介绍了一种通过AOP(面向切面编程)来记录接口访问日志的方法,包括请求的header、参数、用户信息和耗时。每个请求与响应都通过唯一的序列号对应,便于跟踪和分析。此外,还特别关注了自定义响应的日志记录和异常响应的处理。
摘要由CSDN通过智能技术生成

        虽然容器都有记录接口的访问日志,但是毕竟不是自己程序记录的,由于各种原因,也会出现偏差,再者,容器记录的访问日志,不一定满足自己的需求,所以,这时就需要用到AOP,针对接口层做日志记录

具体代码如下:

package cn.xdf.xadd.aop;


import cn.xdf.xadd.context.UserInfoContext;
import cn.xdf.xadd.lang.util.Result;
import cn.xdf.xadd.util.RealIpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;


/**
 * AOP日志记录
 *
 * @author zhurunhua
 * @date 2020-08-11 16:47
 */
@Aspect
@Component
@Slf4j
public class LogRecordAspect {
    /**
     * 定义切面表达式
     */
    private static final String POINT = "execution(*  cn.xdf.xadd.controller..*.*(..))";
    /**
     * 记录每次请求的开始时间
     */
    private static final ThreadLocal<Long> START_TIME = new ThreadLocal<>();
    /**
     * 记录每次请求的随机序列号
     */
    private static final ThreadLocal<String> SEQUENCE = new ThreadLocal<>();

    @Pointcut(POINT)
    public void executeService() {
        //empty point cut
    }

    @Before("executeService()")
    public void before(JoinPoint pjp) {
        //请求信息
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest httpServletRequest = sra.getRequest();
        //获取客户端真实IP
        String realIp = RealIpUtils.getClientIp(httpServletRequest);
        //解析Http Header
        Enumeration names = httpServletRequest.getHeaderNames();
        StringBuilder header = new StringBuilder();
        while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            header.append(name).append(":").append(httpServletRequest.getHeader(name)).append("|");
        }
        //解析参数
        Object[] args = pjp.getArgs();
        Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
        StringBuilder stringBuilder = new StringBuilder();
        parameterMap.forEach((k, v) -> stringBuilder.append(k).append(":").append(Arrays.deepToString(v)).append("|"));

        //每次请求的序列号,避免方便匹配同一个请求以及对应的响应
        SEQUENCE.set(getRandom());
        //记录日志
        log.info("trace log begin --> sequence::{},userName::{},RealIp::{},User-Agent::{},requestUri::{}" +
                        ",header::{},requestMethod::{},request::{}, args::{}",
                SEQUENCE.get(), UserInfoContext.getUserName(), realIp, httpServletRequest.getHeader("User-Agent"),
                httpServletRequest.getRequestURI(), header.toString(), httpServletRequest.getMethod(),
                stringBuilder.toString(), Arrays.deepToString(args));
        //记录当前时间戳
        START_TIME.set(System.currentTimeMillis());
    }

    @AfterReturning(pointcut = "executeService()", returning = "result")
    public void after(Object result) {
        try {
            String res = "not standard response";
            //自定义标准返回类 也可以直接输出 不做判断
            if (result instanceof Result) {
                res = result.toString();
            }
            //记录返回信息
            log.info("trace log end --> sequence::{}, used::{}ms, responseBody::{}", SEQUENCE.get(), (System.currentTimeMillis() - START_TIME.get()), res);
        } finally {
            START_TIME.remove();
            SEQUENCE.remove();
        }
    }

    /**
     * 生成8位随机字符串
     *
     * @return java.lang.String
     * @date 2020-08-11 16:52
     */
    private String getRandom() {
        return RandomStringUtils.random(8, true, true);
    }
}


特点:

  • 主要记录了请求的header、参数、当前登陆用户的信息(可以去掉,用户相关的工具类没上传)
  • 每次请求与响应有唯一的序列号对应
  • 记录每次请求的耗时
  • 可针对自定义响应记录标准响应日志,其他的异常响应不做记录

其他待日后完善。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值