How to use AOP to record logs in Springboot interface projects

1. Background

Always want to build a unified log collection system for the project, take the first step, build a log collection class, and use AOP to achieve non-intrusive log collection

2. Environment

1. This essay is based on the spring boot project

2. The database is mysql 5.7.9 version

3.jdk version is 1.8

Three, description

This version uses database storage, and then consider using elasticsearch and other tools for storage

Four, content

1. Build a log collection entity class: BaseLogMessage

public class BaseLogMessage {
    
    
  private String serverIP;
  private String appName;
  private String method;
  private String type;
  private String userCode;
  private String uri;
  private String operationName;
  private String operationStatus;
  private long startTime;
  private Object parameter;
  private Object result;
  private int SpendTime;
 // 此处省略get、set
}

2. Construct a configuration file reading class for reading the system name in the configuration file: SystemPropetiesUtil

@Configuration
public class SystemPropetiesUtil {
    
    
  @Value("${spring.application.name}")
  private String sysName;//系统名称<br>  // 此处省略get、set<br>}

3. Create a new AOP class and use it as a point of cut in the controller method to perform log collection: LogAspect

@Aspect
@Component
public class LogAspect {
    
    
  @Autowired
  private SystemPropetiesUtil systemPropetiesUtil;
 
  //定义切点方法
  @Pointcut("execution(public * cq..campus.prevented.controller.*.*(..))")
  public void controllerLog() {
    
    
  }
 
  public static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
 
  @Around("controllerLog()")
  public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
    long startTime = System.currentTimeMillis();
    //获取当前请求对象
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    //记录请求信息
    BaseLogMessage baseLogMessage = new BaseLogMessage();
    //1.获取到所有的参数值的数组
    Object[] args = joinPoint.getArgs();
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    //2.获取到方法的所有参数名称的字符串数组
    String[] parameterNames = methodSignature.getParameterNames();
    Object result = joinPoint.proceed();
    Method method = methodSignature.getMethod();
    if (method.isAnnotationPresent(ApiOperation.class)) {
    
    
      ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
      baseLogMessage.setOperationName(apiOperation.value());
    }
    long endTime = System.currentTimeMillis();
    String urlStr = request.getRequestURL().toString();
    baseLogMessage.setUri(urlStr);
    baseLogMessage.setType("操作日志");
    baseLogMessage.setServerIP(getRemoteIP(request));
    baseLogMessage.setMethod(request.getMethod());
    baseLogMessage.setAppName(systemPropetiesUtil.getSysName());
    baseLogMessage.setResult(result);
    baseLogMessage.setParameter(getParameter(method, joinPoint.getArgs()));
    baseLogMessage.setSpendTime((int) (endTime - startTime));
    baseLogMessage.setStartTime(endTime);
    LOGGER.info("{}", JsonUtils.objectToJson(baseLogMessage));
    // 数据库存储操作
    return result;
  }
 
  /**
   * 异常返回通知,用于拦截异常日志信息 连接点抛出异常后执行
   *
   * @param joinPoint 切入点
   * @param e     异常信息
   */
  @AfterThrowing(pointcut = "controllerLog()", throwing = "e")
  public void saveExceptionLog(JoinPoint joinPoint, Throwable e) {
    
    
    long startTime = System.currentTimeMillis();
    if(null==kafkaClient){
    
    
      kafkaClient = KafkaProducerClient.getInstance(systemPropetiesUtil.getKafkaHost());
     //  redisClient= RedisClient.getInstance(systemPropetiesUtil.getReidsHost(), Integer.parseInt(systemPropetiesUtil.getRedisPort()), "");
    }
    // 获取RequestAttributes
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    // 从获取RequestAttributes中获取HttpServletRequest的信息
    HttpServletRequest request = (HttpServletRequest) requestAttributes
        .resolveReference(RequestAttributes.REFERENCE_REQUEST);
    String urlStr = request.getRequestURL().toString();
    BaseLogMessage baseLogMessage = new BaseLogMessage();
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    Method method = methodSignature.getMethod();
    StringBuffer strbuff = new StringBuffer();
    for (StackTraceElement stet : elements) {
    
    
      strbuff.append(stet + "\n");
    }
    String message = exceptionName + ":" + exceptionMessage + strbuff.toString();
    try {
    
    
      Object[] args = joinPoint.getArgs();
      String[] parameterNames = methodSignature.getParameterNames();
      long endTime = System.currentTimeMillis();
      baseLogMessage.setUri(urlStr);
      baseLogMessage.setType("异常日志");
      baseLogMessage.setServerIP(getRemoteIP(request));
      baseLogMessage.setMethod(request.getMethod());
      baseLogMessage.setAppName(systemPropetiesUtil.getSysName());
      baseLogMessage.setResult(message);
      baseLogMessage.setParameter(getParameter(method, joinPoint.getArgs()));
      baseLogMessage.setSpendTime((int) (endTime - startTime));
      baseLogMessage.setStartTime(endTime);
      LOGGER.info("{}", JsonUtils.objectToJson(baseLogMessage));
     // 数据库存储操作
    } catch (Exception e2) {
    
    
      e2.printStackTrace();
    }
 
  }
 
  /**
   * 根据方法和传入的参数获取请求参数
   */
  private Object getParameter(Method method, Object[] args) {
    
    
    List<Object> argList = new ArrayList<>();
    Parameter[] parameters = method.getParameters();
    for (int i = 0; i < parameters.length; i++) {
    
    
     
      RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
      if (requestBody != null) {
    
    
        argList.add(args[i]);
      }
      RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
      if (requestParam != null) {
    
    
        Map<String, Object> map = new HashMap<>();
        String key = parameters[i].getName();
        if (!StringUtils.isEmpty(requestParam.value())) {
    
    
          key = requestParam.value();
        }
        map.put(key, args[i]);
        argList.add(map);
      }
    }
    if (argList.size() == 0) {
    
    
      return null;
    } else if (argList.size() == 1) {
    
    
      return argList.get(0);
    } else {
    
    
      return argList;
    }
  }
 /**
   * 获取请求ip
   */
  public static String getRemoteIP(HttpServletRequest request) {
    
    
    String ip =null;
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
    
    
      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();
    }
    if (ip != null) {
    
    
      //对于通过多个代理的情况,最后IP为客户端真实IP,多个IP按照','分割
      int position = ip.indexOf(",");
      if (position > 0) {
    
    
        ip = ip.substring(0, position);
      }
    }
    return ip;
  }
}  

Five, the problem

If the method is executed normally and does not enter the AOP class, please check whether the AOP cutpoint is written correctly.

Life is more than perseverance and struggle. Dreams are meaningful pursuits
. I recommend a free learning exchange group for everyone:
Finally, I wish you all early success in learning, get a satisfactory offer, get a quick promotion and raise your salary, and reach the pinnacle of life.
If you need courseware source code software and other materials to add a small assistant vx: xcw18874131605 (note: CSDN)

Guess you like

Origin blog.csdn.net/p1830095583/article/details/115255142