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