Request IO流無法重複讀取的原因和解決方法

2021-09-02 23:30:46 字數 2932 閱讀 2112

歡迎關注驛外殘香 | hc的部落格

只能讀一次的原因

首先要知道為什麼httpservletrequest的流只能讀取一次。

呼叫httpservletrequest.getinputstream()可以看到獲取的流型別為servletinputstream,繼承inputstream

下面複習下inputstream,inputstreamread方法內部有乙個postion,標誌當前流讀取到的位置,每讀取一次,位置就會移動一次,如果讀到最後,read()會返回-1,標誌已經讀取完了。如果想要重新讀取則需要重寫reset()方法,當然能否reset是有條件的,它取決於marksupported()是否返回true。

inputstream原始碼中預設不實現reset(),並且marksupported()預設返回false:

public

synchronized

void

reset()

throws ioexception

public

boolean

marksupported()

而檢視servletinputstream原始碼可以發現,該類沒有重寫mark(),reset()以及marksupported(),因此request io流無法重複讀取

public

abstract

class

servletinputstream

extends

inputstream

public

intreadline

(byte

b,int off,

int len)

throws ioexception

else

}return count >

0? count :-1

;}}public

abstract

boolean

isfinished()

;public

abstract

boolean

isready()

;public

abstract

void

setreadlistener

(readlistener var1)

;}

既然servletinputstream不支援重新讀寫,那麼為什麼不把流讀出來後用容器儲存起來,後面就可以多次利用了。

/**

* **來自網路,侵刪

*/ private final byte body;

super(request);

string sessionstream = getbodystring(request);

body = sessionstream.getbytes(charset.forname("utf-8"));

}/**

* 獲取請求body

** @param request 請求

* @return body字串

*/private string getbodystring(final servletrequest request)

}catch (ioexception e)

finally

catch (ioexception e)

}if (reader != null)

catch (ioexception e) }}

return sb.tostring();

}/**

* 複製輸入流

* @param inputstream 請求輸入流

* @return 複製出來的輸入流

*/private inputstream cloneinputstream(servletinputstream inputstream)

bytearrayoutputstream.flush();

}catch (ioexception e)

return new bytearrayinputstream(bytearrayoutputstream.tobytearray());

}@override

public bufferedreader getreader()

@override

public servletinputstream getinputstream()

@override

public boolean isfinished()

@override

public boolean isready()

@override

public void setreadlistener(readlistener readlistener) };}

}

並且在讀取請求流的過濾器中使用該包裝器:

@override

public

void

dofilter

(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain)

throws ioexception, servletexception

這時候就在後面的**中再次呼叫流了

mysql 可重複讀。

一 可重複讀 我們先看看現象,再分析原理。我的mysql版本是5.5。下面是一張表,只有一條資料,並且我開啟了事物 此時,另乙個事物將record加1,因此我在開啟乙個命令列客戶端,執行下面的命令 成功加1之後,實際上,資料庫中record肯定是2。然後回到之前的客戶端,再查一次 沒毛病,recor...

mysql可重複讀

mysql innodb的預設隔離級別是可重複讀,之前理解有些偏差,查閱一些資料後總結出幾點 首先有兩個概念 一致性檢視 當乙個事務開啟時,innodb會生成乙個檢視,這個檢視是邏輯檢視,通過undo log和row tranzaction id控制實現。在該事務的任何時間點,一致性檢視中的資料都是...

不可重複讀,可重複讀,幻讀,MVCC概念理解

是指在乙個事務內,多次讀同一資料。在這個事務還沒有結束時,另外乙個事務也訪問該同一資料。那麼,在第乙個事務中的兩次讀資料之間,由於第二個事務的修改,那麼第乙個事務兩次讀到的資料可能是不一樣的。這樣就發生了在乙個事務內兩次讀到的資料是不一樣的,因此稱為是不可重複讀。前提是非序列化 乙個事務在執行過程中...