學完微型服務器(Tomcat)對其工作流程的理解,自己着手寫個簡單的tomcat

學完微型服務器(Tomcat)對其工作流程的理解,自己着手寫個簡單的tomcat

                                                                                                                             

 

                                                                                                                                                                                      2019-05-09   19:28:42 

 

 

注:項目(MyEclipse)創建的時候選擇:Web Service Project

第一步 對Tomcat工作流程進行分析

 

第二步 對其項目進行全局的把關

首先看看Project(FirstTomcat)的目錄結構

|-FirstTomcat

|——src

|   |-org.mrzhangxd.com

|     |-FirstRequest.java

|     |-FirstResponse.java

|     |-FirstServlet.java

|     |-FirstTomcat.java

|     |-FirstServletMapping.java

|     |_FirstServletMappingConfig.java

|   |-JRE System Library[JavaSE-x.y]

|   |-JAXB x.y.z Libraries

|   |-JavaEE x.y Generic Library

|   |-JSTL x.y.z Library

|   |-JAX-RS x.y Libraries(Project Jersey x.y)

|___|_WebRoot

第三步 代碼實現

處理請求:

    1. 創建一個request對象並填充那些有可能被所引用的Servlet使用的信息,如參數,頭部、cookies、查詢字符串等。
    2. 創建一個response對象,所引用的servlet使用它來給客戶端發送響應。
    3. 調用servlet的service方法,並傳入request和response對象。這裏servlet會從request對象取值,給response寫值。
    4. 根據servlet返回的response生成相應的HTTP響應報文。

接下來一一實現

 

請求:FirstRequest.java

 

package org.mrzhangxd.com;

import java.io.InputStream;

/**

 *

 * @author mrzhangxd

 *

 */

public class FirstRequest {

        //請求路徑

        private String url;

        //請求方法

        private String method;

        public FirstRequest(InputStream inputStream)throws Exception{

            String httpRequest = "";

            byte[] httpRequestBytes = new byte[1024];

            int length = 0;

            if((length = inputStream.read(httpRequestBytes))>0){

                httpRequest = new String(httpRequestBytes,0,length);

            }

            //HTTP請求協議:首行的內容依次爲:請求方法、請求路徑以及請求協議及其對應的版本號

            //GET    /index    /HTTP/1.1

            String httpHead = httpRequest.split("\n")[0];//取出HTTP協議的首行

            System.out.println(httpHead);

            method = httpHead.split("\\s")[0];//按照空格進行分割,第一個請求方法

           

            url = httpHead.split("\\s")[1];//按照空格進行分割,第二個是路徑

            System.out.println(this.toString());

        }

       

        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;

        }

        public String toString(){

            return "MyRequest[url = "+url+",method = "+method+"]";

           

        }

}

 

迴應:FirstResponse.java

 

package org.mrzhangxd.com;

import java.io.IOException;

import java.io.OutputStream;

/**

 *

 * @author mrzhangxd

 *

 */

public class FirstResponse {

    private  OutputStream outputStream;

    public FirstResponse(OutputStream outputStream){

        this.outputStream = outputStream;

    }

    //將文本轉換爲字節流

    public void write(String content)throws IOException{

        StringBuffer httpResponse = new StringBuffer();

        httpResponse.append("HTTP/1.1 200 OK\n")

        .append("Content-Type;text/html\n")

        .append("\r\n")

        .append("<html><link rel = \"icon\"href = \"data:;base64,=\">")

        .append(content)//將頁面內容寫入

        .append("</body></html>")

        .append("");

        outputStream.write(httpResponse.toString().getBytes());//將文本轉換爲字節碼

        outputStream.close();

    }

}

 

Servlet請求處理基類:FirstServlet.java

 

package org.mrzhangxd.com;

/**

 *

 * @author mrzhangxd

 *

 */

public abstract class FirstServlet {

    public void servlet(FirstRequest firstRequest,FirstResponse firstResponse){

        if(firstRequest.getMethod().equalsIgnoreCase("POST")){

            doPost(firstRequest,firstResponse);

        }else if(firstRequest.getMethod().equalsIgnoreCase("GET")){

            doGet(firstRequest,firstResponse);

        }

    }

    private void doGet(FirstRequest firstRequest, FirstResponse firstResponse) {

        // TODO Auto-generated method stub

    }

    private void doPost(FirstRequest firstRequest, FirstResponse firstResponse) {

        // TODO Auto-generated method stub

    }

    public void service(FirstRequest firstRequest, FirstResponse firstResponse) {

        // TODO Auto-generated method stub

    }

}

 

下一步servlet配置:FirstServletMapping.java

 

package org.mrzhangxd.com;

 

/**

 *

 * @author mrzhangxd

 *

 */

public class FirstServletMapping {

    private String servletName;

    private String url;

    private String clazz;

   

    public FirstServletMapping(String servletName, String url, String clazz) {

        super();

        this.servletName = servletName;

        this.url = url;

        this.clazz = clazz;

    }

   

    public String getServletName() {

        return servletName;

    }

   

    public void setServeletName(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;

    }

}

 

其他配置:FirstServletMappingConfig.java

 

package org.mrzhangxd.com;

import java.util.ArrayList;

import java.util.List;

/**

 *

 * @author mrzhangxd

 *

 */

public class FirstServletMappingConfig {

    public static List<FirstServletMapping> servletMappingList = new ArrayList<>();

    static {

        servletMappingList.add(new FirstServletMapping("index", "/index", "firstTomcat.test.IndexServlet"));

        servletMappingList.add(new FirstServletMapping("firstblog", "/firstblog", "firstTomcat.test.MyBlog"));

    }

}

 

核心處理類:FirstTomcat.java,處理流程如下:

1)   提供Socket服務

2)   封裝請求/響應對象

3)   將不同的請求映射到具體的Servlet處理

這裏重點說的是,要利用 ServerSocket 通過服務器上的端口通信 以及 accpt方法一直等待客戶端的請求

package org.mrzhangxd.com;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.HashMap;

import java.util.Map;

/**

 *

 * @author mrzhangxd

 *

 */

public class FirstTomcat {

    private Integer port = 8080;     //定義8080端口    

    private Map<String, String> urlServletMapping = new HashMap<>();    //存儲url和對應的類

    public FirstTomcat(Integer port) {

        super();

        this.port = port;

    } 

    @SuppressWarnings("resource")

    public void start() {

        initServletMapping();      

        try {

            ServerSocket serverSocket = null;     //實例化一個 ServerSocket 對象,表示通過服務器上的端口通信

            serverSocket = new ServerSocket(port);  

            System.out.println("MyTomcat is starting...");

            while(true) {

            Socket socket = serverSocket.accept();     //服務器調用 ServerSocket 類的 accept() 方法,該方法將一直等待,直到客戶端連接到服務器上給定的端口

            InputStream inputStream = socket.getInputStream();

            OutputStream outputStream = socket.getOutputStream(); 

            FirstRequest myRequest = new FirstRequest(inputStream);

            FirstResponse myResponse = new FirstResponse (outputStream);   

            dispatch(myRequest, myResponse);       

            socket.close();               

            }

        }catch(Exception e) {

            e.printStackTrace();

        }

    }

    //初始化映射

    public void initServletMapping() {

        for(FirstServletMapping servletMapping : FirstServletMappingConfig.servletMappingList) {

            urlServletMapping.put(servletMapping.getUrl(), servletMapping.getClazz());

        }

        }  

    //分發請求

    @SuppressWarnings("unchecked")

    public void dispatch(FirstRequest firstRequest, FirstResponse firstResponse) {

        String clazz = urlServletMapping.get(firstRequest.getUrl());        

        try {

            Class<FirstServlet> firstServletClass = (Class<FirstServlet>)Class.forName(clazz);

            FirstServlet firstservlet = firstServletClass.newInstance();

            firstservlet.service(firstRequest, firstResponse);

        }catch(ClassNotFoundException e) {

            e.printStackTrace();

        }catch(InstantiationException e) {

            e.printStackTrace();

        }catch(IllegalAccessException e) {

            e.printStackTrace();

        }

        }    

        public static void main(String[] args) {

            FirstTomcat myTomcat = new FirstTomcat(8080);

            myTomcat.start();

        }

}

 

測試類按照上面類裏的註釋自己解決,測試結果略。

 

注:

編碼格式、註釋都參考《代碼整潔之道》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章