post請求體內容無法重復獲取
為什么會無法重復讀取呢?
以tomcat為例,在進行請求體讀取時實際底層調用的是org.apache.catalina.connector.Request的getInputStream()方法,而該方法返回的是CoyoteInputStream輸入流
public?ServletInputStream?getInputStream()?throws?IOException?{
????if?(usingReader)?{
????????throw?new?IllegalStateException(sm.getString("coyoteRequest.getInputStream.ise"));
????}
????usingInputStream?=?true;
????if?(inputStream?==?null)?{
????????inputStream?=?new?CoyoteInputStream(inputBuffer);
????}
????return?inputStream;
}
在使用CoyoteInputStream進行讀取時
public?int?read(byte[]?b,?int?off,?int?len)?throws?IOException?{
??//?如果流關閉,則拋出異常
????if?(closed)?{
????????throw?new?IOException(sm.getString("inputBuffer.streamClosed"));
????}
//?如果已經讀完了,則返回-1
????if?(checkByteBufferEof())?{
????????return?-1;
????}
????int?n?=?Math.min(len,?bb.remaining());
????bb.get(b,?off,?n);
????return?n;
}
而流讀取完畢都會進行close,這個流close之后,close狀態就置為了true,所以導致流無法進行二次讀取
那么如何解決呢?將tomcat的Request類進行重新實現嗎?代價太大了,sun公司當初在設計的時候就已經提供了解決方法,對于請求和響應,sun公司提供了包裝類,可以HttpServletRequestWrapper類包裝原始的request對象,實現了HttpServletRequest接口的所有方法,內部調用了所包裝的request對象的對應方法;相應的也有HttpServletResponseWrapper類來包裝原始的response對象繼承HttpServletRequestWrapper來進行方法重寫,可以使用HttpServletResponseWrapper和HttpServletRequestWrapper來進行定制響應和請求
public?class?BodyReaderHttpServletRequestWrapper?extends?HttpServletRequestWrapper?{
??//?存儲請求體
????private?byte[]?body;
????private?HttpServletRequest?orgRequest;
????public?BodyReaderHttpServletRequestWrapper(HttpServletRequest?request)?throws?IOException?{
????????super(request);
????????this.orgRequest?=?request;
????????body?=?HttpHelper.getBody(request);
????}
????public?HttpServletRequest?getOrgRequest()?{
????????return?this.orgRequest;
????}
??//?重寫讀取,從存儲的字節數組中讀
????@Override
????public?BufferedReader?getReader()?throws?IOException?{
????????return?new?BufferedReader(new?InputStreamReader(getInputStream()));
????}
??//?重寫讀取,從存儲的字節數組中讀
????@Override
????public?ServletInputStream?getInputStream()?throws?IOException?{
????????final?ByteArrayInputStream?bais?=?new?ByteArrayInputStream(body);
????????return?new?ServletInputStream()?{
????????????@Override
????????????public?int?read()?throws?IOException?{
????????????????return?bais.read();
????????????}
????????????@Override
????????????public?boolean?isFinished()?{
????????????????return?false;
????????????}
????????????@Override
????????????public?boolean?isReady()?{
????????????????return?false;
????????????}
????????????@Override
????????????public?void?setReadListener(ReadListener?readListener)?{
????????????}
????????};
????}
}
https://zhhll.icu/2020/javaweb/問題/6.post請求體內容無法重復獲取/
本文由 mdnice 多平臺發布