問題來源於我想打印請求和響應結構體,那么怎么做?
網上搜索到相關的有種方式都可以
- 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。