老蒋的知识库

  • 首页
  • 文章归档
  • 关于页面

  • 搜索

Java Aop 切面编程定制化打印Api接口日志

发表于 2023-09-23 | 分类于 Java | 0 | 阅读次数 37

如果写入公共组件作为第三方包导入需要维护自动装配:resources\META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports
参考资料:https://halo.ljdzsk.com/archives/javaspring公共组件与自动装配

小坑:这里记得要用全局的ObjectMapper,否则在转义JSON返回时可能存在输出日志和返回的响应不一致的情况。


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Value;
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 java.io.IOException;
import java.util.Enumeration;

@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class ApiLogAspect {
    // TODO 用于过滤不输出日志的路由,暂时没想到怎么做
    @Value("${api-log.exclude.routes:[]}")
    public String[] EXCLUDE_ROUTES;

    // 使用全局的objectMapper解析返回值。
    private final ObjectMapper objectMapper;

    //定义切入点
    @Pointcut("execution(* com.*.*.controller.*.*(..))")
    public void log() {
    }

    //定义通知,方法执行前
    @Before("log()")
    public void doBefore(JoinPoint point) throws IOException {
        if (!log.isDebugEnabled()) return;
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.debug("---------- 请求内容开始 ----------");
//        log.debug("IP来源: " + request.getRemoteAddr());
        log.debug("路由: " + request.getRequestURI());
        log.debug("请求模式: " + request.getMethod());
        Enumeration<String> enumeration = request.getHeaderNames();
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("请求头: ");
        while (enumeration.hasMoreElements()) {
            String name = enumeration.nextElement();
            stringBuilder.append("\n" + name + ":" + request.getHeader(name));
        }
        log.debug(stringBuilder.toString());
        stringBuilder.delete(0, stringBuilder.length());


        Enumeration<String> enu = request.getParameterNames();
        if (point.getArgs().length > 0) {
            // @RequestParam 参数
            stringBuilder.append("传参: ");
            while (enu.hasMoreElements()) {
                String name = enu.nextElement();
                stringBuilder.append(name + "=" + new String(request.getParameter(name).getBytes("ISO-8859-1"), "utf-8") + "&");
            }
            log.debug(stringBuilder.toString());
            stringBuilder.delete(0, stringBuilder.length());
            // 所有请求参数
            stringBuilder.append("Args");
            for (Object o : point.getArgs()) {
                stringBuilder.append("\n" + new ObjectMapper().writeValueAsString(o));
            }
            log.debug(stringBuilder.toString());
            stringBuilder.delete(0, stringBuilder.length());

        }
        log.debug("---------- 请求内容结束 ----------");
    }

    //定义通知,方法返回前
    @AfterReturning(pointcut = "log()", returning = "returnVal")
    public void AfterReturning(JoinPoint point, Object returnVal) throws JsonProcessingException {
        if (!log.isDebugEnabled()) return;
        log.debug("********** 响应内容开始 **********");
        log.debug(objectMapper.writeValueAsString(returnVal));
        log.debug("********** 响应内容结束 **********");
    }

    @Around("log()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        if (log.isDebugEnabled()) {
            log.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 请求开始 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            Object result = point.proceed();
            log.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 请求结束 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            return result;
        } else {
            return point.proceed();
        }
    }
}
  • 本文作者: jagger
  • 本文链接: /archives/javaaop-qie-mian-bian-cheng-ding-zhi-hua-da-yin-api-jie-kou-ri-zhi
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
Java Spring序列化与Jackson妙用
Java Spring Logging 使用技巧
jagger

jagger

66 日志
31 分类
0 标签
Creative Commons
0%
© 2026 jagger
由 Halo 强力驱动