Welcome to pay attention to personal wechat public number: Ha learning Java, the end of the article to share “Java core knowledge collation & interview. PDF” resource link!!

Personal website: www.exception.site/springboot/…

In fact, Ha has published a previous article on how to uniformly print request logs using AOP facets, so why do you want to publish another? Run out of stuff to write?

Ha ha, of course not! The reason is that there are still defects in the implementation scheme at that time. The reasons are as follows:

  1. It’s not flexible enough, because it cuts to all the Controller methods, that is, it cuts to death, and if we don’t want an interface to print the entry log, we can’t do it;
  2. If the Controller package level is too deep, the interfaces of many packages cannot be cut off.

Today we will focus on how to use custom annotations in Spring Boot to uniformly print entry and entry logs for AOP facets. Friends can collect a wave.

Without further ado, let’s get to the point!

directory

First, take a look at the output effect of section log

Add AOP Maven dependencies

Custom log annotations

Configure the AOP aspect

Five, how to use it?

Does it work well for file uploading?

7. Only want to use in development environment and test environment?

Eight, how to specify the priority of multi-slice?

First, take a look at the output effect of section log

Before taking a look at the implementation, let’s take a look at the output effect of the section log:

Spring Boot custom annotation, AOP section unified print request log effect diagram

As you can see from the figure above, each request has a clear start and end, and the following parameters are printed:

  • URL: request interface address.
  • Description: Indicates the Chinese Description of the interface.
  • HTTP Method: Request method, yesPOST.GET, orDELETEAnd so on;
  • Class Method: Method path: package name + Method name;
  • IP: IP address of the requester.
  • Request Args: The input parameter of the Request is output in JSON format.
  • Response Args: The Response parameter is output in JSON format.
  • Time-consuming: Indicates the Time consumed by the request to estimate the performance index of each interface.

How’s that? It looks good, doesn’t it? Now let’s see, how do we implement this step by step?

Add AOP Maven dependencies

Add dependencies to the project pom.xml file:

<! -- AOP dependencies -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<! Print entry and exit parameters in JSON format -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>
Copy the code

Custom log annotations

Let’s customize a log annotation like this:

Custom annotations

  • When to use this annotation, we define it as runtime.
  • ② where annotations are used, we define them as acting on methods.
  • ③ Whether annotations will be included in JavaDoc;
  • (4)Note name:WebLog;
  • ⑤ : Define an attribute, default is empty string;

Source code is as follows:

package site.exception.springbootaopwebrequest.aspect;

import java.lang.annotation.*;

/ * * *@authorDog Ha (wechat id: Ha learning Java) *@site www.exception.site
 * @date 2019/2/12
 * @timeOn the afternoon of 4 *@discription* * /
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface WebLog {
    /** * Log description **@return* /
    String description(a) default "";

}
Copy the code

At this point, a complete custom annotation definition is complete.

Configure the AOP aspect

Before configuring an AOP aspect, we need to understand the role of AspectJ-related annotations:

  • @aspect: Declare this class as an annotation class;
  • Pointcut: defines a Pointcut followed by an expression that can be defined to cut an annotation or a method under a package;

After the pointcut is defined, it is around this pointcut:

  • Before: Before the pointcut, weave in the relevant code;
  • @after: After the pointcut, weave the relevant code;
  • AfterReturning: AfterReturning from the cut point, weave related code, generally used to do some processing on the returned value of the scene;
  • AfterThrowing: handles logic handling when an exception is thrown by the woven code;
  • @around: Around, which allows you to weave code Around pointcuts and control when pointcuts are executed.
Annotation execution order

Next, define a WebLogAspes.java aspect class and declare a pointcut:

Define a pointcut

Then, define the @around surround for when to execute the pointcut:

around

  • ① : Record the start time of calling the interface;
  • (2) Before -> interface logic code -> @after -> @afterreturning;
  • ③ : print out the parameter;
  • (4) : printing interface processing time;
  • ⑤ : Returns the return parameter result of the interface.

Look again at the @before method:

@Before

See annotation function description, because annotation says still quite clear!

And finally, to wrap things up with @after:

A newline

@After

We print the end-of-log flag at the end of each interface. Finally, take a look at the project package structure:

Project package structure

At this point, the section-related code is complete!

Complete code:

package site.exception.springbootaopwebrequest.aspect;

import com.google.gson.Gson;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
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.lang.reflect.Method;

/ * * *@authorDog Ha (wechat id: Ha learning Java) *@site www.exception.site
 * @date 2019/2/12
 * @timeOn the afternoon of 4 *@discription* * /
@Aspect
@Component
@Profile({"dev"."test"})
public class WebLogAspect {

    private final static Logger logger         = LoggerFactory.getLogger(WebLogAspect.class);
    /** newline */
    private static final String LINE_SEPARATOR = System.lineSeparator();

    /** To customize@WebLogAnnotated as pointcut */
    @Pointcut("@annotation(site.exception.springbootaopwebrequest.aspect.WebLog)")
    public void webLog(a) {}

    /** ** is woven into * before the pointcut@param joinPoint
     * @throws Throwable
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // Start printing the request log
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // Get the description of the @weblog annotation
        String methodDescription = getAspectLogDescription(joinPoint);

        // Prints request parameters
        logger.info("========================================== Start ==========================================");
        // Prints the request URL
        logger.info("URL : {}", request.getRequestURL().toString());
        // Prints description information
        logger.info("Description : {}", methodDescription);
        // Prints Http method
        logger.info("HTTP Method : {}", request.getMethod());
        // Prints the full path to the controller call and the execution method
        logger.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // Prints the requested IP
        logger.info("IP : {}", request.getRemoteAddr());
        // Prints the request entry parameter
        logger.info("Request Args : {}".new Gson().toJson(joinPoint.getArgs()));
    }

    /** * is woven into * after the pointcut@throws Throwable
     */
    @After("webLog()")
    public void doAfter(a) throws Throwable {
        // The interface ends with a line break for easy viewing
        logger.info("=========================================== End ===========================================" + LINE_SEPARATOR);
    }

    /** * surround *@param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        // Print out the parameter
        logger.info("Response Args : {}".new Gson().toJson(result));
        // Execution time
        logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
        return result;
    }


    /** * Get the description of the section annotation **@paramJoinPoint tangent point *@returnDescription@throws Exception
     */
    public String getAspectLogDescription(JoinPoint joinPoint)
            throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        StringBuilder description = new StringBuilder("");
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description.append(method.getAnnotation(WebLog.class).description());
                    break; }}}returndescription.toString(); }}Copy the code

Five, how to use it?

Since our pointcut is the custom @weblog annotation, we just need to add @weblog annotation to each interface method of the Controller Controller. If we don’t want an interface to print the entry log, we don’t need to add annotation:

User login interface

Does it work well for file uploading?

It works! The section log works fine for both single-file and multi-file uploads, but I don’t want to post what I’m testing here. Interested partners can try!

7. Only want to use in development environment and test environment?

What about applications with high performance requirements that do not want to print logs in production but only want to use them in development or test environments? We simply add @profile to the slice, as shown below:

The specified profile

This specifies that prod only works in dev and test environments. Prod does not work in production.

Eight, how to specify the priority of multi-slice?

Let’s say we have more than one aspect defined in our service, such as our interface to the Web layer, not only to print logs, but also to verify tokens, etc. How do you specify the priority of an aspect? How do you specify the order in which the slices are executed?

We can specify the priority with the @order (I) annotation. Note that the lower the value of I, the higher the priority.

If we define the log aspect as @order (10) and then we define the token aspect checkTokenAspect.java as @order (11), then the execution Order between them is as follows:

Multiple pointcut priorities

We can sum it up:

  • Before I cut to the point,@OrderIs executed from small to large, that is, the smaller the priority is higher;
  • After the tangent point,@OrderIt is executed from large to small, that is, the larger the priority is higher;

Nine, Ref

Blog.didispace.com/springboota…

GitHub source code address

Github.com/weiwosuoai/…

Gifts | interview & learning welfare resources

Recently found a good PDF resource on the Internet “Java core knowledge & interview. PDF” to share with you, not only interview, learning, you are worth it!!

Access: pay attention to the public number: xiahaxuejava, background reply resources, both free access to resources without routine links, the following is the directory and some screenshots:

Pay attention to wechat public number [xiaoxuxueJava], reply to [resources], you can get free free resources link oh

Pay attention to wechat public number [xiaoxuxueJava], reply to [resources], you can get free free resources link oh

Pay attention to wechat public number [xiaoxuxueJava], reply to [resources], you can get free free resources link oh

Pay attention to wechat public number [xiaoxuxueJava], reply to [resources], you can get free free resources link oh

Pay attention to wechat public number [xiaoxuxueJava], reply to [resources], you can get free free resources link oh

Pay attention to wechat public number [xiaoxuxueJava], reply to [resources], you can get free free resources link oh

Important things to say twice, pay attention to the public number: small ha learning Java, background reply resources, both free no routine access to resources links!!

Welcome to follow the wechat public number: Xiaoxue Java

Ha learning Java, pay attention to receive 10G interview learning materials oh