Aop 日志切面,打印日志

1 日志打印用来监控程序的执行很重要

 手动在Controller 里面打印日志很繁琐。

package com.mangoubiubiu.controller;


import com.alibaba.fastjson.JSONObject;
import com.mangoubiubiu.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

@RestController
@Slf4j
public class LoginController {

    @PostMapping("login")
    public R login(@RequestBody JSONObject jsonObject, HttpServletRequest request){
        log.info("Thread name is {} Invoke api url is {}  in params is {}",Thread.currentThread().getName(),request.getRequestURL(),jsonObject.toJSONString());
        //----业务代码 调用service
        log.info("Thread name is {} Invoke api url is {}  out params is {}",Thread.currentThread().getName(),request.getRequestURL(),R.ok().data(jsonObject));
        return R.ok().data(jsonObject);

    }


}

Aop 日志切面,打印日志

 虽然也能打印到,但是有一万个 方法 就复制黏贴二万条 那多多少少有点拉胯,而且不易维护。

二 进阶,利用Aop进行切面,进行日志打印

package com.mangoubiubiu.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
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.util.Arrays;

/**
 * 日志切面类
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(public * com.mangoubiubiu.controller.*.*(..))")
    public void pointCut(){}

    /**
     * 前置通知 在目标方法 运行前执行
     * @param joinpoint
     */
    @Before("pointCut()")
    public void logStart(JoinPoint joinpoint){
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String requestURL = request.getRequestURL().toString();
        //获取入参信息
        Object[] args=   joinpoint.getArgs();
        log.info("Thread name is {} Invoke api url is {}  in params is {}",Thread.currentThread().getName(),requestURL,Arrays.asList(args));
    }

    /**
     *   返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后执行
     * @param joinpoint
     * @param result
     */
    //JoinPoint 一定要出现在参数表的第一位
    @AfterReturning(value="pointCut()",returning="result")
    public void logreturn(JoinPoint joinpoint,Object result){
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String requestURL = request.getRequestURL().toString();
        log.info("Thread name is {} Invoke api url is {}  out params is {}",Thread.currentThread().getName(),requestURL,result);
    }
}

 Aop 日志切面,打印日志

 

 测试 

Aop 日志切面,打印日志

 

 Aop 日志切面,打印日志

 

 

2021-12-10 22:04:38.530  INFO 9816 --- [io-10090-exec-1] com.mangoubiubiu.aspect.LogAspect        : Thread name is http-nio-10090-exec-1 Invoke api url is http://127.0.0.1:10090/login_by_session/login  in params is [{"mayr":"你看后"}, org.apache.catalina.connector.RequestFacade@6eaba842]
2021-12-10 22:04:38.594  INFO 9816 --- [io-10090-exec-1] com.mangoubiubiu.aspect.LogAspect        : Thread name is http-nio-10090-exec-1 Invoke api url is http://127.0.0.1:10090/login_by_session/login  out params is R(success=true, code=20000, message=成功, data={"mayr":"你看后"})

非常nice

二 再次进阶,如果我想计算接口调用耗时 怎么做---利用环绕通知(永远滴神)

package com.mangoubiubiu.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sun.rmi.transport.ObjectTable;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 日志切面类
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    /**
     * 切入点
     */
    @Pointcut("execution(public * com.mangoubiubiu.controller.*.*(..))")
    public void pointCut(){}

    /**
     * 前置通知 在目标方法 运行前执行
     * @param joinpoint
     */
    //@Before("pointCut()")
    public void logStart(JoinPoint joinpoint){
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String requestURL = request.getRequestURL().toString();
        //获取入参信息
        Object[] args=   joinpoint.getArgs();
        log.info("Thread name is {} Invoke api url is {}  in params is {}",Thread.currentThread().getName(),requestURL,Arrays.asList(args));
    }

    /**
     *   返回通知(@AfterReturning):logReturn:在目标方法(div)正常返回之后执行
     * @param joinpoint
     * @param result
     */
    //JoinPoint 一定要出现在参数表的第一位
    //@AfterReturning(value="pointCut()",returning="result")
    public void logreturn(JoinPoint joinpoint,Object result){
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String requestURL = request.getRequestURL().toString();
        log.info("Thread name is {} Invoke api url is {}  out params is {}",Thread.currentThread().getName(),requestURL,result);
    }


    /**
     * 环绕通知
     * @param joinPoint
     * @return
     */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String requestURL = request.getRequestURL().toString();
        Object[] args=   joinPoint.getArgs();

        try {
            Long startTime=System.currentTimeMillis();
            log.info("Thread name is {} Invoke api url is {}  in params is {}",Thread.currentThread().getName(),requestURL,Arrays.asList(args));
            //执行目标方法
            Object result = joinPoint.proceed();
            log.info("Thread name is {} Invoke api url is {}  out params is {} Time-consuming {}ms",Thread.currentThread().getName(),requestURL,result,System.currentTimeMillis()-startTime);
            return result;
        }catch (Throwable e){

        }
        return null;
    }



}

Aop 日志切面,打印日志

 

 注掉了哈

测试

Aop 日志切面,打印日志

Aop 日志切面,打印日志

 

 非常强大

三 再次进阶,环绕通知 篡改返回参数

Aop 日志切面,打印日志

 

 测试

Aop 日志切面,打印日志

 

 非常强大 , 环绕通知的返回参数,就是方法的返回参数,并且能修改方法的返回参数,在实际应用场景中可以塞值,非常好用。

上一篇:自定义注解+AOP,优雅的打印方法接受和返回的参数内容


下一篇:Spring 之使用 AOP