2013-08-28 21 views
8

我處於這種情況,我的應用程序需要檢查POST請求的內容/數據/正文/有效內容,而不更改後續getParameter調用的結果。閱讀HTTPServletRequest的POST正文,然後在Tomcat中調用getParameter

從InputStream讀取體:

主體可以使用從request.getInputStream或從的BufferedReader request.getReader InputStream的讀取。

讀POST參數:

POST請求通常包括在請求的主體中的請求參數。這些可以使用getParameter來檢索。

問題:

第一getParameter呼叫內部解析InputStream和插入所有參數成參數HashMap中。它要求inputStream仍然包含解析的內容。因此,人們無法檢查內容,並仍然有一個正在進行的getParameter調用。

的提案(但不充分)解決方案

創建緩存InputStream和返回的getInputStream緩存請求包裝。

我見過的解決方案建議所有網站上,但它不工作,因爲getParameter實際上不叫getInputStream,而是指埋在請求對象的原始INPUTBUFFER。我試過了,都是從Servlet內部和通過使用過濾器

我能想到的唯一解決方案涉及重寫getParameter實際上手動解析緩存的輸入流。但是這感覺是一個糟糕的主意。

有沒有人有別的辦法? (這是Tomcat 5.5)這感覺應該是一個常見的用例;我無法相信它有多難。

+1

該問題的答案不是解決方案。我已經實現了它,但它無法解決問題。從那以後,我讀了tomcat源代碼,並意識到getParameter不會調用getInputStream,如上所述,所以不會從緩存的流版本中讀取。 請參閱http://grepcode.com/file/repo1.maven.org/maven2/tomcat/catalina/5.5.23/org/apache/catalina/connector/RequestFacade.java?av=f#342 我不是肯定爲什麼人們似乎發現它是一個解決方案。 – rewolf

+0

getParameter方法調用getInputStream。首先,getParameter調用parseParameters然後調用parseParameters調用readPostBody然後調用readPostBody調用getInputStream。 – peakmuma

回答

1

正如@caskey所建議的,可能的解決方案是使用反射來將inputBuffer替換爲可重放的輸入緩衝區。但我沒有使用這種方法,因爲它覺得調皮。

相反,我在過濾器中讀取InputStream的成字節數組,並返回內部使用ByteArrayInputStream圍繞陣列的所有getInputStream調用一個新的InputStream創建請求包裝。

在讀取輸入流到字節數組後,我通過解析有效載荷來創建一個參數映射。我將超類的參數映射合併爲支持查詢參數的GET案例。我已經重寫了所有的getParameter *()方法來使用這個參數映射。

我用apache.axis.utils.IOUtils.readFully很容易讀取流入字節數組。而我目前使用javax.servlet.http.HttpUtils.parsePostData來解析數據到參數映射中。 HttpUtils.parsePostData實際上已被棄用,所以我會在找到它時用更好的版本替換它。

但是,這個作品,耶!

1

(這是一個相當古老的tomcat,我假設升級到更現代的一個是不是一種選擇。)

你想做的事,需要攔截的具體HttpServletResponse對象包裝底層的建築是什麼的InputStream。在推回輸入流(或等效)中包裝InputStream是必要的。

Tomcat 5.5已經很老了我甚至無法想象這將如何實現'正常',但也許你可以編寫一個過濾器,使用反射來訪問和交換具體請求對象內的InputStream對象。

+0

是的。你對反思的想法很有幫助。我們也想出了它。我選擇了一種不同的方法 - 在支持重播輸入流的過濾器中創建請求包裝器。然後我重寫了getParameter *()方法從解析輸入流/有效載荷創建的映射中讀取。 – rewolf