在本文中,我們將探討如何從Spring Boot 過濾器中的ServletResponse檢索響應正文。
本質上,我們將定義問題,然後使用快取響應正文的解決方案,使其在 Spring Boot 過濾器中可用。讓我們開始。
首先,讓我們瞭解我們要解決的問題。
使用 Spring Boot 過濾器時,從 ServletResponse 訪問響應主體很 棘手。這是因為響應主體不容易獲得,因為它是在過濾器鏈完成執行後寫入輸出流的。
但是,某些操作(例如生成雜湊簽名)需要響應正文的內容,然後才能將其傳送到客戶端。因此,我們需要找到一種方法來讀取body的內容。
在過濾器中使用ContentCachingResponseWrapper
為了克服前面定義的問題,我們將建立一個自定義過濾器並使用Spring Framework 提供的ContentCachingResponseWrapper類:
@Override |
簡而言之,包裝類允許我們包裝HttpServletResponse來快取響應正文內容,並呼叫doFilter()將請求傳遞到下一個過濾器。
請記住,我們一定不要忘記這裡的doFilter()呼叫。否則,傳入的請求將不會進入 Spring 過濾器鏈中的下一個過濾器,應用程式也不會按照我們的預期處理該請求。事實上,不呼叫doFilter()是違反servlet規範的。
此外,我們一定不要忘記使用responseCacheWrapperObject呼叫doFilter ()。否則,響應正文將不會被快取。簡而言之,ContentCachingResponseWrapper將過濾器放置在響應輸出流和發出 HTTP 請求的客戶端之間。因此,在建立響應主體輸出流後(在本例中是在doFilter()呼叫之後),內容可在過濾器內進行處理。
使用包裝器後,可以使用getContentAsByteArray()方法在過濾器中獲取響應正文。我們使用這個方法來計算MD5雜湊值。
首先,我們使用MessageDigest類建立響應正文的 MD5 雜湊值。其次,我們將位元組陣列轉換為十六進位制字串。第三,我們使用setHeader()方法將生成的雜湊字串設定為響應物件的標頭。
如果需要,我們可以將位元組陣列轉換為字串,並使正文的內容更加明確。
最後,在退出doFilter()方法之前呼叫copyBodyToResponse()至關重要,以將更新後的響應正文複製回原始響應:
responseCacheWrapperObject.copyBodyToResponse();
在退出doFilter()方法之前呼叫copyBodyToResponse()至關重要。否則,客戶端將不會收到完整的響應。
配置過濾器
現在,我們需要在 Spring Boot 中新增過濾器:
@Bean |
在這裡,我們使用 我們之前建立的過濾器的實現來配置建立一個FilterRegistrationBean 。
測試MD5
最後,我們可以使用Spring 中的整合測試來測試一切是否按預期工作:
@Test |
在這裡,我們呼叫/api/example控制器,它返回“Hello, World!”正文中的文字。我們定義了getMD5Hash()方法,它將響應轉換為 MD5,類似於我們在過濾器中使用的:
private String getMD5Hash(String input) throws NoSuchAlgorithmException { |
結論
在本文中,我們學習瞭如何使用ContentCachingResponseWrapper類從Spring Boot 過濾器中的ServletResponse檢索響應正文。我們使用此機制來展示如何在 HTTP 響應標頭中實現正文的 MD5 編碼。