成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

實(shí)現(xiàn)簡(jiǎn)單的Tomcat | Tomcat原理學(xué)習(xí)(1)

Corwien / 1700人閱讀

摘要:項(xiàng)目結(jié)構(gòu)項(xiàng)目結(jié)構(gòu)如下實(shí)現(xiàn)細(xì)節(jié)創(chuàng)建對(duì)象首先創(chuàng)建自定義的請(qǐng)求類,其中定義與兩個(gè)屬性,表示請(qǐng)求的以及請(qǐng)求的方式。其構(gòu)造函數(shù)需要傳入一個(gè)輸入流,該輸入流通過(guò)客戶端的套接字對(duì)象得到。創(chuàng)建服務(wù)端套接字,并綁定某個(gè)端口。

緣起

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

照例附上github鏈接。


項(xiàng)目結(jié)構(gòu)

項(xiàng)目結(jié)構(gòu)如下:



實(shí)現(xiàn)細(xì)節(jié) 創(chuàng)建MyRequest對(duì)象

首先創(chuàng)建自定義的請(qǐng)求類,其中定義url與method兩個(gè)屬性,表示請(qǐng)求的url以及請(qǐng)求的方式。

其構(gòu)造函數(shù)需要傳入一個(gè)輸入流,該輸入流通過(guò)客戶端的套接字對(duì)象得到。

輸入流中的內(nèi)容為瀏覽器傳入的http請(qǐng)求頭,格式如下:

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

通過(guò)對(duì)以上內(nèi)容的分割與截取,我們可以得到該請(qǐng)求的url以及請(qǐng)求的方式。

package tomcat.dome;

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

//實(shí)現(xiàn)自己的請(qǐng)求類
public class MyRequest {
    //請(qǐng)求的url
    private String url;
    //請(qǐng)求的方法類型
    private String method;
    
    //構(gòu)造函數(shù) 傳入一個(gè)輸入流
    public MyRequest(InputStream inputStream) throws IOException {
        //用于存放http請(qǐng)求內(nèi)容的容器
        StringBuilder httpRequest=new StringBuilder();
        //用于從輸入流中讀取數(shù)據(jù)的字節(jié)數(shù)組
        byte[]httpRequestByte=new byte[1024];
        int length=0;
        //將輸入流中的內(nèi)容讀到字節(jié)數(shù)組中,并且對(duì)長(zhǎng)度進(jìn)行判斷
        if((length=inputStream.read(httpRequestByte))>0) {
            //證明輸入流中有內(nèi)容,則將字節(jié)數(shù)組添加到容器中
            httpRequest.append(new String(httpRequestByte,0,length));
        }
        //將容器中的內(nèi)容打印出來(lái)
        System.out.println("httpRequest = [ "+httpRequest+" ]");
        
        
        //從httpRequest中獲取url,method存儲(chǔ)到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;
    }
    
}



創(chuàng)建MyResponse對(duì)象

創(chuàng)建自定義的響應(yīng)類,構(gòu)造函數(shù)需要傳入由客戶端的套接字獲取的輸出流。

定義其write方法,像瀏覽器寫出一個(gè)響應(yīng)頭,并且包含我們要寫出的內(nèi)容content。

package tomcat.dome;

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

//實(shí)現(xiàn)自己的響應(yīng)類
public class MyResponse {
    //定義輸出流
    private OutputStream outputStream;
    
    //構(gòu)造函數(shù) 傳入輸出流
    public MyResponse(OutputStream outputStream) {
        this.outputStream=outputStream;
    }
    
    //創(chuàng)建寫出方法
    public void write(String content)throws IOException{
        //用來(lái)存放要寫出數(shù)據(jù)的容器
        StringBuffer stringBuffer=new StringBuffer();
        stringBuffer.append("HTTP/1.1 200 OK
")
        .append("Content-type:text/html
")
        .append("
")
        .append("Hello World")
        .append(content)
        .append("");
        
        //轉(zhuǎn)換成字節(jié)數(shù)組 并進(jìn)行寫出
        outputStream.write(stringBuffer.toString().getBytes());
        //System.out.println("sss");
        outputStream.close();
    }
    
}



創(chuàng)建MyServlet對(duì)象

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

在其中定義了兩個(gè)需要子類實(shí)現(xiàn)的抽象方法doGet和doSet。

并且創(chuàng)建了一個(gè)service方法,通過(guò)對(duì)傳入的request對(duì)象的請(qǐng)求方式進(jìn)行判斷,確定調(diào)用的是doGet方法或是doPost方法。

package tomcat.dome;

//寫一個(gè)抽象類作為servlet的父類
public abstract class MyServlet {
    //需要子類實(shí)現(xiàn)的抽象方法
    protected abstract void doGet(MyRequest request,MyResponse response);
    protected abstract void doPost(MyRequest request,MyResponse response);
    
    //父類自己的方法
    //父類的service方法對(duì)傳入的request以及response
    //的方法類型進(jìn)行判斷,由此調(diào)用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");
        }
    }
}



創(chuàng)建業(yè)務(wù)相關(guān)的Servlet

這里我創(chuàng)建了兩個(gè)業(yè)務(wù)相關(guān)類:StudentServlet和TeacherServlet。

package tomcat.dome;

import java.io.IOException;

//實(shí)現(xiàn)自己業(yè)務(wù)相關(guān)的Servlet
public class StudentServlet extends MyServlet{

    @Override
    protected void doGet(MyRequest request, MyResponse response) {
        //利用response中的輸出流 寫出內(nèi)容
        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中的輸出流 寫出內(nèi)容
        try {
            response.write("I am a student.");
        }catch(IOException e) {
            e.printStackTrace();
        }    
    }

}
package tomcat.dome;

import java.io.IOException;

//實(shí)現(xiàn)自己業(yè)務(wù)相關(guān)的Servlet
public class TeacherServlet extends MyServlet{

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

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

}



創(chuàng)建映射關(guān)系結(jié)構(gòu)ServletMapping

該結(jié)構(gòu)實(shí)現(xiàn)的是請(qǐng)求的url與具體的Servlet之間的關(guān)系映射。

package tomcat.dome;

//請(qǐng)求url與項(xiàng)目中的servlet的映射關(guān)系
public class ServletMapping {
    //servlet的名字
    private String servletName;
    //請(qǐng)求的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;
    }
}



映射關(guān)系配置對(duì)象ServletMappingConfig

配置類中定義了一個(gè)列表,里面存儲(chǔ)著項(xiàng)目中的映射關(guān)系。

package tomcat.dome;

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

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



主角登場(chǎng) MyTomcat!

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

1)初始化請(qǐng)求的映射關(guān)系。

2)創(chuàng)建服務(wù)端套接字,并綁定某個(gè)端口。

3)進(jìn)入循環(huán),用戶接受客戶端的鏈接。

4)通過(guò)客戶端套接字創(chuàng)建request與response對(duì)象。

5)根據(jù)request對(duì)象的請(qǐng)求方式調(diào)用相應(yīng)的方法。

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



測(cè)試結(jié)果

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/73638.html

相關(guān)文章

  • Tomcat】IDEA下跟蹤查看源碼

    摘要:算是心血來(lái)潮吧,想看看的源碼,順便學(xué)習(xí)一下。這里就簡(jiǎn)單的做點(diǎn)記錄如何用跟蹤查看源碼。當(dāng)然這里也提供書籍的源碼,可以下載下來(lái)對(duì)照書看。附上一張運(yùn)行成功的結(jié)果圖   算是心血來(lái)潮吧,想看看 Tomcat 的源碼,順便學(xué)習(xí)一下?! ∵@里就簡(jiǎn)單的做點(diǎn)記錄--如何用 IDEA 跟蹤查看 Tomcat 源碼。  同時(shí),這里也推薦下 how-tomcat-works 這本書,雖然書中講的是 tomc...

    edgardeng 評(píng)論0 收藏0
  • tomcat與nginx反向代理,https過(guò)程分析

    摘要:接下來(lái)我們要配置這個(gè)的端口,這樣他們才能運(yùn)行時(shí)端口號(hào)不沖突。問(wèn)題指明不同的端口號(hào)訪問(wèn)也太蠢了吧的確很蠢,所以我們要慢慢過(guò)渡學(xué)習(xí)。接下來(lái)我們學(xué)習(xí)用來(lái)進(jìn)行反向代理。阿里云的部分有一些配置的具體過(guò)程。 一、在linux上部署運(yùn)行多個(gè)tomcat 1、以前的我們 雖然說(shuō)是在linux上,但是windows上也是同樣的道理,只不過(guò)我們服務(wù)器都是選用linux罷了。 原先,自己有多個(gè)項(xiàng)目需要部署在...

    aikin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<