日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《深入剖析Tomcat》阅读(三)

發布時間:2023/12/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《深入剖析Tomcat》阅读(三) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?這里要介紹下Tomcat的一個重要設計方法,Catalina設計方式。

Servlet容器是一個復雜系統,但是,它有三個基本任務,對每個請求,servlet容器會為其完成以下三個操作:

1.創建一個Request對象,用可能會在調用的Servlet中使用到的信息填充該request對象,如參數、頭、cookie、查詢字符串、URI等。

? request對象是javax.servlet.ServletRequest接口或javax.servlet.http.ServletRequest接口的一個實例。

2.創建一個調用Servlet的response對象,用來向Web客戶端發送響應。response對象是javax.servlet.ServletResponse接口或javax.servlet.http.ServletResponse接口的一個實例。

3.調用Servlet的service()方法,將request對象和response對象作為參數傳入。Servlet從request對象中讀取信息,并通過response對象發送響應信息。

?-----------------------------------------------------------------------------------------------------

Catalina是一個成熟的軟件,設計和開發得十分優雅。(其實我在公司項目中發現的使用方法也是這樣的,十分的優雅的軟件開發方式)

Catalina使得軟件開發功能結構編程模塊化的,基于上文提到的servlet容器的任務,可以將Catalina劃分為兩個模塊:連接器(connector)和容器(container)

連接器負責將一個請求與容器相關聯。它的工作包括為它接收到的每一個HTTP請求創建一個Request對象和一個Response對象。然后,它將處理過程交給容器。容器從連接器中接收到Request對象和Response對象,并負責調用相應的Servlet的service()方法。

?

?

簡而言這模式就是connector負責接收請求,創建解析請求需要的Request對象和Response對象,然后將請求分發到容器中處理。

(普通的服務端結構一般也是這么設計的,IO部分負責接收請求,創建解析請求的對象,然后將請求丟進線程池中進行處理)

xxxx

--------------------------------------------

?

現在根據模塊開發Servlet容器:

1)連接器 ? HttpConnector和HttpProcessor 連接器及其支持類 標示HTTP請求的類(HTTPRequest)及其支持類 負責HTTP響應的類,HttpResponse以及其支持類,外觀類以及常量類

2)啟動模塊 ?啟動模塊包括一個類,就是startup.Bootstrap 類,負責啟動應用程序。

3)核心模塊

啟動類

package ex03.pyrmont.startup;import ex03.pyrmont.connector.http.HttpConnector;public final class Bootstrap {public static void main(String[] args){HttpConnector connector = new HttpConnector();connector.start();} }

?

關于這個建議具有連接器和容器功能的Http服務器

http://www.cnblogs.com/wuxinliulei/p/4967625.html

?

?

?

---------------------------------------------------------------------------

重點介紹這個模型當中對HTTP請求信息的parse

HttpConnector類在接收到連接請求后,將請求派發給一個HttpProcessor對象處理

import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket;public class HttpConnector implements Runnable {boolean stopped;private String scheme = "http";public String getScheme(){return scheme;}public void run(){ServerSocket serverSocket = null;int port = 8080;try{serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));} catch (IOException e){e.printStackTrace();System.exit(1);}while (!stopped){// Accept the next incoming connection from the server socketSocket socket = null;try{socket = serverSocket.accept();} catch (Exception e){continue;}// Hand this socket off to an HttpProcessorHttpProcessor processor = new HttpProcessor(this);processor.process(socket);}}public void start(){Thread thread = new Thread(this);thread.start();} }

將此次連接獲取的Socket對象傳入,調用HttpProcessor對象的process方法來處理Http請求

下面是HttpProcessor對象的process方法,重點關注SocketInputStream對象,SocketInputStream對象是對InputStream對象的一層包裝,封裝了一些對Http請求解析方便的方法。 ??

public void process(Socket socket){SocketInputStream input = null;OutputStream output = null;try{input = new SocketInputStream(socket.getInputStream(), 2048);output = socket.getOutputStream();// create HttpRequest object and parserequest = new HttpRequest(input);// create HttpResponse objectresponse = new HttpResponse(output);response.setRequest(request);response.setHeader("Server", "Pyrmont Servlet Container");parseRequest(input, output);parseHeaders(input);// check if this is a request for a servlet or a static resource// a request for a servlet begins with "/servlet/"if (request.getRequestURI().startsWith("/servlet/")){ServletProcessor processor = new ServletProcessor();processor.process(request, response);} else{StaticResourceProcessor processor = new StaticResourceProcessor();processor.process(request, response);}// Close the socketsocket.close();// no shutdown for this application} catch (Exception e){e.printStackTrace();}}

?

process方法當中調用了parseRequest方法,該方法傳入SocketInputStream對象和OutputStream對象,方法對輸入流當中的http請求進行了解析,

這里牽涉到幾個幫助類?

1:HttpRequestLine類,定義在HttpProcessor方法的成員變量當中。private HttpRequestLine requestLine = new HttpRequestLine();?

該類中對http請求內容中的請求行(http請求依次分為請求行、請求頭、/r/n,請求體四部分),第一行內容進行了解析 即

POST /servlet/primitServlet Http/1.1 ? ?GET ?/sample/hello.jsp ? HTTP/1.1 這樣的內容

HttpRequestLine類是一個可以復用的類(PS:但是HttpProcessor在這個框架當中沒有對象池的復用,所以沒有卵用),對httpMethod ? httpUrl ?protocol 三部分做了處理。其中還提供了字符串匹配的方法indexOf(char[] xxx) indexOf(String xxx)

/*** HTTP request line enum type.*/final class HttpRequestLine {// -------------------------------------------------------------- Constantspublic static final int INITIAL_METHOD_SIZE = 8;public static final int INITIAL_URI_SIZE = 64;public static final int INITIAL_PROTOCOL_SIZE = 8;public static final int MAX_METHOD_SIZE = 1024;public static final int MAX_URI_SIZE = 32768;public static final int MAX_PROTOCOL_SIZE = 1024;// ----------------------------------------------------------- Constructorspublic HttpRequestLine(){this(new char[INITIAL_METHOD_SIZE], 0, new char[INITIAL_URI_SIZE], 0, new char[INITIAL_PROTOCOL_SIZE], 0);}public HttpRequestLine(char[] method, int methodEnd, char[] uri, int uriEnd, char[] protocol, int protocolEnd){this.method = method;this.methodEnd = methodEnd;this.uri = uri;this.uriEnd = uriEnd;this.protocol = protocol;this.protocolEnd = protocolEnd;}// ----------------------------------------------------- Instance Variablespublic char[] method;public int methodEnd;public char[] uri;public int uriEnd;public char[] protocol;public int protocolEnd;// ------------------------------------------------------------- Properties// --------------------------------------------------------- Public Methods/*** Release all object references, and initialize instance variables, in* preparation for reuse of this object.*/public void recycle(){methodEnd = 0;uriEnd = 0;protocolEnd = 0;}/*** Test if the uri includes the given char array.*/public int indexOf(char[] buf){return indexOf(buf, buf.length);}/*** Test if the value of the header includes the given char array.*/public int indexOf(char[] buf, int end){char firstChar = buf[0];int pos = 0;while (pos < uriEnd){pos = indexOf(firstChar, pos);if (pos == -1)return -1;if ((uriEnd - pos) < end)return -1;for (int i = 0; i < end; i++){if (uri[i + pos] != buf[i])break;if (i == (end - 1))return pos;}pos++;}return -1;}/*** Test if the value of the header includes the given string.*/public int indexOf(String str){return indexOf(str.toCharArray(), str.length());}/*** Returns the index of a character in the value.*/public int indexOf(char c, int start){for (int i = start; i < uriEnd; i++){if (uri[i] == c)return i;}return -1;}// --------------------------------------------------------- Object Methodspublic int hashCode(){// FIXMEreturn 0;}public boolean equals(Object obj){return false;}}

  

我們要注意到parseRequest方法的第一行代碼 input.readRequestLine(requestLine) SocketInputStream的該方法完成了對HttpRequestLine對象的初始化,主要初始化了六個對象

public char[] method; ?//method對象
public int methodEnd; //method對象的結束位置
public char[] uri; ? ? ? ? //uri對象
public int uriEnd; ? ? ? ?//uri對象的結束位置
public char[] protocol; //協議對象
public int protocolEnd;//協議對象的結束位置

注意read方法完成了對count的初始化,并且將第一行內容緩存到char[] buf當中

/*** Read byte.*/public int read() throws IOException{if (pos >= count){fill();if (pos >= count)return -1;}return buf[pos++] & 0xff;} /*** Fill the internal buffer using data from the undelying input stream.*/protected void fill() throws IOException{pos = 0;count = 0;int nRead = is.read(buf, 0, buf.length);if (nRead > 0){count = nRead;}}

  

public void readRequestLine(HttpRequestLine requestLine) throws IOException{// Recycling checkif (requestLine.methodEnd != 0)requestLine.recycle();// Checking for a blank lineint chr = 0;do{ // Skipping CR or LFtry{chr = read();} catch (IOException e){chr = -1;}} while ((chr == CR) || (chr == LF));if (chr == -1)throw new EOFException(sm.getString("requestStream.readline.error"));pos--;// Reading the method nameint maxRead = requestLine.method.length;int readStart = pos;int readCount = 0;boolean space = false;while (!space){// if the buffer is full, extend itif (readCount >= maxRead){if ((2 * maxRead) <= HttpRequestLine.MAX_METHOD_SIZE){char[] newBuffer = new char[2 * maxRead];System.arraycopy(requestLine.method, 0, newBuffer, 0, maxRead);requestLine.method = newBuffer;maxRead = requestLine.method.length;} else{throw new IOException(sm.getString("requestStream.readline.toolong"));}}// We're at the end of the internal bufferif (pos >= count){int val = read();if (val == -1){throw new IOException(sm.getString("requestStream.readline.error"));}pos = 0;readStart = 0;}if (buf[pos] == SP){space = true;}requestLine.method[readCount] = (char) buf[pos];readCount++;pos++;}requestLine.methodEnd = readCount - 1;// Reading URImaxRead = requestLine.uri.length;readStart = pos;readCount = 0;space = false;boolean eol = false;while (!space){// if the buffer is full, extend itif (readCount >= maxRead){if ((2 * maxRead) <= HttpRequestLine.MAX_URI_SIZE){char[] newBuffer = new char[2 * maxRead];System.arraycopy(requestLine.uri, 0, newBuffer, 0, maxRead);requestLine.uri = newBuffer;maxRead = requestLine.uri.length;} else{throw new IOException(sm.getString("requestStream.readline.toolong"));}}// We're at the end of the internal bufferif (pos >= count){int val = read();if (val == -1)throw new IOException(sm.getString("requestStream.readline.error"));pos = 0;readStart = 0;}if (buf[pos] == SP){space = true;} else if ((buf[pos] == CR) || (buf[pos] == LF)){// HTTP/0.9 style requesteol = true;space = true;}requestLine.uri[readCount] = (char) buf[pos];readCount++;pos++;}//請求航URL結束requestLine.uriEnd = readCount - 1;// Reading protocolmaxRead = requestLine.protocol.length;readStart = pos;readCount = 0;while (!eol){// if the buffer is full, extend itif (readCount >= maxRead){if ((2 * maxRead) <= HttpRequestLine.MAX_PROTOCOL_SIZE){char[] newBuffer = new char[2 * maxRead];System.arraycopy(requestLine.protocol, 0, newBuffer, 0, maxRead);requestLine.protocol = newBuffer;maxRead = requestLine.protocol.length;} else{throw new IOException(sm.getString("requestStream.readline.toolong"));}}// We're at the end of the internal bufferif (pos >= count){// Copying part (or all) of the internal buffer to the line// bufferint val = read();if (val == -1)throw new IOException(sm.getString("requestStream.readline.error"));pos = 0;readStart = 0;}if (buf[pos] == CR){// Skip CR.} else if (buf[pos] == LF){eol = true;} else{requestLine.protocol[readCount] = (char) buf[pos];readCount++;}pos++;}// HTTP/1.1requestLine.protocolEnd = readCount;}

  

?

private void parseRequest(SocketInputStream input, OutputStream output) throws IOException, ServletException{// Parse the incoming request lineinput.readRequestLine(requestLine);String method = new String(requestLine.method, 0, requestLine.methodEnd);String uri = null;String protocol = new String(requestLine.protocol, 0, requestLine.protocolEnd);// Validate the incoming request lineif (method.length() < 1){throw new ServletException("Missing HTTP request method");} else if (requestLine.uriEnd < 1){throw new ServletException("Missing HTTP request URI");}// Parse any query parameters out of the request URIint question = requestLine.indexOf("?");if (question >= 0){request.setQueryString(new String(requestLine.uri, question + 1, requestLine.uriEnd - question - 1));uri = new String(requestLine.uri, 0, question);} else{request.setQueryString(null);uri = new String(requestLine.uri, 0, requestLine.uriEnd);}// Checking for an absolute URI (with the HTTP protocol)if (!uri.startsWith("/")){int pos = uri.indexOf("://");// Parsing out protocol and host nameif (pos != -1){pos = uri.indexOf('/', pos + 3);if (pos == -1){uri = "";} else{uri = uri.substring(pos);}}}// Parse any requested session ID out of the request URIString match = ";jsessionid=";int semicolon = uri.indexOf(match);if (semicolon >= 0){String rest = uri.substring(semicolon + match.length());int semicolon2 = rest.indexOf(';');if (semicolon2 >= 0){request.setRequestedSessionId(rest.substring(0, semicolon2));rest = rest.substring(semicolon2);} else{request.setRequestedSessionId(rest);rest = "";}request.setRequestedSessionURL(true);uri = uri.substring(0, semicolon) + rest;} else{request.setRequestedSessionId(null);request.setRequestedSessionURL(false);}// Normalize URI (using String operations at the moment)String normalizedUri = normalize(uri);// Set the corresponding request properties((HttpRequest) request).setMethod(method);request.setProtocol(protocol);if (normalizedUri != null){((HttpRequest) request).setRequestURI(normalizedUri);} else{((HttpRequest) request).setRequestURI(uri);}if (normalizedUri == null){throw new ServletException("Invalid URI: " + uri + "'");}}

  

?----------------------------------------------------------------------------------------------------------------------------------------

為什么采用連接器的第三章的代碼沒有采用第二章的簡單形式直接將相關內容解析出來呢?

?

private String parseUri(String requestString){int index1, index2;index1 = requestString.indexOf(' ');if (index1 != -1){index2 = requestString.indexOf(' ', index1 + 1);if (index2 > index1)return requestString.substring(index1 + 1, index2);}return null;} public void parse() {// Read a set of characters from the socketStringBuffer request = new StringBuffer(2048);int i;byte[] buffer = new byte[2048];try{i = input.read(buffer);} catch (IOException e){e.printStackTrace();i = -1;}for (int j = 0; j < i; j++){request.append((char) buffer[j]);}System.out.print(request.toString());uri = parseUri(request.toString()); }

?

其實上面的處理方式是不嚴謹的,應該讀到/r/n之后停止,而不是固定讀取2048字節,然后處理這讀出來的字節。

?

轉載于:https://www.cnblogs.com/wuxinliulei/p/4960670.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的《深入剖析Tomcat》阅读(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品一二三级 | 成人免费看视频 | 国产一级做a爰片久久毛片男 | 国产超碰人人 | 精品美女一区 | 一级黄色大片在线观看 | www.色黄 | 毛片在线观看视频 | 成人国产三级 | 中文字幕在线第一页 | 欧美一区二区三区不卡视频 | www三级免费 | 快色在线观看 | 国产又粗又长又爽 | 国产高清免费观看 | 九九热精品在线视频 | 精品无人国产偷自产在线 | 黄色片地址 | 激情影音 | 欧美午夜在线 | 91丝袜在线观看 | 色噜噜狠狠狠综合曰曰曰88av | 9l视频自拍蝌蚪9l视频 | 日韩美女av在线 | 人人草网站 | 欧美成人一区在线 | 国产精品永久 | 国产吃瓜黑料一区二区 | 精品少妇人妻一区二区黑料社区 | 欧美激情亚洲色图 | 美女让男生桶 | 99ri在线| 免费激情网 | 91色爱 | 国产在线视频一区二区 | 九九黄色片 | 少妇媚药按摩中文字幕 | 久久久成人精品一区二区三区 | 精品777| 97在线免费视频观看 | 免费观看美女裸体网站 | 日韩精品中文字幕在线 | 中文字幕av专区 | 欧美三日本三级少妇三99 | 亚洲一级片在线播放 | 香港日本韩国三级网站 | av动漫免费看 | 国产精品毛片久久久久久 | 中文字幕永久在线播放 | 超碰综合在线 | 色一五月| 波多野结衣福利视频 | 中文字幕成人在线 | 欧美国产激情 | 午夜影视在线观看 | 欧美成人免费网站 | 韩国美女视频在线观看18 | 一级女性全黄久久生活片免费 | 都市豪门艳霸淫美妇 | 怡红院一区二区三区 | 99视屏| 精品国产一区二区三区久久久蜜月 | 免费av毛片| 一级片免费看视频 | 欧美视频在线观看一区二区 | 午夜免费观看视频 | 国产99视频在线观看 | 日韩五码| 国产精品一区二区三区四区在线观看 | 久久狠狠婷婷 | 中文字幕在线看高清电影 | 国产高清视频在线免费观看 | 久久机热 | 国产精品精| 97香蕉久久超级碰碰高清版 | 永久免费毛片 | 91久久电影 | 不卡一区二区在线观看 | 蜜桃精品噜噜噜成人av | 老熟妇高潮一区二区三区 | 黄色大片一级片 | se94se欧美 | 强公把我次次高潮hd | av免费在线网站 | 久久久久色 | 国精品无码一区二区三区 | 手机在线看永久av片免费 | 亚洲av乱码一区二区 | 色婷婷av一区 | 久久亚洲精品国产 | 三级五月天 | 精品黑人一区二区三区国语馆 | 精品无码国产污污污免费网站 | 婷婷综合在线视频 | 精品无码久久久久久久久果冻 | 嫩草视屏 | 五月天丁香视频 | 18成人免费观看视频 | 成年丰满熟妇午夜免费视频 |