概述
在Jetty中Buffer是對Java中Stream IO中的buffer和NIO中的buffer的抽象表示,它主要用于緩存連接中讀取和寫入的數(shù)據(jù)。在Jetty中,對每個連接使用Buffer從其InputStream中讀取字節(jié)數(shù)據(jù),或?qū)⑻幚砗蟮捻憫止?jié)寫入OutputStream中,從而Jetty其他模塊在處理請求和響應數(shù)據(jù)時直接和Buffer打交道,而不需要關注底層IO流。
Buffer接口定義
Jetty中Buffer接口定義如下:
public interface Buffer extends Cloneable {
// 基于Buffer主要用于向當前連接讀寫數(shù)據(jù),因而它定義了兩個核心的方法:readFrom和writeTo。其中readFrom方法從InputStream中讀取字節(jié)數(shù)據(jù),writeTo方法將響應字節(jié)寫入OutputStream中,即向Connection中讀取和寫入數(shù)據(jù),寫完后清理當前Buffer。
int readFrom(InputStream in, int max) throws IOException;
void writeTo(OutputStream out) throws IOException;
// 在Buffer從InputStream(Connection)中讀取數(shù)據(jù)后,Buffer接口還提供了很多不同的方法用于從Buffer中讀取或?qū)懭胱止?jié)數(shù)據(jù)。
// Jetty中的Buffer是一個FIFO的字節(jié)隊列,它的設計類似NIO中Buffer的設計:每次get操作都從getIndex開始,并且getIndex會向前移動讀取的字節(jié)數(shù)的長度;每次的peek操作也getIndex開始,但是peek操作不會使getIndex向前移動;每次put操作都從putIndex開始,并且putIndex會向前移動寫入的字節(jié)數(shù)的長度;每次poke操作也會從putIndex開始,但是poke操作不會使putIndex向前移動;mark操作會以getIndex作為基準設置markIndex的值,從而在reset時會將getIndex重置到之前mark過的位置;capacity表示該Buffer最多可存儲的字節(jié)數(shù),而length表示從getIndex到putIndex還存在的字節(jié)數(shù)。并且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還有獨立的兩種狀態(tài):access級別和volatile。
access級別有:IMMUTABLE,表示當前Buffer所有的Index和內(nèi)容都不能被改變;READONLY,表示當前Buffer是只讀的,即getIndex和markIndex可以被改變,而putIndex以及Buffer內(nèi)容不可以;READWRITE,表示所有的Index以及Buffer的內(nèi)容可以被改變。
volatile狀態(tài)表示當前Buffer是否會通過其他路徑被修改,默認情況下,ByteArrayBuffer、DirectNIOBuffer等是NON_VOLATILE狀態(tài),而View是VOLATILE狀態(tài)(除非View內(nèi)部的Buffer是IMMUTABLE)。VOLATILE的狀態(tài)感覺不是一個比較嚴謹?shù)母拍睿热鐚σ粋€View它是VOLATILE的,但是在這種情況下,它內(nèi)部包裝的Buffer應該也變成VOLATILE狀態(tài),并且在所有的View被回收后,其內(nèi)部包裝的Buffer應該重新變成NON_VOLATILE狀態(tài)。要實現(xiàn)這種嚴謹邏輯應該是可以做的到的,只是會比較麻煩,而且貌似也沒必要,因而Jetty并沒有嘗試著去這樣做。
// 返回包含當前Buffer從getIndex到putIndex內(nèi)容的Buffer,并且返回的Buffer不可以被其他路徑修改。如果當前Buffer是NON_VOLATILE,則直接返回當前Buffer(這個實現(xiàn)是不嚴謹?shù)模驗樵谶@種情況下,其實有兩個Buffer實例可以修改同一份數(shù)據(jù)),否則,克隆一個新的Buffer,這樣對新的Buffer的修改不會影響原Buffer的內(nèi)容。
Buffer asNonVolatileBuffer();
// 返回一個只讀的Buffer(View),該只讀的Buffer的讀取不會影響原來Buffer的Index。
Buffer asReadOnlyBuffer();
// 拷貝一個不可修改的ByteBuffer。
Buffer asImmutableBuffer();
// 返回一個可修改的Buffer,并且對返回的Buffer的內(nèi)容修改會影響原有的Buffer。
Buffer asMutableBuffer();
// 當前Buffer是否不可被修改,即Buffer內(nèi)容和所有Index都不能被修改。
boolean isImmutable();
// 當前Buffer是否是只讀的。
boolean isReadOnly();
// 是否當前Buffer內(nèi)容可以通過其他路徑被修改,比如View一般情況下是VOLATILE狀態(tài)(除非View內(nèi)部的Buffer是IMMUTABLE)。
boolean isVolatile();
// 除了以上的操作,Buffer還提供了一些其他用于操作Buffer內(nèi)部字節(jié)的方法:
//如果內(nèi)部使用字節(jié)數(shù)組表示,返回該字節(jié)數(shù)組,否則,返回null。
byte[] array();
// 獲取從getIndex到putIndex的字節(jié)數(shù)組,其長度為length。
byte[] asArray();
// 如果當前Buffer是對另一個Buffer的包裝,則返回內(nèi)部被包裝的Buffer實例,否則返回當前Buffer本身。
Buffer buffer();
int capacity();
// 返回當前Buffer剩余的空間,即capacity-putIndex。
int space();
// 清除Buffer內(nèi)容,即設置getIndex和putIndex為0,以及markIndex為-1。
// 整理Buffer內(nèi)容,即將markIndex >= 0 ? min(getIndex, markIndex) : getIndex到putIndex的內(nèi)容移動到Buffer的起始位置,同時修改相應的getIndex、markIndex、putIndex。
void compact();
// 當前Buffer是否有可用字節(jié),即是否putIndex>getIndex。
boolean hasContent();
// 跳過n個字節(jié),即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狀態(tài)和內(nèi)容的字符串。
String toDetailString();
boolean equalsIgnoreCase(Buffer buffer);
}
類圖
主要實現(xiàn)類
AbstractBuffer:
所有Buffer的基類,是對Buffer接口的基本實現(xiàn)。
ByteBuffer:
它繼承自AbstractBuffer主要的非NIO的Buffer實現(xiàn),內(nèi)部使用字節(jié)數(shù)組做緩存,直接讀InputStream和寫OutputStream。
DirectNIOBuffer:
它實現(xiàn)了NIOBuffer接口,繼承自AbstractBuffer,內(nèi)部使用Direct的ByteBuffer做緩存,使用ReadableByteChannel和WritableByteChannel分別對InputStream(readFrom傳入)和OutputStream(writeTo傳入)包裝,并在這兩個方法中使用包裝后的Channel讀寫數(shù)據(jù)。
IndirectNIOBuffer:
它繼承自ByteBuffer,內(nèi)部使用非direct的ByteBuffer做緩存,并且它也直接對InputStream和OutputStream讀寫。
RandomAccessFileBuffer:
它繼承自AbstractBuffer,內(nèi)部使用RandomAccessFile做緩存。
View:
它繼承自AbstractBuffer,內(nèi)部使用另一個Buffer作為緩存,并且對非IMMUTABLE的Buffer,很多時候,它是VOLATILE。View如其名,它是對內(nèi)部Buffer的視圖,對View內(nèi)容以及Index的修改會影響內(nèi)部Buffer中相應的值。
Buffers
Buffers是Buffer的抽象工廠,它用于創(chuàng)建Header的Buffer和Body的Buffer,并且可以根據(jù)給定的size獲得相應的Buffer實例,在Buffer使用完成后,還可以通過returnBuffer方法將它歸還個Buffers以復用。在創(chuàng)建Buffers子類時,可以將指定Header和Body各自Buffer的類型,從而在內(nèi)部創(chuàng)建相應Buffer時會創(chuàng)建相應類型的Buffer,支持的Buffer類型有:BYTE_ARRAY、DIRECT、INDIRECT。
Jetty中有兩個Buffers的實現(xiàn):PooledBuffers和ThreadLocalBuffers。
PooledBuffers使用ConcurrentLinkedQueue構建各自的Header、Body、Other類型的Buffer池,它有一個maxSize值用于控制該Buffers中包含的所有類型的Buffer的總數(shù)。
ThreadLocalBuffers將Header、Body、Other類型的Buffer保存在ThreadLocal中。
Jetty還提供了
BuffersFactory用于創(chuàng)建不同類型的Buffers:通過在參數(shù)中maxSize是否大于等于0以決定是使用PooledBuffers還是ThreadLocalBuffers。
BufferCache/BufferDateCache
Jetty還為Buffer提供了兩個特殊的類:BufferCache和BufferDateCache。
BufferCache
用于存儲一個可以使用存儲的String值、索引值等獲取相應的Buffer實例,主要用于HttpHeaders、HttpMethods等一些預定義的值。
BufferDateCache
繼承自DateCache,它存儲了上一次使用一個long類型的date值格式化出的Buffer實例,從而實現(xiàn)部分復用(復用在同一秒得到的Request請求時創(chuàng)建的Buffer,因為時間也只能在這種情況下被復用,因而才會有這樣的實現(xiàn)),在Request類中使用。
posted on 2014-03-29 13:30
DLevin 閱讀(1551)
評論(0) 編輯 收藏 所屬分類:
Jetty