Spring中的Filter、HandlerInterceptor和AOP

问题来源于我想打印请求和响应结构体,那么怎么做?
网上搜索到相关的有种方式都可以

  • Filter
  • HandlerInterceptor
  • AOP

对三个的关系不太熟,所以大概了解了一下

简要梳理一下一个Spring应用服务处理请求的逻辑首先:

  • 客户端请求
  • 服务器容器处理(tomcat)
  • 匹配Url的Filter依次执行
  • 匹配的Servlet(对于Spring来说,就是DispatcherServlet)
  • HandlerMapping找到对应的控制器
  • HandlerAdaptor调用匹配的控制器,在这一步执行前,会调用注册的HandlerInterceptor
    • 注意这里调用的控制器,一般是通过Spring的DI注入的容器,如果有了AOP切面,则实际调用的可能是AOP生成的Proxy

所以这三者功能上都可以做

  • Filter在容器层,由容器调用。FIlter功能更强大,甚至可以改变Request,Response的请求内容
  • HandlerInterceptor在控制器方法执行前,可以看到有post/pre/afterCompletion方法对应处理的3个阶段
  • AOP应该是可以做日志的最后一步了,下一步就到了逻辑了

Interceptor和Filter也试过了,最终选择的是通过AOP来做,优点是这里直接可以获取方法参数(通过ProceedingJoinPoint getArgs())。

而在Intercetpor和Filter中需要从Request/Response中直接操作流,由于流被读取后无法再次读取,所以一般用这种方法都要将流复制一份出来,看起来比较像hack。

这里AOP最大的限制在于Spring默认的代理模式,如果方法参数有类似@Valid的注解,会先执行校验,如果校验失败,那么无法走进我们的AOP。

当然如果想要打印原始的请求参数(而不是方法的入参),那么也不能用AOP。

上一篇:Spring MVC拦截器学习


下一篇:springboot 自定义拦截器