在jetty中buffer是對java中stream io中的buffer和nio中的buffer的抽象表示,它主要用于緩存連接配接中讀取和寫入的資料。在jetty中,對每個連接配接使用buffer從其inputstream中讀取位元組資料,或将處理後的響應位元組寫入outputstream中,進而jetty其他子產品在處理請求和響應資料時直接和buffer打交道,而不需要關注底層io流。
jetty中buffer接口定義如下:
public interface buffer extends cloneable {
// 基于buffer主要用于向目前連接配接讀寫資料,因而它定義了兩個核心的方法:readfrom和writeto。其中readfrom方法從inputstream中讀取位元組資料,writeto方法将響應位元組寫入outputstream中,即向connection中讀取和寫入資料,寫完後清理目前buffer。
int readfrom(inputstream in, int max) throws ioexception;
void writeto(outputstream out) throws ioexception;
// 在buffer從inputstream(connection)中讀取資料後,buffer接口還提供了很多不同的方法用于從buffer中讀取或寫入位元組資料。
// jetty中的buffer是一個fifo的位元組隊列,它的設計類似nio中buffer的設計:每次get操作都從getindex開始,并且getindex會向前移動讀取的位元組數的長度;每次的peek操作也getindex開始,但是peek操作不會使getindex向前移動;每次put操作都從putindex開始,并且putindex會向前移動寫入的位元組數的長度;每次poke操作也會從putindex開始,但是poke操作不會使putindex向前移動;mark操作會以getindex作為基準設定markindex的值,進而在reset時會将getindex重置到之前mark過的位置;capacity表示該buffer最多可存儲的位元組數,而length表示從getindex到putindex還存在的位元組數。并且buffer永遠保證以下關系總是成立:markindex<=getindex<=putindex<=capacity
byte get();
int get(byte[] b, int offset, int length);
buffer get(int length);
int getindex();
void mark();
void mark(int offset);
int markindex();
byte peek();
byte peek(int index);
buffer peek(int index, int length);
int peek(int index, byte[] b, int offset, int length);
int poke(int index, buffer src);
void poke(int index, byte b);
int poke(int index, byte b[], int offset, int length);
int put(buffer src);
void put(byte b);
int put(byte[] b,int offset, int length);
int put(byte[] b);
int putindex();
int length();
void clear();
void reset();
void setgetindex(int newstart);
void setmarkindex(int newmark);
void setputindex(int newlimit);
// 一個buffer還有獨立的兩種狀态:access級别和volatile。
access級别有:immutable,表示目前buffer所有的index和内容都不能被改變;readonly,表示目前buffer是隻讀的,即getindex和markindex可以被改變,而putindex以及buffer内容不可以;readwrite,表示所有的index以及buffer的内容可以被改變。
volatile狀态表示目前buffer是否會通過其他路徑被修改,預設情況下,bytearraybuffer、directniobuffer等是non_volatile狀态,而view是volatile狀态(除非view内部的buffer是immutable)。volatile的狀态感覺不是一個比較嚴謹的概念,比如對一個view它是volatile的,但是在這種情況下,它内部包裝的buffer應該也變成volatile狀态,并且在所有的view被回收後,其内部包裝的buffer應該重新變成non_volatile狀态。要實作這種嚴謹邏輯應該是可以做的到的,隻是會比較麻煩,而且貌似也沒必要,因而jetty并沒有嘗試着去這樣做。
// 傳回包含目前buffer從getindex到putindex内容的buffer,并且傳回的buffer不可以被其他路徑修改。如果目前buffer是non_volatile,則直接傳回目前buffer(這個實作是不嚴謹的,因為在這種情況下,其實有兩個buffer執行個體可以修改同一份資料),否則,克隆一個新的buffer,這樣對新的buffer的修改不會影響原buffer的内容。
buffer asnonvolatilebuffer();
// 傳回一個隻讀的buffer(view),該隻讀的buffer的讀取不會影響原來buffer的index。
buffer asreadonlybuffer();
// 拷貝一個不可修改的bytebuffer。
buffer asimmutablebuffer();
// 傳回一個可修改的buffer,并且對傳回的buffer的内容修改會影響原有的buffer。
buffer asmutablebuffer();
// 目前buffer是否不可被修改,即buffer内容和所有index都不能被修改。
boolean isimmutable();
// 目前buffer是否是隻讀的。
boolean isreadonly();
// 是否目前buffer内容可以通過其他路徑被修改,比如view一般情況下是volatile狀态(除非view内部的buffer是immutable)。
boolean isvolatile();
// 除了以上的操作,buffer還提供了一些其他用于操作buffer内部位元組的方法:
//如果内部使用位元組數組表示,傳回該位元組數組,否則,傳回null。
byte[] array();
// 擷取從getindex到putindex的位元組數組,其長度為length。
byte[] asarray();
// 如果目前buffer是對另一個buffer的包裝,則傳回内部被包裝的buffer執行個體,否則傳回目前buffer本身。
buffer buffer();
int capacity();
// 傳回目前buffer剩餘的空間,即capacity-putindex。
int space();
// 清除buffer内容,即設定getindex和putindex為0,以及markindex為-1。
// 整理buffer内容,即将markindex >= 0 ? min(getindex, markindex) : getindex到putindex的内容移動到buffer的起始位置,同時修改相應的getindex、markindex、putindex。
void compact();
// 目前buffer是否有可用位元組,即是否putindex>getindex。
boolean hascontent();
// 跳過n個位元組,即getindex增加min(remaining(), n)的值。
int skip(int n);
// 切割出目前buffer從getindex到putindex的view,一般來說它是volatile的(除非它是immutable類型的buffer)。
buffer slice();
// 切割出目前buffer從markindex到putindex的view,一般來說它是volatile的(除非它是immutable類型的buffer)。
buffer slicefrommark();
buffer slicefrommark(int length);
// 傳回包含目前buffer狀态和内容的字元串。
string todetailstring();
boolean equalsignorecase(buffer buffer);
}
abstractbuffer:
所有buffer的基類,是對buffer接口的基本實作。
bytebuffer:
它繼承自abstractbuffer主要的非nio的buffer實作,内部使用位元組數組做緩存,直接讀inputstream和寫outputstream。
directniobuffer:
它實作了niobuffer接口,繼承自abstractbuffer,内部使用direct的bytebuffer做緩存,使用readablebytechannel和writablebytechannel分别對inputstream(readfrom傳入)和outputstream(writeto傳入)包裝,并在這兩個方法中使用包裝後的channel讀寫資料。
indirectniobuffer:
它繼承自bytebuffer,内部使用非direct的bytebuffer做緩存,并且它也直接對inputstream和outputstream讀寫。
randomaccessfilebuffer:
它繼承自abstractbuffer,内部使用randomaccessfile做緩存。
view:
它繼承自abstractbuffer,内部使用另一個buffer作為緩存,并且對非immutable的buffer,很多時候,它是volatile。view如其名,它是對内部buffer的視圖,對view内容以及index的修改會影響内部buffer中相應的值。
buffers是buffer的抽象工廠,它用于建立header的buffer和body的buffer,并且可以根據給定的size獲得相應的buffer執行個體,在buffer使用完成後,還可以通過returnbuffer方法将它歸還個buffers以複用。在建立buffers子類時,可以将指定header和body各自buffer的類型,進而在内部建立相應buffer時會建立相應類型的buffer,支援的buffer類型有:byte_array、direct、indirect。
jetty中有兩個buffers的實作:pooledbuffers和threadlocalbuffers。
pooledbuffers使用concurrentlinkedqueue建構各自的header、body、other類型的buffer池,它有一個maxsize值用于控制該buffers中包含的所有類型的buffer的總數。 threadlocalbuffers将header、body、other類型的buffer儲存在threadlocal中。
jetty還提供了buffersfactory用于建立不同類型的buffers:通過在參數中maxsize是否大于等于0以決定是使用pooledbuffers還是threadlocalbuffers。
jetty還為buffer提供了兩個特殊的類:buffercache和bufferdatecache。
buffercache
用于存儲一個可以使用存儲的string值、索引值等擷取相應的buffer執行個體,主要用于httpheaders、httpmethods等一些預定義的值。
bufferdatecache
繼承自datecache,它存儲了上一次使用一個long類型的date值格式化出的buffer執行個體,進而實作部分複用(複用在同一秒得到的request請求時建立的buffer,因為時間也隻能在這種情況下被複用,因而才會有這樣的實作),在request類中使用。