Springboot中基于AOP和拦截器两种方式记录请求日志的对比

相关依赖文件

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <!--fastjson依赖-->
   
<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.44</version>
    </dependency>

Controller测试类

package com.ljt.demo.controller;
 @RestController
public class DemoController {

    @GetMapping("/test/{name}")

    public String test(@PathVariable String name,

                       @RequestParam String param){

        name = "hello "+name+"  "+param;

        return name;
    }
}

AOP方式:

新建类WebcontrollerAop,代码如下:

@Aspect
@Component
public class WebControllerAop {
    /**
     * 指定切点
     * 匹配 com.example.demo.controller包及其子包下的所有类的所有方法
     */
    @Pointcut("execution(public * com.ljt.demo.controller.*.*(..))")
    public void  optlog(){
    }

    /**
     * 前置通知,方法调用前被调用
     * @param joinPoint
     */
    @Before("optlog()")
    public void doBefore(JoinPoint joinPoint){
       // System.out.println("我是前置通知,方法执行前调用...");
        //获取目标方法的参数信息
       Object[] obj = joinPoint.getArgs();
        Signature signature = joinPoint.getSignature();
        //代理的是哪一个方法
        String methodName = signature.getName();
        //AOP代理类的名字
        String className = signature.getDeclaringTypeName();
        MethodSignature methodSignature = (MethodSignature) signature;
        String[] strings = methodSignature.getParameterNames();
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = attributes.getRequest();
        StringBuffer content = new StringBuffer();
        content.append("url="+req.getRequestURI());
        content.append(" ,paramName=").append(Arrays.toString(strings));
        content.append(" ,paramValue=").append( Arrays.toString(joinPoint.getArgs()));
        content.append( ", clientIp=").append( req.getRemoteAddr());
        content.append(" ,HTTP_METHOD=").append(req.getMethod());
        content.append(" ,methodName=").append(methodName);
        content.append(" ,methodClassName=").append(className);
        System.out.println("AOP方式:"+content);
        //设置请求开始时间
        req.setAttribute("STARTTIME2", System.currentTimeMillis());

    }



    /**
     * 处理完请求返回内容
     * @param ret
     * @throws Throwable
     */

    @AfterReturning(returning = "ret", pointcut = "optlog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
      //  System.out.println("方法的返回值 : " + ret);
    }



    /**
     * 后置异常通知
     * @param jp
     */

    @AfterThrowing("optlog()")
    public void throwss(JoinPoint jp){
        System.out.println("方法异常时执行.....");
    }

    /**
     * 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
     * @param jp
     */
    @After("optlog()")
    public void after(JoinPoint jp){
      //  System.out.println("方法最终执行.....");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = attributes.getRequest();
        //当前时间
        long currentTime = System.currentTimeMillis();
        long  startTime = Long.valueOf(req.getAttribute("STARTTIME2").toString());
        System.out.println("AOP方式请求耗时:"+(currentTime - startTime)+"ms");
    }



    /**
     * 环绕通知,环绕增强,相当于MethodInterceptor
     * @param pjp
     * @return
     */

    @Around("optlog()")
    public Object arround(ProceedingJoinPoint pjp) {
        try {
            Object o =  pjp.proceed();
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;

        }

    }

}
 

拦截器方式:

1.新建拦截器类WebInterceptor实现HandlerInterceptor接口

   public class WebInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         //请求路劲
         String url = request.getRequestURI();
         //获取请求参数信息
         String paramData = JSON.toJSONString(request.getParameterMap(),SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.WriteMapNullValue);
         //获取请求客户都IP
        String clientIp = request.getRemoteAddr();
        //请求方法
         String  methodName = request.getMethod();
      //   String  requestType = request.getHeader("X-Requested-With");
         StringBuffer content = new StringBuffer();
         content.append("url="+url);
         content.append(" ,paramData=").append(paramData);
         content.append( ", clientIp=").append(clientIp);
         content.append(" ,HTTP_METHOD=").append(methodName);
         System.out.println("拦截器方式:"+content);
        //设置请求开始时间
         request.setAttribute("STARTTIME", System.currentTimeMillis());
         return true;
    }



    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        //controller 方法处理完毕后,调用此方法
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {

        //页面渲染完毕后调用次方法,通常用来清除某些资源,类似java中的finnally
        int status = response.getStatus();
         //当前时间
        long currentTime = System.currentTimeMillis();
        long  startTime = Long.valueOf(request.getAttribute("STARTTIME").toString());
        System.out.println("拦截器方式请求耗时:"+(currentTime - startTime)+"ms");
    }

}

2.添加拦截器

 @Configuration
public class MvcConfigurer implements WebMvcConfigurer {
    //拦截器
    public void addInterceptors(InterceptorRegistry registry){
     //增加一个拦截器
        registry.addInterceptor(new WebInterceptor()).addPathPatterns("/**");
    }
}

运行测试

  1. 启动项目
  2. 浏览器输入地址: http://localhost:8080/test/hello?param=123456

控制台打印输出:

0f4c5aa99d485ae672faf04044ea8f48fbe.jpg

总结:

  1. 一个controler方式的执行过程中,拦截器最先开始执行,最后执行完毕。
  2. 对于请求参数的获取,AOP方式更加的完整、准确,可以获取到@PathVariable 注解的参数。 如例子中hello就是一个参数。
  3. AOP方式对与请求信息获取的更加详细,可以获取到方法名称和所在的类。

  完整代码见: https://gitee.com/freide/springboot

转载于:https://my.oschina.net/freide/blog/2989724

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值