歡迎關注驛外殘香 | hc的部落格
只能讀一次的原因
首先要知道為什麼httpservletrequest
的流只能讀取一次。
呼叫httpservletrequest.getinputstream()
可以看到獲取的流型別為servletinputstream
,繼承inputstream
。
下面複習下inputstream
,inputstream
的read
方法內部有乙個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概念理解
是指在乙個事務內,多次讀同一資料。在這個事務還沒有結束時,另外乙個事務也訪問該同一資料。那麼,在第乙個事務中的兩次讀資料之間,由於第二個事務的修改,那麼第乙個事務兩次讀到的資料可能是不一樣的。這樣就發生了在乙個事務內兩次讀到的資料是不一樣的,因此稱為是不可重複讀。前提是非序列化 乙個事務在執行過程中...