国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

實現簡單的Tomcat | Tomcat原理學習(1)

Corwien / 1643人閱讀

摘要:項目結構項目結構如下實現細節創建對象首先創建自定義的請求類,其中定義與兩個屬性,表示請求的以及請求的方式。其構造函數需要傳入一個輸入流,該輸入流通過客戶端的套接字對象得到。創建服務端套接字,并綁定某個端口。

緣起

用了那么久tomcat,突然覺得自己對它或許并沒有想象中的那么熟悉,所以趁著放假我研究了一下這只小貓咪,實現了自己的小tomcat,寫出這篇文章同大家一起分享!

照例附上github鏈接。


項目結構

項目結構如下:



實現細節 創建MyRequest對象

首先創建自定義的請求類,其中定義url與method兩個屬性,表示請求的url以及請求的方式。

其構造函數需要傳入一個輸入流,該輸入流通過客戶端的套接字對象得到。

輸入流中的內容為瀏覽器傳入的http請求頭,格式如下:

GET /student HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: Hm_lvt_eaa22075ffedfde4dc734cdbc709273d=1549006558; _ga=GA1.1.777543965.1549006558

通過對以上內容的分割與截取,我們可以得到該請求的url以及請求的方式。

package tomcat.dome;

import java.io.IOException;
import java.io.InputStream;

//實現自己的請求類
public class MyRequest {
    //請求的url
    private String url;
    //請求的方法類型
    private String method;
    
    //構造函數 傳入一個輸入流
    public MyRequest(InputStream inputStream) throws IOException {
        //用于存放http請求內容的容器
        StringBuilder httpRequest=new StringBuilder();
        //用于從輸入流中讀取數據的字節數組
        byte[]httpRequestByte=new byte[1024];
        int length=0;
        //將輸入流中的內容讀到字節數組中,并且對長度進行判斷
        if((length=inputStream.read(httpRequestByte))>0) {
            //證明輸入流中有內容,則將字節數組添加到容器中
            httpRequest.append(new String(httpRequestByte,0,length));
        }
        //將容器中的內容打印出來
        System.out.println("httpRequest = [ "+httpRequest+" ]");
        
        
        //從httpRequest中獲取url,method存儲到myRequest中
        String httpHead=httpRequest.toString().split("
")[0];
        url=httpHead.split("s")[1];
        method=httpHead.split("s")[0];
        System.out.println("MyRequests = [ "+this+" ]");
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }
    
}



創建MyResponse對象

創建自定義的響應類,構造函數需要傳入由客戶端的套接字獲取的輸出流。

定義其write方法,像瀏覽器寫出一個響應頭,并且包含我們要寫出的內容content。

package tomcat.dome;

import java.io.IOException;
import java.io.OutputStream;

//實現自己的響應類
public class MyResponse {
    //定義輸出流
    private OutputStream outputStream;
    
    //構造函數 傳入輸出流
    public MyResponse(OutputStream outputStream) {
        this.outputStream=outputStream;
    }
    
    //創建寫出方法
    public void write(String content)throws IOException{
        //用來存放要寫出數據的容器
        StringBuffer stringBuffer=new StringBuffer();
        stringBuffer.append("HTTP/1.1 200 OK
")
        .append("Content-type:text/html
")
        .append("
")
        .append("Hello World")
        .append(content)
        .append("");
        
        //轉換成字節數組 并進行寫出
        outputStream.write(stringBuffer.toString().getBytes());
        //System.out.println("sss");
        outputStream.close();
    }
    
}



創建MyServlet對象

由于我們自己寫一個Servlet的時候需要繼承HttpServlet,因此在這里首先定義了一個抽象類——MyServlet對象。

在其中定義了兩個需要子類實現的抽象方法doGet和doSet。

并且創建了一個service方法,通過對傳入的request對象的請求方式進行判斷,確定調用的是doGet方法或是doPost方法。

package tomcat.dome;

//寫一個抽象類作為servlet的父類
public abstract class MyServlet {
    //需要子類實現的抽象方法
    protected abstract void doGet(MyRequest request,MyResponse response);
    protected abstract void doPost(MyRequest request,MyResponse response);
    
    //父類自己的方法
    //父類的service方法對傳入的request以及response
    //的方法類型進行判斷,由此調用doGet或doPost方法
    public void service(MyRequest request,MyResponse response) throws NoSuchMethodException {
        if(request.getMethod().equalsIgnoreCase("POST")) {
            doPost(request, response);
        }else if(request.getMethod().equalsIgnoreCase("GET")) {
            doGet(request, response);
        }else {
            throw new NoSuchMethodException("not support");
        }
    }
}



創建業務相關的Servlet

這里我創建了兩個業務相關類:StudentServlet和TeacherServlet。

package tomcat.dome;

import java.io.IOException;

//實現自己業務相關的Servlet
public class StudentServlet extends MyServlet{

    @Override
    protected void doGet(MyRequest request, MyResponse response) {
        //利用response中的輸出流 寫出內容
        try {
            //System.out.println("!!!!!!!!!!!!!!!!!!");
            response.write("I am a student.");
            //System.out.println("9999999999999999");
        }catch(IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(MyRequest request, MyResponse response) {
        //利用response中的輸出流 寫出內容
        try {
            response.write("I am a student.");
        }catch(IOException e) {
            e.printStackTrace();
        }    
    }

}
package tomcat.dome;

import java.io.IOException;

//實現自己業務相關的Servlet
public class TeacherServlet extends MyServlet{

    @Override
    protected void doGet(MyRequest request, MyResponse response) {
        //利用response中的輸出流 寫出內容
        try {
            response.write("I am a teacher.");
        }catch(IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(MyRequest request, MyResponse response) {
        //利用response中的輸出流 寫出內容
        try {
            response.write("I am a teacher.");
        }catch(IOException e) {
            e.printStackTrace();
        }    
    }

}



創建映射關系結構ServletMapping

該結構實現的是請求的url與具體的Servlet之間的關系映射。

package tomcat.dome;

//請求url與項目中的servlet的映射關系
public class ServletMapping {
    //servlet的名字
    private String servletName;
    //請求的url
    private String url;
    //servlet類
    private String clazz;
    public String getServletName() {
        return servletName;
    }
    public void setServletName(String servletName) {
        this.servletName = servletName;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getClazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
    public ServletMapping(String servletName, String url, String clazz) {
        super();
        this.servletName = servletName;
        this.url = url;
        this.clazz = clazz;
    }
}



映射關系配置對象ServletMappingConfig

配置類中定義了一個列表,里面存儲著項目中的映射關系。

package tomcat.dome;

import java.util.ArrayList;
import java.util.List;

//創建一個存儲有請求路徑與servlet的對應關系的 映射關系配置類
public class ServletMappingConfig {
    //使用一個list類型 里面存儲的是映射關系類Mapping
    public static ListservletMappings=new ArrayList<>(16);
    
    //向其中添加映射關系
    static {
        servletMappings.add(new ServletMapping("student","/student", "tomcat.dome.StudentServlet"));
        servletMappings.add(new ServletMapping("teacher","/teacher", "tomcat.dome.TeacherServlet"));
    }
}



主角登場 MyTomcat!

在服務端MyTomcat中主要做了如下幾件事情:

1)初始化請求的映射關系。

2)創建服務端套接字,并綁定某個端口。

3)進入循環,用戶接受客戶端的鏈接。

4)通過客戶端套接字創建request與response對象。

5)根據request對象的請求方式調用相應的方法。

6)啟動MyTomcat!

package tomcat.dome;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;


//Tomcat服務器類 編寫對請求做分發處理的相關邏輯
public class MyTomcat {
    //端口號
    private int port=8080;
    //用于存放請求路徑與對應的servlet類的請求映射關系的map
    //相應的信息從配置類中獲取
    private MapurlServletMap=new HashMap<>(16);
    //構造方法
    public MyTomcat(int port) {
        this.port=port;
    }
    
    //tomcat服務器的啟動方法
    public void start() {
        //初始化請求映射關系
        initServletMapping();
        //服務端的套接字
        ServerSocket serverSocket=null;
        try {
            //創建綁定到某個端口的服務端套接字
            serverSocket=new ServerSocket(port);
            System.out.println("MyTomcat begin start...");
            //循環 用于接收客戶端
            while(true) {
                //接收到的客戶端的套接字
                Socket socket=serverSocket.accept();
                //獲取客戶端的輸入輸出流
                InputStream inputStream=socket.getInputStream();
                OutputStream outputStream=socket.getOutputStream();
                //通過輸入輸出流創建請求與響應對象
                MyRequest request=new MyRequest(inputStream);
                MyResponse response=new MyResponse(outputStream);
                
                //根據請求對象的method分發請求 調用相應的方法
                dispatch(request, response);
                //關閉客戶端套接字
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //初始化請求映射關系,相關信息從配置類中獲取
    private void initServletMapping() {
        for(ServletMapping servletMapping:ServletMappingConfig.servletMappings) {
            urlServletMap.put(servletMapping.getUrl(), servletMapping.getClazz());
        }
    }
    
    //通過當前的request以及response對象分發請求
    private void dispatch(MyRequest request,MyResponse response) {
        //根據請求的url獲取對應的servlet類的string
        String clazz=urlServletMap.get(request.getUrl());
        //System.out.println("====="+clazz);
        try {
            //通過類的string將其轉化為對象
            Class servletClass=Class.forName("tomcat.dome.StudentServlet");
            //實例化一個對象
            MyServlet myServlet=(MyServlet)servletClass.newInstance();
            
            //調用父類方法,根據request的method對調用方法進行判斷
            //完成對myServlet中doGet與doPost方法的調用
            myServlet.service(request, response);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
    
    //main方法  直接啟動tomcat服務器
    public static void main(String[] args) {
        new MyTomcat(8080).start();
    }
    
}



測試結果

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73638.html

相關文章

  • Tomcat】IDEA下跟蹤查看源碼

    摘要:算是心血來潮吧,想看看的源碼,順便學習一下。這里就簡單的做點記錄如何用跟蹤查看源碼。當然這里也提供書籍的源碼,可以下載下來對照書看。附上一張運行成功的結果圖   算是心血來潮吧,想看看 Tomcat 的源碼,順便學習一下。  這里就簡單的做點記錄--如何用 IDEA 跟蹤查看 Tomcat 源碼?! ⊥瑫r,這里也推薦下 how-tomcat-works 這本書,雖然書中講的是 tomc...

    edgardeng 評論0 收藏0
  • tomcat與nginx反向代理,https過程分析

    摘要:接下來我們要配置這個的端口,這樣他們才能運行時端口號不沖突。問題指明不同的端口號訪問也太蠢了吧的確很蠢,所以我們要慢慢過渡學習。接下來我們學習用來進行反向代理。阿里云的部分有一些配置的具體過程。 一、在linux上部署運行多個tomcat 1、以前的我們 雖然說是在linux上,但是windows上也是同樣的道理,只不過我們服務器都是選用linux罷了。 原先,自己有多個項目需要部署在...

    aikin 評論0 收藏0

發表評論

0條評論

Corwien

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<