Define an Annotation class

Annotation in Chinese means Annotation. The specific meaning of Annotation can be found in the rookie tutorial. On this annotation class, there are three annotations: @target, @Retention, and @Documented. Click on any annotation in Springboot (@Controller, @Service, etc.) and you will see that all three annotations appear all the time. All annotations need to be added.

import java.lang.annotation.*;

/** * TYPE means it can be placed on a class, MTTHOD means it can be placed on a method */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {

    String module(a) default "";

    String operator(a) default "";

}
Copy the code

2. Define the Aspect class Aspect

  1. With the annotations declared, we need to define a facet class that implements all the operations we need. Add the @pointcut Annotation to the pt() function to represent the Pointcut, containing the package address of the @annotation you just declared.
  2. Define the log function and add the @around annotation Around the pt() function.
import com.alibaba.fastjson.JSON;
import com.jyuxuan.blog.utils.HttpContextUtils;
import com.jyuxuan.blog.utils.IPUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
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.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Component
@Aspect // The section defines the relationship between the notification and the pointcut
@Slf4j
public class LogAspect {

    @Pointcut("@annotation(com.***.blog.common.aop.LogAnnotation)")
    public void pt(a) {}/** * wrap around notification */
    @Around("pt()")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // Execute method
        Object result = joinPoint.proceed();
        // Execution time (ms)
        long time = System.currentTimeMillis() - beginTime;
        // Save the log
        recordLog(joinPoint, time);
        return result;
    }

    private void recordLog(ProceedingJoinPoint joinPoint, long time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        log.info("=====================log start================================");
        log.info("module:{}", logAnnotation.module());
        log.info("operation:{}", logAnnotation.operator());

        // The method name of the request
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.info("request method:{}", className + "." + methodName + "()");

        // Request parameters
        Object[] args = joinPoint.getArgs();
        String params = JSON.toJSONString(args[0]);
        log.info("params:{}", params);

        // Get request set IP address
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        log.info("ip:{}", IPUtils.getIpAddr(request));

        log.info("excute time : {} ms", time);
        log.info("=====================log end================================"); }}Copy the code

3. Use annotations in the Controller method

Add annotations to one of your random methods to view the log information on the workbench.

@PostMapping
@logAnnotation (Module = "name ", operator =" operation name ")
public Result test(@RequestBody Work work) {
    return Result.success(null);
}
Copy the code

4. Supplementary content

1. @ Target

Click on any annotation to see the @target annotation, then click on the @target annotation to find the following. Click ElementType again

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}
Copy the code

Here you can see all the content information that @target can annotate, all in the comment.

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE, // Class, interface, or enumeration

    /** Field declaration (includes enum constants) */
    FIELD, / / domain

    /** Method declaration */
    METHOD, / / method

    /** Formal parameter declaration */
    PARAMETER, / / parameters

    /** Constructor declaration */
    CONSTRUCTOR, // constructor

    /** Local variable declaration */
    LOCAL_VARIABLE, // Local variables

    /** Annotation type declaration */
    ANNOTATION_TYPE, // Annotation type

    /** Package declaration */
    PACKAGE, / / package

    /**
     * Type parameter declaration
     *
     * @since1.8 * /
    TYPE_PARAMETER, // Parameter type

    /**
     * Use of a type
     *
     * @since1.8 * /
    TYPE_USE // Can mark any type
}
Copy the code

2, @ Retention

Specify the lifetime of the modified annotations, that is, to which stage they will remain, by clicking enter.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value(a);
}
Copy the code

Click RetentionPolicy again.

public enum RetentionPolicy {
    /** * Annotations are to be discarded by the compiler. */
    SOURCE, // indicates that the source level is reserved and lost after compilation

    /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time.  This is the default * behavior. */
    CLASS, // Compile-level reserved, present in the compiled class file, discarded at JVM runtime, (default)

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME // The runtime level is reserved, which exists in the compiled class file and is retained at JVM runtime and can be called by reflection
}
Copy the code

3, @ Documented

Indicates that the annotation is recorded by Javadoc, indicating that the class under the annotation appears in the Java Doc HTML document.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
Copy the code