寫在前面:2020年面試必備的Java後端進階面試題總結了一份複習指南在Github上,內容詳細,圖文並茂,有需要學習的朋友可以Star一下!
GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master
Spring Boot的httptrace端口能夠記錄每次訪問的請求和響應信息,但是不能記錄body,這樣在出問題時就不方便排查,而且httptrace不方便在原有的基礎上進行擴展,所以只能尋求其他方式進行記錄。
Logbook是一個可擴展的Java庫,可以爲不同的客戶端和服務端技術提供完整的請求和響應日誌記錄。它能夠滿足一些特殊的需求:
- 允許web應用記錄程序接收或發送的所有HTTP通信
- 易於保留和進行分析
Logbook在大部分情況下是開箱即用的,即使對於一些不常用的技術或者應用,實現它們也非常簡單。
特性
日誌記錄:HTTP請求和響應,包含body;未授權的請求會記錄部分日誌(不包含body)
自定義:能夠自定義記錄格式、記錄方式以及請求記錄的條件
支持框架:Servlet容器,Apache’s HTTP client,Square’s OkHttp等
混淆敏感數據
Spring Boot自動配置
合理的默認值
快速開始
Logbook爲Spring Boot用戶提供了很方便的自動配置功能,即我們所熟悉的 starter 。它使用了合理的默認值自動配置了以下功能:
Servlet filter
適用於未授權請求的Servlet filter(如果檢測到項目中使用Spring Security)
Header過濾器、Parameter過濾器、Body過濾器
HTTP格式化器、JSON格式化器
日誌寫入方式
引入 starter 模塊:
默認配置下,輸出的日誌爲JSON格式:
Request
Response
配置
下面的表格展示了可配置的選項:
配置示例
詳細用法
所有的功能集成都需要一個 Logbook 實例來完成,它保存了所有的配置並將所有需要的組件連接在一起。你可以使用所有的默認值創建一個實例:
或者使用 LogbookBuilder 創建一個自定義的版本:
在使用 starter 時,我們只需要自定義相應的 Bean 即可。
策略
Logbook使用一個非常硬性的策略來執行請求/響應日誌記錄:
請求/響應分開記錄
請求/響應儘快記錄
請求/響應一起記錄或不記錄
從2.0版本開始,Logbook引入了一個新的策略模式爲核心,它內置了部分策略:
BodyOnlyIfStatusAtLeastStrategy
StatusAtLeastStrategy
WithoutBodyStrategy
階段
Logbook工作在幾個不同的階段:
條件
過濾
格式化
記錄
每個階段都由一個或多個可以自定義的接口完成。每個階段都有一個合理的默認值。
條件
記錄HTTP消息並且包含其body的代價是非常大的,所以禁用某些請求的日誌記錄非常有意義。一個常見的情景就是忽略一些不必要的請求,比如Spring Boot的Actuator端點。
定義一個條件非常簡單,只需要編寫一個 Predicate 來決定請求是否需要記錄。當然,你也可以組合預定義的 Predicate :
對與路徑的包含和排除也可以通過設置 logbook.include 和 logbook.exclude 屬性實現。
過濾
過濾的目的是防止記錄HTTP請求和響應的某些敏感數據。這通常包括Authorization請求頭,但也可以用於某些明文查詢或表單參數,例如access_token和password。
Logbook支持不同類型的過濾器:
SpringBoot使用Logbook記錄HTTP請求響應日誌
QueryFilter , PathFilter , HeaderFilter 和 BodyFilter 能夠滿足絕大多數情況下的需求,對於更復雜的需求,可以使用 RequestFilter 和 ResponseFilter 。
關聯
Logbook使用一個id來關聯請求和響應,因爲請求和響應通常位於日誌文件中的不同位置。
在Spring Cloud應用中一般會集成Zipkin進行鏈路追蹤,此時可以使用TraceId來關聯請求和響應日誌記錄。
如果默認實現不滿足你的需求,你可以提供一個自定義的實現:
格式化
格式化定義瞭如何把請求和響應轉換爲字符串的方式。格式化不會指定請求和響應的記錄位置,這是由writer來完成的。
Writer
Writer定義了格式化後的請求和響應寫入的位置。Logbook內置了三種實現:Logger,Stream和Chunking。
Logger
默認情況下,請求和響應使用了slf4j來進行日誌記錄,日誌的級別爲 trace 。你也可以自定義:
Stream
另一種實現方式是記錄請求和響應到 PrintStream ,例如 System.out 或 System.err 。在生產環境中這是一個糟糕的選擇,但有時對於短暫的本地開發和調試很有用。
Chunking
ChunkingSink 會把長的消息分割成較小的塊,並且會委託給另一個sink將它們寫入,只需要設置 logbook.write.chunk-size 屬性即可。
Sink
HttpLogFormatter 和 HttpLogWriter 的組合能夠適用於大部分場合,但是也有一些侷限性。實現 Sink 接口可以實現更復雜的需求,例如把請求和響應持久化到數據庫。
你可以使用 CompositeSink 將多個Sink合併爲一個。
Servlet
在Servlet環境中,Logbook是通過 LogbookFilter 來實現的。默認情況下,對於
application/x-www-form-urlencoded 請求會同等對待,即你會在日誌中看到請求body。這種方法的缺點是下游代碼將無法使用任何
HttpServletRequest.getParameter*(…) 方法。
從Logbook 1.5.0開始,可以使用
logbook.servlet.form-request 系統屬性(System Property)指定三種策略之一,這些策略定義Logbook如何處理這種情況:
其他框架支持
Logbook默認還提供了對HTTP Client、JAX-RS、Netty、OkHttp v2.x、OkHttp v3.x的支持,具體使用方法可以參考官方文檔。