上善若水
          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中需要一個單獨的類來專門處理HTTP響應消息和請求消息的生成和發送,Jetty的作者將該抽象(接口)命名為Generator,它有兩個實現類:HttpGenerator和NestedGenerator。其類圖如下:

          Generator接口

          HTTP請求消息分為請求行、消息報頭、請求正文三部分,HTTP響應消息分為狀態行、消息報頭、消息正文。在HTTP請求消息和響應消息格式的唯一區別是請求行和狀態行,因而只需要將這一行的內容區分開來,其他的可以共享邏輯。

          請求行和響應行設置
          請求行包括請求方法、URI、HTTP協議版本,響應行包括HTTP協議版本、狀態碼、狀態短語,因而在Generator接口中定義了各自的設置方法:

              // 設置_method、_uri字段,如果當前_version是HTTP/0.9,則_noContent置為true
              void setRequest(String method, String uri);
              // 設置_status、_reason字段,對_reason字段,將所有'\r', '\n'替換成空格(' ')。清除_method字段。如果Generator已經開始生成效應消息,則不可再調用該方法。
              void setResponse(int status, String reason);
              // 設置HTTP協議版本,這里的值9表示HTTP/0.9, 10表示HTTP/1.0,11表示HTTP/1.1。對HTTP/0.9的請求消息,不能包含請求內容。如果Generator已經開始生成效應消息,則不可再調用該方法。
              void setVersion(int version);

          HTTP消息報頭設置
          在Generator中,通過completeHeader中的HttpFields參數傳入HTTP消息報頭,而其中的allContentAdded參數用于檢查并設置_last字段狀態。
          //通過傳入的HttpFields參數設置HTTP消息報頭,allContentAdded參數用于檢查并設置_last字段狀態。
          public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
          void setDate(Buffer timeStampBuffer);
          void setSendServerVersion(boolean sendServerVersion);
          void setContentLength(long length);
          void setPersistent(boolean persistent);
          在該方法的實現中:
          1. 向_header緩存中寫入請求行或響應行(對HTTP/0.9的特殊處理不詳述)。對HTTP響應消息,如果狀態碼是[100-200)、204、304,這些響應消息不能有響應消息體。對狀態碼是100的響應消息還不能有其他消息頭。
          2. 如果設置了_date值(狀態碼在200及以上,這里貌似木有考慮請求消息),在消息頭中包含"Date"消息頭。
          3. 對fields參數中的所有消息頭,依次寫入到_header緩存中(消息頭名移除'\r', '\n', ':'字符,消息頭值移除'\r', '\n'字符)。對"Content-Length"頭,記錄_contentLength字段;對"Content-Type"為"multipart/byteranges"頭,設置_contentLength為SLEF_DEFINING_CONTENT;對"Transfer-Encoding"頭,并且_contentLength的值為CHUNKED_CONTENT,則添加"Transfer-Encoding: chunked\r\n"頭(或用戶自定義的以"chunked"開頭的值);對"Server"頭,且設置了"sendServerVersion"字段,則添加"Server"頭;對"Connection"頭,在請求消息中直接設置該頭,同時更新"keep_alive"的值("close"->keep_alive=false, "keep-alive"->keep_alive=true),在響應消息中,更新"keep_alive"和"_persistent"的值,對"upgrade"值,直接添加,而對其他值,根據"keep_alive"和"_persistent"的值以及HTTP版本號添加"close"或"keep-alive"的值,以及用戶自定義的值;根據當前_contentLength值設置"Content-Length"頭;最后添加"\r\n"到_header緩存表示消息頭結束。
          4. 將_state狀態從STATE_HEADER更新到STATE_CONTENT。

          HTTP消息體設置
          Generator中有兩個方法用于向其添加HTTP消息體:
          void addContent(Buffer content, boolean last) throws IOException;
          boolean addContent(byte b) throws IOException;
          這兩個方法的實現:
          1. 如果當前已存在未刷新的_content內容或者_contentLength為CHUNKED_CONTENT,則先刷新緩存。
          2. 更新_content字段和_contentWritten字段。
          3. 將_content的值寫入_buffer字段中。
          在刷新緩存時:
          1. 準備Buffer:將_content值寫入_buffer中,并清除_content引用;如果_contentLength為CHUNKED_CONTENT,設置_bufferChunk為true,并且對chunked內容,先寫入16進制的size,緊跟"\r\n",然后是正真的內容;對最后一個chunk,添加"\r\n\r\n"。
          2. 然后根據_header, _buffer, _content狀態,將它們中的內容寫入到Endpoint中。
          3. 如果當前狀態是STATE_FLUSHING,則將_state狀態置為STATE_END。

          HTTP消息完成生成
          Generator調用complete方法表示生成已經完成:
          public void complete() throws IOException
          在該方法中,它將_state狀態設置為STATE_FLUSHING,并刷新緩存。

          Generator中的其他方法
          在Generator/HttpGenerator中還有一些發送響應消息的方法:
          void sendError(int code, String reason, String content, boolean close) throws IOException;
          public void send1xx(int code) throws IOException
          public void sendResponse(Buffer response) throws IOException
          其中sendError是Generator接口中的方法,它是一個工具方法用于一次將一個HTTP響應消息寫入到Endpoint中:
              public void sendError(int code, String reason, String content, boolean close) throws IOException {
                  if (close)
                      _persistent=false;
                  if (!isCommitted()) {
                      setResponse(code, reason);
                      if (content != null)  {
                          completeHeader(nullfalse);
                          addContent(new View(new ByteArrayBuffer(content)), Generator.LAST);
                      } else {
                          completeHeader(nulltrue);
                      }
                      complete();
                  }
              }
          sendResponse方法是HttpGenerator中的方法,它將response參數直接作為響應消息體,并設置_state為STATE_FLUSHING,是一個工具方法。
          send1xx方法是HttpGenerator中的方法,它將1xx的響應消息直接寫入到Endpoint中。
          posted on 2014-04-20 15:58 DLevin 閱讀(1286) 評論(2)  編輯  收藏 所屬分類: Jetty

          FeedBack:
          # re: 深入Jetty源碼之HttpGenerator
          2014-04-21 10:51 | 種植技術網
          看來博主英文水平不錯的  回復  更多評論
            
          # re: 深入Jetty源碼之HttpGenerator
          2014-04-21 10:52 | 無添加
          技術博客含金量高  回復  更多評論
            
          主站蜘蛛池模板: 铜川市| 南丰县| 拜城县| 永兴县| 上犹县| 怀来县| 惠水县| 临海市| 华容县| 富宁县| 吕梁市| 铜山县| 永定县| 南平市| 桐城市| 通山县| 鲁甸县| 凤冈县| 贵德县| 玉树县| 阆中市| 平远县| 黑河市| 迭部县| 盐源县| 罗源县| 邯郸县| 南充市| 沈阳市| 清原| 和平县| 柏乡县| 田东县| 观塘区| 新源县| 鹰潭市| 谷城县| 南溪县| 东兴市| 拜城县| 夏河县|