上善若水
          In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
          posts - 146,comments - 147,trackbacks - 0

          概述

          在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);
           }

          類圖


          主要實現類

          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類中使用。
          posted on 2014-03-29 13:30 DLevin 閱讀(1554) 評論(0)  編輯  收藏 所屬分類: Jetty
          主站蜘蛛池模板: 静乐县| 吴堡县| 卓尼县| 河曲县| 浮山县| 会同县| 抚顺市| 凤冈县| 称多县| 澳门| 南城县| 喀什市| 全椒县| 泸定县| 南岸区| 宝鸡市| 嘉荫县| 乡宁县| 库尔勒市| 乌拉特中旗| 布尔津县| 犍为县| 丽水市| 屯留县| 大兴区| 辰溪县| 金坛市| 平南县| 勃利县| 台前县| 景宁| 宿州市| 罗田县| 阿荣旗| 商城县| 河池市| 恩平市| 南投市| 博客| 京山县| 工布江达县|