概述
在Jetty中Buffer是對Java中Stream IO中的buffer和NIO中的buffer的抽象表示,它主要用于緩存連接中讀取和寫入的數據。在Jetty中,對每個連接使用Buffer從其InputStream中讀取字節數據,或將處理后的響應字節寫入OutputStream中,從而Jetty其他模塊在處理請求和響應數據時直接和Buffer打交道,而不需要關注底層IO流。Buffer接口定義
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);
}
// 基于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
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。
BufferCache/BufferDateCache
Jetty還為Buffer提供了兩個特殊的類:BufferCache和BufferDateCache。BufferCache
用于存儲一個可以使用存儲的String值、索引值等獲取相應的Buffer實例,主要用于HttpHeaders、HttpMethods等一些預定義的值。
BufferDateCache
繼承自DateCache,它存儲了上一次使用一個long類型的date值格式化出的Buffer實例,從而實現部分復用(復用在同一秒得到的Request請求時創建的Buffer,因為時間也只能在這種情況下被復用,因而才會有這樣的實現),在Request類中使用。