Spring Boot 中的AOP使用示例,打印请求执行时间等

巧了我就是萌 提交于 2020-03-12 10:15:49

参考书:Spring实战(第4版) Spring Boot 2 精髓

IDE: IDEA 2019.2.3

Maven 3.6.2

Spring Boot 2.1.10.RELEASE

Knife4j


一、准备:

1. 对Spring AOP 有点了解

2. pom中添加aop的starter

如果parent定义了版本,此处可以不加version

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.1.10.RELEASE</version>
</dependency>

二、配置

1. 在启动类添加自动代理注解

@EnableAspectJAutoProxy

2. 编写切面

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;

@Configuration
public class GlobalConfig {


    @Bean
    StopWatch stopWatch(){
        return new StopWatch();
    }
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

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

@Component
@org.aspectj.lang.annotation.Aspect
public class Aspect {
    private static final Logger logger = LoggerFactory.getLogger(Aspect.class);

    @Autowired
    private StopWatch stopWatch;

    @Pointcut(value = "execution(com.tjonecorp.meeting.base.ReturnEntity com.tjonecorp.meeting.controller.*.*(..)) " +
            "&& @annotation(org.springframework.web.bind.annotation.GetMapping)" +
            "|| @annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void getReq() {
        // 切点
    }

    @Around("getReq()")
    public Object simplePrintReqProcess(ProceedingJoinPoint pjp) throws Throwable {
        // 通知开始时计时
        stopWatch.start();

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取请求的request
        HttpServletRequest request = attributes.getRequest();

        // 连接点所在类对象
        Object o = pjp.getTarget();

        // 连接点所在方法
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();

        // 输出请求log
        logger.info("--------------------------------Request Start--------------------------------");
        logger.info("Request URL: {}", request.getRequestURI());
        logger.info("Request Method: {}", o.getClass().getName() + "." + method.getName());
        Object result = pjp.proceed();
        stopWatch.stop();
        logger.info("Request done in {}ms", stopWatch.getTotalTimeMillis());
        logger.info("--------------------------------Response Success--------------------------------\n");
        return result;
    }

}

看看效果:

 

注意:如果不用变量接收 pjp.proceed(),控制器中方法的返回体无法得到,可用swagger测试便知。

以上代码sonar扫描没有大问题,可直接粘贴稍作修改即可。

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!