關(guān)于post請求內(nèi)容無法重復獲取的解決方法
post請求體內(nèi)容無法重復獲取
為什么會無法重復讀取呢?
以tomcat為例,在進行請求體讀取時實際底層調(diào)用的是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 { // 如果流關(guān)閉,則拋出異常 if (closed) { throw new IOException(sm.getString("inputBuffer.streamClosed")); } // 如果已經(jīng)讀完了,則返回-1 if (checkByteBufferEof()) { return -1; } int n = Math.min(len, bb.remaining()); bb.get(b, off, n); return n; }
而流讀取完畢都會進行close,這個流close之后,close狀態(tài)就置為了true,所以導致流無法進行二次讀取
那么如何解決呢?將tomcat的Request類進行重新實現(xiàn)嗎?代價太大了,sun公司當初在設(shè)計的時候就已經(jīng)提供了解決方法,對于請求和響應,sun公司提供了包裝類,可以HttpServletRequestWrapper類包裝原始的request對象,實現(xiàn)了HttpServletRequest接口的所有方法,內(nèi)部調(diào)用了所包裝的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; } // 重寫讀取,從存儲的字節(jié)數(shù)組中讀 @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } // 重寫讀取,從存儲的字節(jié)數(shù)組中讀 @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) { } }; } }
到此這篇關(guān)于關(guān)于post請求內(nèi)容無法重復獲取的解決方法的文章就介紹到這了,更多相關(guān)post請求無法重復獲取內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
WIN7系統(tǒng)JavaEE(tomcat7 Eclipse)環(huán)境配置教程(二)
這篇文章主要介紹了WIN7系統(tǒng)JavaEE(java+tomcat7+Eclipse)環(huán)境配置教程,本文重點在于tomcat配置、Eclipse配置,感興趣的小伙伴們可以參考一下2016-06-06Java 圖解Spring啟動時的后置處理器工作流程是怎樣的
spring的后置處理器有兩類,bean后置處理器,bf(BeanFactory)后置處理器。bean后置處理器作用于bean的生命周期,bf的后置處理器作用于bean工廠的生命周期2021-10-10java并發(fā)編程專題(一)----線程基礎(chǔ)知識
這篇文章主要介紹了java并發(fā)編程線程的基礎(chǔ)知識,文中講解非常詳細,幫助大家更好的學習JAVA并發(fā)編程,感興趣想學習JAVA的可以了解下2020-06-06在Spring Boot中集成RabbitMQ詳細步驟(最新推薦)
本文將介紹如何在Spring Boot項目中集成RabbitMQ,實現(xiàn)生產(chǎn)者和消費者的基本配置,本文分步驟給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-12-12Spring Boot Redis客戶端遠程操作實現(xiàn)過程解析
這篇文章主要介紹了Spring Boot Redis客戶端遠程操作實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04Redis使用RedisTemplate模板類的常用操作方式
這篇文章主要介紹了Redis使用RedisTemplate模板類的常用操作方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09