为了甩锅,我写了个牛逼的日志切面

该博客介绍了如何使用Spring AOP和AspectJ注解实现请求日志记录。`RequestLogAspect`类展示了如何定义切点、环绕通知以及异常处理,用于捕获请求的IP、URL、HTTP方法、类方法、入参、结果和异常信息,并通过SLF4J进行日志输出。此外,还提供了一个方法用于处理MultipartFile参数,将其转换为原始文件名。
摘要由CSDN通过智能技术生成

package com.hz.framework.aspectj;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**

  • @author zyg

  • @className RequestLogAspect

  • @date 2022年04月22日 16:32
    */
    @Component
    @Aspect
    public class RequestLogAspect {
    private final static Logger LOGGER = LoggerFactory.getLogger(RequestLogAspect.class);

    //@Pointcut(“execution(* com.hikvision.trainplatform.controller…*(…))”)
    @Pointcut(“@annotation(com.hz.common.annotation.Log)”)
    public void requestServer() {
    }

    @Around(“requestServer()”)
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    Object result = proceedingJoinPoint.proceed();
    RequestInfo requestInfo = new RequestInfo();
    requestInfo.setIp(request.getRemoteAddr());
    requestInfo.setUrl(request.getRequestURL().toString());
    requestInfo.setHttpMethod(request.getMethod());
    requestInfo.setClassMethod(String.format(“%s.%s”, proceedingJoinPoint.getSignature().getDeclaringTypeName(),
    proceedingJoinPoint.getSignature().getName()));
    requestInfo.setRequestParams(getRequestParamsByProceedingJoinPoint(proceedingJoinPoint));
    requestInfo.setResult(result);
    requestInfo.setTimeCost(System.currentTimeMillis() - start);
    LOGGER.info(“Request Info : {}”, JSON.toJSONString(requestInfo));

     return result;
    

    }

    @AfterThrowing(pointcut = “requestServer()”, throwing = “e”)
    public void doAfterThrow(JoinPoint joinPoint, RuntimeException e) {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    RequestErrorInfo requestErrorInfo = new RequestErrorInfo();
    requestErrorInfo.setIp(request.getRemoteAddr());
    requestErrorInfo.setUrl(request.getRequestURL().toString());
    requestErrorInfo.setHttpMethod(request.getMethod());
    requestErrorInfo.setClassMethod(String.format(“%s.%s”, joinPoint.getSignature().getDeclaringTypeName(),
    joinPoint.getSignature().getName()));
    requestErrorInfo.setRequestParams(getRequestParamsByJoinPoint(joinPoint));
    requestErrorInfo.setException(e);
    LOGGER.info(“Error Request Info : {}”, JSON.toJSONString(requestErrorInfo));
    }

    /**

    • 获取入参
    • @param proceedingJoinPoint
    • @return
      */
      private Map<String, Object> getRequestParamsByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) {
      //参数名
      String[] paramNames = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterNames();
      //参数值
      Object[] paramValues = proceedingJoinPoint.getArgs();
      return buildRequestParam(paramNames, paramValues);
      }

    private Map<String, Object> getRequestParamsByJoinPoint(JoinPoint joinPoint) {
    //参数名
    String[] paramNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
    //参数值
    Object[] paramValues = joinPoint.getArgs();
    return buildRequestParam(paramNames, paramValues);
    }

    private Map<String, Object> buildRequestParam(String[] paramNames, Object[] paramValues) {
    Map<String, Object> requestParams = new HashMap<>();
    for (int i = 0; i < paramNames.length; i++) {
    Object value = paramValues[i];
    //如果是文件对象,获取文件名
    if (value instanceof MultipartFile) {
    MultipartFile file = (MultipartFile) value;
    value = file.getOriginalFilename();
    }
    //如果是批量文件上传
    if (value instanceof List) {
    try {
    List multipartFiles = castList(value, MultipartFile.class);
    if (multipartFiles != null) {
    List fileNames = new ArrayList<>();
    for (MultipartFile file : multipartFiles) {
    fileNames.add(file.getOriginalFilename());
    }
    requestParams.put(paramNames[i], fileNames);
    break;
    }
    } catch (ClassCastException e) {
    //忽略不是文件类型的List
    }
    }
    requestParams.put(paramNames[i], value);
    }
    return requestParams;
    }

    public static List castList(Object obj, Class clazz) {
    List result = new ArrayList();
    if (obj instanceof List<?>) { for (Object o : (List<?>) obj) {
    result.add(clazz.cast(o));
    }
    return result;
    }
    return null;
    }

    @Data
    public class RequestInfo {
    private String ip;
    private String url;
    private String httpMethod;
    private String classMethod;
    private Object requestParams;
    private Object result;
    private Long timeCost;
    }

    @Data
    public class RequestErrorInfo {
    private String ip;
    private String url;
    private String httpMethod;
    private String classMethod;
    private Object requestParams;
    private RuntimeException exception;
    }
    }

文章来源:https://c1n.cn/D5opM

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值