小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

從0手寫實現(xiàn)Tomcat

 wxt208 2019-05-24

今天我們來一步一步實現(xiàn)從0開始手寫Tomcat。

首先,我們要知道Tomcat是什么,能做什么。

Tomcat是一個Web網(wǎng)絡(luò)應(yīng)用程序,可以接收請求,并且可以處理請求。接收請求意味著必須要有一個端口,Tomcat默認(rèn)http端口是8080,請求過來后由socket網(wǎng)絡(luò)處理,請求最終需要交給線程處理,根據(jù)URL調(diào)用servlet,之后返回響應(yīng)內(nèi)容。

那么要實現(xiàn)Tomcat的功能,首先第一步我們要實現(xiàn)Socket編程。

Socket實際上做了什么呢? 

Socket調(diào)用操作系統(tǒng)的SocketAPI來實現(xiàn)網(wǎng)絡(luò)處理。所謂網(wǎng)絡(luò)編程,就是對外開放接口,讓我們的程序可以與外部建立連接。

底層Socket API函數(shù)定義

  • listen()、accept()函數(shù)只能用于服務(wù)器端;

    • listen用于網(wǎng)絡(luò)監(jiān)聽

    • accept用于獲取連接

  • connect()函數(shù)只能用于客戶端;

    • connect用于客戶端連接服務(wù)端

  • socket()、bind()、send()、recv()、sendto()、recvfrom()、close()

    • socket用于獲取套接字對象

    • bind用于綁定端口或其他信息

    • send、recv、sendto、recvfrom用于發(fā)送和接收數(shù)據(jù)

    • close用于關(guān)閉連接

了解完socket編程后,我們先來完成Socket網(wǎng)絡(luò)處理部分,如下:

private static ExecutorService threadPool = Executors.newCachedThreadPool(); public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(8080); System.out.println('tomcat 服務(wù)器啟動成功'); while (!serverSocket.isClosed()) { //獲取Socket連接 Socket request = serverSocket.accept(); threadPool.execute(() -> { try (InputStream is = request.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)) ){ System.out.println('收到請求:'); String msg = null; while ((msg = reader.readLine()) != null) { if (msg.length() == 0) { break; } System.out.println(msg); } System.out.println('---------收到請求'); } catch (IOException e) { e.printStackTrace(); } finally { try { if (request != null) { request.close(); } } catch (IOException e) { e.printStackTrace(); } } }); } if (serverSocket != null) { serverSocket.close(); }  }

完成Socket網(wǎng)絡(luò)編程,我們啟動服務(wù)后,通過telnet可以發(fā)現(xiàn)8080端口已啟動,但是我們通過瀏覽器訪問http://localhost:8080 卻發(fā)現(xiàn)瀏覽器顯示“無法訪問該頁面”。這是為什么呢?

我們的目標(biāo)是要實現(xiàn)瀏覽器和Java Web服務(wù)器Tomcat實現(xiàn)交互,那么Java Web服務(wù)器Tomcat如何與瀏覽器交互呢?

Tomcat和瀏覽器之間要交互,需要約定一個協(xié)議,這樣才能正常交互。

Http協(xié)議 --- 請求

Http協(xié)議 --- 響應(yīng)

為了實現(xiàn)Java Web服務(wù)器Tomca與瀏覽器之間能正常交互,我們需要加上一段請求響應(yīng)代碼,完整代碼如下:

  private static ExecutorService threadPool = Executors.newCachedThreadPool();    public static void main(String[] args) throws Exception {    ServerSocket serverSocket = new ServerSocket(8080);    System.out.println('tomcat 服務(wù)器啟動成功');    while (!serverSocket.isClosed()) {      //獲取Socket連接      Socket request = serverSocket.accept();      threadPool.execute(() -> {        try (InputStream is = request.getInputStream();            BufferedReader reader = new BufferedReader(new InputStreamReader(is))            ){          System.out.println('收到請求:');          String msg = null;          while ((msg = reader.readLine()) != null) {            if (msg.length() == 0) {              break;            }            System.out.println(msg);          }          System.out.println('---------收到請求');          //響應(yīng)返回結(jié)果  200          OutputStream os = request.getOutputStream();          os.write('HTTP/1.1 200 OK\r\n'.getBytes());          os.write('Content-Lenght: 11\r\n\r\n'.getBytes());          os.write('Hello World'.getBytes());          os.flush();                  } catch (IOException e) {          e.printStackTrace();        } finally {          try {            if (request != null) {              request.close();            }          } catch (IOException e) {            e.printStackTrace();          }        }      });    }    if (serverSocket != null) {      serverSocket.close();    }  }

這時候,我們啟動服務(wù)后,再通過瀏覽器去訪問http://localhost:8080/,我們會發(fā)現(xiàn)瀏覽器返回了“Hello World”。

接下來,我們要實現(xiàn)根據(jù)請求URL執(zhí)行相應(yīng)的servlet方法。

例如:“GET /servlet-demo-1.0.0/index HTTP/1.1”,我們要根據(jù)這樣一個請求去找到對應(yīng)的項目及調(diào)用相應(yīng)的servlet。

首先我們要知道有哪幾個項目,請求的項目是哪個,對應(yīng)的servlet是哪個。通過請求路徑,我們可以知道請求的項目名稱是“servlet-demo-1.0.0”,請求的servlet路徑是 /index 。我們可以根據(jù)項目名稱查找到對應(yīng)的項目,讀取項目的web.xml,從web.xml中獲取到Servlet對應(yīng)的class,也可以獲取到ServletMapping設(shè)置的路徑來做請求過濾,也可以獲取其他信息來做相應(yīng)的一些操作。

這里有一個問題,獲取到的class文件可以執(zhí)行用來調(diào)用Servlet嗎?

答案是肯定不行,了解JVM的應(yīng)該都知道,我們需要先將class文件加載到JVM,然后才能正常調(diào)用相應(yīng)的方法。

項目類資源加載

通過以下代碼,我們可以實現(xiàn)對項目類加載,獲取到Servlet實例。

//每個項目,類加載器,去加載置頂位置的class信息URL classUrl = new URL('file:' + projectPath + '\\WEB-INF\\classes\\');URLClassLoader servletClassLoader = new URLClassLoader(new URL[] {classUrl});//1、 加載到JVMClass<?> servletClass = servletClassLoader.loadClass(servletClassName);//2、 實例化Servlet servlet = (Servlet) servletClass.newInstance();

我們先來回顧一下Servlet的生命周期是怎樣的,如下所示:

在我們這個模擬例子中,我們就不實現(xiàn)init()和destory()了,我們就來調(diào)用service()方法處理客戶端請求。javax.servlet.Servlet的service()方法是有兩個參數(shù)的

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

我們在應(yīng)用開發(fā)中常用的HttpServletRequest和HttpServletResponse,實際上是我們的Java Web服務(wù)器已經(jīng)幫我們實現(xiàn)了,這里我們也需要來實現(xiàn)我們的HttpServletRequest和HttpServletResponse,然后在調(diào)用service()方法就可以了。到這里,我們簡易版的Web服務(wù)器就算成功了。

代碼地址:https://github.com/biaotang/demo-tomcat

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多