Use Springboot AOP for request interface exception monitoring

Common annotations

@Aspect aspect class
@Before prepended
@AfterReturning after
@Around Surround
@AfterThrowing exception

Entry point setting

execution(public * *(..)) defines the execution of any public method
execution(* set*(..)) defines the execution of any method starting with “set”
execution(* com.sys.service.UserService.*(..)) defines the execution of any method of the UserService interface
execution(* com.sys.service.*.*(..)) defines the execution of any method in the service package
execution(* com.sys.service ..*.*(..)) defines the execution of any method of any class in the service package and all subpackages
execution(* com.sys.pointcutexp…JoinPointObject.*(…)) defines the execution of any method of the JoinPointObject class in the pointcutexp package and all subpackages

Description of the use of aop this time

Use the @AfterReturning method to get the return status code of the request interface, save the status code and error information of the problem that needs to be processed to the database and output it to the log file, so as to facilitate the monitoring of interface call error information through the database. By configuring the entry point to process all the request interfaces of the controller, there is no need to process in each request method.
Use the @AfterThrowing method to get the abnormal call information of the request interface method, and the others are the same as above.

Reference code

package com.system.common.aop;

import com.alibaba.fastjson.JSON;
import com.system.service.SysLogService;
import com.xlx.entity.BaseResponse;
import com.xlx.entity.bsc.system.DO.SystemLogInfoDO;
import com.xlx.utils.ExceptionUtil;
import com.xlx.utils.StringParseUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @version: java version 1.8
 * @Author: sagitario
 * @description: Abnormal request records to database and log output
 * @date: 2023-04-20 11:44
 */
@Component
@Aspect
@Slf4j
public class ApiResponseAOP {<!-- -->

    @Autowired
    private SysLogService sysLogService;

    private static String [] passUrl = {<!-- -->"filtered request url"};

    @Pointcut("execution(* com.*.controller.*.*(..))")
    private void methodAspect(){<!-- -->}//Define an entry point

    @Before("methodAspect()")
    public void doAudit(JoinPoint joinPoint) {<!-- -->
        log.info("BeforeAdvice..........");
    }

    @AfterReturning(value = "methodAspect()",returning = "methodResult")
    public void afterReturning(JoinPoint joinPoint, Object methodResult) {<!-- -->
        MethodSignature ms = (MethodSignature) joinPoint. getSignature();
        Method method = ms. getMethod();
        String clazz = method. getDeclaringClass(). getName();
        log.debug("The request class is:" + clazz);
        String mName = method. getName();
        log.debug("The request method is:" + mName);
        if(Arrays. binarySearch(passUrl, mName)<0){<!-- -->
            BaseResponse baseResponse = (BaseResponse) methodResult;
            if(!baseResponse.isSuccess()){<!-- -->
                StringBuffer stringBuffer = new StringBuffer();
                for (int i = 0; i < joinPoint. getArgs(). length; i ++ ) {<!-- -->
                    log.debug("The request parameters are:" + JSON.toJSONString(joinPoint.getArgs()[i]));
                    stringBuffer.append(JSON.toJSONString(joinPoint.getArgs()[i]));
                }
                log.debug("The request returned content is:" + methodResult.toString());
                SystemLogInfoDO systemLogInfoDO = new SystemLogInfoDO();
                systemLogInfoDO.setInfo(clazz + "." + mName);
                systemLogInfoDO.setParam(stringBuffer.toString());
                systemLogInfoDO.setCode(baseResponse.getCode());
                systemLogInfoDO.setMessage(baseResponse.getMessage());
                if(baseResponse.getCode()==204){<!-- -->
                    systemLogInfoDO.setLevel("INFO");
                }else{<!-- -->
                    systemLogInfoDO.setLevel("ERROR");
                }
                sysLogService.insertSelective(systemLogInfoDO);
            }
        }
    }

    @AfterThrowing(value = "methodAspect()",throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e) {<!-- -->
        log.info("After Throwing advice");
        MethodSignature ms = (MethodSignature) joinPoint. getSignature();
        Method method = ms. getMethod();
        String clazz = method. getDeclaringClass(). getName();
        log.info("The request class is:" + clazz);
        String mName = method. getName();
        log.info("The request method is:" + mName);
        SystemLogInfoDO systemLogInfoDO = new SystemLogInfoDO();
        try {<!-- -->
            StringBuffer stringBuffer = new StringBuffer();
            for (int i = 0; i < joinPoint. getArgs(). length; i ++ ) {<!-- -->
                log.info("The request parameters are:" + JSON.toJSONString(joinPoint.getArgs()[i]));
                stringBuffer.append(JSON.toJSONString(joinPoint.getArgs()[i]));
            }
            systemLogInfoDO.setParam(stringBuffer.toString());
        }catch (Exception e1){<!-- -->
            log.info("The request method parameter cannot be parsed:" + ExceptionUtil.getMessage(e1));
            systemLogInfoDO.setParam("The request method parameter cannot be parsed");
        }
        String error = ExceptionUtil. getMessage(e);
        log.info("afterThrowing exception:{}",error);
        systemLogInfoDO.setInfo(clazz + "." + mName);
        systemLogInfoDO.setCode(500);
        systemLogInfoDO.setMessage(error);
        systemLogInfoDO.setLevel("EXCEPTION");
        sysLogService.insertSelective(systemLogInfoDO);
    }

}

Log output

2023-05-22 18:36:14 [http-nio-8831-exec-6] [com.loan.common.aop.ApiResponseAOP:82] INFO com.loan.common.aop.ApiResponseAOP - request class For: com.loan.controller.RepayController
2023-05-22 18:36:14 [http-nio-8831-exec-6] [com.loan.common.aop.ApiResponseAOP:84] INFO com.loan.common.aop.ApiResponseAOP - Request method is: repaymentRecord
2023-05-22 18:36:14 [http-nio-8831-exec-6] [com.loan.common.aop.ApiResponseAOP:89] INFO com.loan.common.aop.ApiResponseAOP - Request parameters are: \ "110014"
2023-05-22 18:36:14 [http-nio-8831-exec-6] [com.xlx.exception.GlobalExceptionHandler:26] ERROR com.xlx.exception.GlobalExceptionHandler - feign.RetryableException: Read timed out executing GET http://external-platform-server/repay/repaymentRecords
at feign.FeignException.errorExecuting(FeignException.java:213)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:115)
?…
2023-05-22 18:36:14 [http-nio-8831-exec-6] [com.loan.common.aop.ApiResponseAOP:98] INFO com.loan.common.aop.ApiResponseAOP - afterThrowing exception: feign. RetryableException: Read timed out executing GET http://external-platform-server/repay/repaymentRecords at feign.FeignException.errorExecuting(FeignException.java:213)at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:115)at feign ign.SynchronousMethodHandler. invoke(SynchronousMethodHandler.java:80) at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)

Other

For JDK dynamic proxy, please refer to an article to thoroughly understand the use of java AOP, @Before, @After, @AfterReturning, @AfterThrowing, @Around, and Spring AOP