Spring Boot2.X requests logs using the AOP print interface

Spring Boot requests logs using the AOP print interface

The two main features of Spring, IOC (Automatic Injection) and AOP (Face Oriented), are the special features of AOP Face Oriented. When users access the system, they print the corresponding request logs according to the control layer methods they access, such as: client browser model, computer system model, method execution time, request parameters and so on.

1. Understanding AOP

(1) AOP is to mark a class or method before and after execution, declaring what to execute before executing here and what to execute after executing here.

This corresponds to some of the AOP terminology and usage scenarios:

Aspect: Declarations are similar to class declarations in Java, which include some Pointcut s and corresponding Advice s.
Joint point: A point that is explicitly defined in the program.This includes method calls, access to class members, and so on.
Pointcut: Represents a group of Joint point s, such as method name, parameter type, return type, and so on.
Advice: Advice defines what a program point defined in a Pointcut does specifically by calling Advice after executing the method, after, return after the method returns normally, and after\throw after the method throws an exception.
Before: Call Advice before executing a method, such as requesting login validation before an interface.
Around: Calling Advice before and after executing a method is the most common method.
Finally: Advice is executed after a method call, whether an exception is thrown or returned normally.

(2) To understand in plain words that AOP is to add new functions using AOP on the basis of the original functions of the project, and will not change the original code such as the code before recharging is the function of successfully sending SMS without recharging. Now with this requirement to send SMS, we can control all similar recharging without changing the code or all the recharging interfaces being processed uniformly.The system access layer uses Aop to send a text message after successful recharging.

2. Use in this article

This article uses annotated AOP

Required dependencies

        <!-- web assembly -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- lombok Code Simplification Plug-in-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Aop assembly-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <!-- Tool class for analyzing client information-->
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>1.20</version>
        </dependency>

Basic Use Demo

package com.leilei.web.controller.common;

import eu.bitwalker.useragentutils.UserAgent;
import java.time.LocalDateTime;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author leilei
 * @version 1.0
 * @date 2020/01/20 19:21
 * @desc: Log Slice Print Request Log
 */
@Slf4j   //Log notes in lombok
@Aspect  //Indicates a tangent class
@Component //Delegate to Spring Administration
public class LogAop {

  /** Entry Method Timestamp */
  private Long startTime;
  /** Method End Timestamp (Timing) */
  private Long endTime;

  public LogAop() {}

  /** Custom point of tangency */
  private final String POINTCUT = "execution(* com.leilei.web.controller..*(..))";

  /**
   * Pre-Notification, Executed Before Method
   * @param joinPoint
   */
  @Before(POINTCUT)
  public void doBefore(JoinPoint joinPoint) {
    // Get the current HttpServletRequest object
    ServletRequestAttributes attributes =
        (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    // Get User-Agent in Request Header
    UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
    // Print the requested content
    startTime = System.currentTimeMillis();
    log.info("Request start time:{}", LocalDateTime.now());
    log.info("request Url : {}", request.getRequestURL().toString());
    log.info("Request Method : {}", request.getMethod());
    log.info("request ip : {}", request.getRemoteAddr());
    log.info("Request Content Type : {}", request.getContentType());
    log.info("Request parameters : {}", Arrays.toString(joinPoint.getArgs()));
    // system information
    log.info("Browser : {}", userAgent.getBrowser().toString());
    log.info("Browser Version : {}", userAgent.getBrowserVersion());
    log.info("operating system: {}", userAgent.getOperatingSystem().toString());
  }

  @After(POINTCUT)
  public void doAfter(JoinPoint joinPoint) {
//    System.out.println("doAfter");
  }

  /**
   * Enter this method at normal end of return notification
   * @param ret
   */
  @AfterReturning(returning = "ret", pointcut = POINTCUT)
  public void doAfterReturning(Object ret) {
    endTime = System.currentTimeMillis();
    log.info("Request End Time : {}", LocalDateTime.now());
    log.info("Request Time-consuming : {}", (endTime - startTime));
    // After processing the request, return the content
    log.info("Request Return : {}", ret);
  }

  /**
   * Exception notification: 1. Execute when the target method ends abnormally, an exception occurs, or an exception is thrown
   *
   * @param throwable
   */
  @AfterThrowing(pointcut = POINTCUT, throwing = "throwable")
  public void doAfterThrowing(Throwable throwable) {
    // Save exception log records
    log.error("Exception time occurred : {}", LocalDateTime.now());
    log.error("throw : {}", throwable.getMessage());
  }
}

The tangent path defined by com.leilei.web.controller for my own project then executes each of the tangent methods in my LogAop tangent class when the user accesses all the Controller s and methods in this path

The @Before and @AfterReturning sections of the code can also be replaced with a surround notification @Around

    @Around(POINTCUT)
    public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // Get the current HttpServletRequest object
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //Get User-Agent in Request Header
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        //Print the requested content
        startTime = System.currentTimeMillis();
        // Request Information
        // Get the request class name and method name
        Signature signature = joinPoint.getSignature();
        // Get real method objects
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        log.info("Request start time:{}" , LocalDateTime.now());
        log.info("request Url : {}" , request.getRequestURL().toString());
        log.info("Request Method : {}" , request.getMethod());
        log.info("request ip : {}" , request.getRemoteAddr());
        log.info("Request Content Type : {}", request.getContentType());
        log.info("Request parameters : {}" , Arrays.toString(joinPoint.getArgs()));
        // system information
        log.info("Browser : {}", userAgent.getBrowser().toString());
        log.info("Browser Version : {}", userAgent.getBrowserVersion());
        log.info("operating system: {}", userAgent.getOperatingSystem().toString());
        // joinPoint.proceed(): When we have finished executing the tangent code, we have to continue working on business-related code.The proceed() method continues to execute the business code, and its return value is the return value after the business process is complete.
        Object result = joinPoint.proceed();
        log.info("Request end time:"+ LocalDateTime.now());
        log.info("Request time-consuming:{}" , (System.currentTimeMillis() - startTime));
        // After processing the request, return the content
        log.info("Request Return : " , result);
        return result;
    }

3. Testing

I requested a method under the project com.leileilei.web.controller path, and then checked in IDEA to see if the log was printed

So, this is the end of the story...

32 original articles published, 23 praised, 6787 visited
Private letter follow

Tags: Spring Lombok Java

Posted on Wed, 05 Feb 2020 18:47:00 -0800 by ddrummond