Simple Tomcat source code implementation

Simple Tomcat source code implementation

Source Download Link] ( https://download.csdn.net/download/yang134679/11092413 )

Let's look at a piece of code

package com.ys.tomcat.test;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class MyTomcatPre {
    public static void main(String[] args) throws Exception{
        //定义服务端的端口号
        ServerSocket serverSocket = new ServerSocket(9999);
        //TomCat启动
        System.out.println("TomCat已经启动");
        //永无休止的接收服务
        while(true){
            //建立一个socket请求,一旦有客户端连上了进行接收
            Socket socket = serverSocket.accept();
            //获取输入流
            InputStream inputStream = socket.getInputStream();
            //缓冲
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
            //将接收到的信息打印到控制台
            String msg = null;
            while ((msg = bufferedReader.readLine()) != null){
                if (msg.length() == 0){
                    break;
                }
                System.out.println(msg);
            }
        }
    }
}

This is a service we set ServerSocket, port number, 9999, when the corresponding browser http request to issue a request, it will print out the console.
We start the test class
Here Insert Picture Description
launched in browser requests
Here Insert Picture Description
the following results
Here Insert Picture Description
Once you have a basic knowledge of the server, a simple source implementation of
the project the main structure

Here Insert Picture Description

When receiving the request to start tomcat we need to process the request, the servlet doget before we use methods and dopost request, where we achieved a reduction of
the main class (MyTomcat) Source

package com.ys.tomcat;

import com.ys.tomcat.servlet.HttpServlet;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;

public class MyTomcat {
    //使用HashMap存储,初始化servlet信息
    public static final HashMap<String,HttpServlet> servletMapping = new HashMap<>();
    public static void main(String[] args) throws  Exception{
    //第一步,初始化servlet
        //资源路径
        String basePath;
        //获取basePath
        basePath = MyTomcat.class.getResource("/").getPath();
        //1.获取解析器
        SAXReader reader = new SAXReader();
        //2。获取document文档对象
        Document document = reader.read(new File(basePath + "web.xml"));
        //3.获取根元素
        Element root = document.getRootElement();
        //4.获取根元素下的子元素
        List<Element> childElements = root.elements();
        //5.遍历子元素
        for (Element element: childElements) {
            //6.判断元素名称为servlet的元素
            if("servlet".equals(element.getName())){
                //7.获取servlet—name元素
                Element servletName = element.element("servlet-name");
                //8.获取servlet-class元素
                Element servletClass = element.element("servlet-class");
                //检测输出
                System.out.println(servletName.getText()+"\t"+servletClass.getText());
                //9.将web.xml中的servlet-name和servlet-class值进行存储
                servletMapping.put(servletName.getText(),
                        (HttpServlet)Class.forName(servletClass.getText()).newInstance());
            }
        }
    //第二阶段--暴露接口,处理请求
        //定义服务端的端口号
        ServerSocket serverSocket = new ServerSocket(8080);
        //TomCat启动
        System.out.println("TomCat已经启动");
        //永无休止的接收服务
        while(true){
            //建立一个socket请求,一旦有客户端连上了进行接收
            Socket socket = serverSocket.accept();
            //接收一个开启一个线程
            Thread thread = new ServletThread(socket);
            //开启线程
            thread.start();
        }
    }
}

First, we use the jar package dom4j web.xml file is parsed to ensure servlet service first started in the main method
web.xml source

<?xml version="1.0" encoding="utf-8"?>

<web-app xmlns="http://www.example.org/web-app_2_5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
                version="2.5">
    <servlet>
        <servlet-name>mytomcat</servlet-name>
        <servlet-class>com.ys.tomcat.servlet.MyServlet</servlet-class>
    </servlet>
</web-app>

But we must first package Request a class that we used to obtain information request url header information request method of requesting and

package com.ys.tomcat.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

/**
 * http请求封装类
 */
public class Request {
    //请求类型  get/post
    private String method;
    //请求资源路径 url
    private String url;

    public Request(InputStream inputStream) throws IOException{
        //缓冲,转码
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
        //创建一个String数组保存请求头信息,先读取一行信息,然后按照“ ”切割
        String[] input = reader.readLine().split(" ");
        //数组第一个是请求方法
        this.method = input[0];
        //数组的第二位是url
        this.url = input[1];


    }

    public String getMethod() {
        return method;
    }

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

    public String getUrl() {
        return url;
    }

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

We also need to do in response to the data package for Response
Response Source

package com.ys.tomcat.http;

import java.io.OutputStream;

/**
 * 请求封装类
 */
public class Response {
    //response是输出响应,用输出流
    public OutputStream outputStream;
    //状态行
    //Http版本,状态码,状态信息
    //响应报文头部
    //用于说明服务器要使用的附加资源
    //空行
    //请求头和主体数据间必须有换行
    public static String responseHeader = "Http/1.1 200 \r\n"
                                        +"Content-Type:text/html \r\n"
                                        +"\r\n";

    public Response(OutputStream outputStream) {
        this.outputStream = outputStream;
    }
}

After reading to the servlet configuration, we restore the servlet
SuperServlet source

package com.ys.tomcat.servlet;

import com.ys.tomcat.http.Request;
import com.ys.tomcat.http.Response;

import java.io.IOException;

public interface SuperServlet {
	//初始化方法
	void init();
	//service方法
	void service(Request request, Response response) throws IOException;
	//销毁方法
	void destroy();
}

HttpServlet Code (formerly the jdk modeled HttpServlet), method call service is determined, and then call a specific implementation class

package com.ys.tomcat.servlet;

import com.ys.tomcat.http.Request;
import com.ys.tomcat.http.Response;

import java.io.IOException;



public abstract class HttpServlet implements SuperServlet{
	//初始化方法
	@Override
	public void init() {
		
	}
	//销毁方法
	@Override
	public void destroy() {
		
	}
	//核心业务方法
	@Override
	public void service(Request request, Response response) throws IOException {
		//判断是否哪种请求方法get/post
		if("get".equalsIgnoreCase(request.getMethod())){
			doGet(request,response);
		}else{
			doPost(request,response);
		}
	}
	//等待实例类调用
	public abstract void doGet(Request request, Response response);
	
	public abstract void doPost(Request request, Response response);
}

MyServlet source, where the specific call processing method

package com.ys.tomcat.servlet;
/**
 * 自定义servlet
 */

import com.ys.tomcat.http.Request;
import com.ys.tomcat.http.Response;

import java.io.OutputStream;

public class MyServlet extends HttpServlet{
    @Override
    public void doPost(Request request, Response response) {
        try{
            System.out.println("请求的method(类型)"+request.getMethod());
            System.out.println("请求的url"+request.getUrl());

            //返回response请求头+请求信息
            String res = Response.responseHeader + "connection succession...";
            //
            OutputStream outputStream = response.outputStream;
            //
            outputStream.write(res.getBytes());
            //冲刷
            outputStream.flush();
            //关闭流对象
            outputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    @Override
    public void doGet(Request request, Response response) {
        doPost(request,response);
    }
}

After the deal servlet, we will wait for the second part of the access connection, master classes, once there is a request, it will create a ServletThread thread, performs a service
Here Insert Picture Description

ServletThread source

package com.ys.tomcat;

import com.ys.tomcat.http.Request;
import com.ys.tomcat.http.Response;
import com.ys.tomcat.servlet.HttpServlet;

import java.io.OutputStream;
import java.net.Socket;


/**
 *自定义的线程执行tomcat操作(对servlet进行处理)
 *
 */
public class ServletThread extends Thread{
	//创建socket对象接受数据
	protected Socket socket;

	//初始化传值
	public ServletThread(Socket socket){
		this.socket = socket;
	}
	
	@Override
	public void run() {
		try{
			System.out.println("执行的线程"+Thread.currentThread());
			//将输入流对象传递给request对象
			Request request = new Request(socket.getInputStream());
			//拿到响应封装
			Response response = new Response(socket.getOutputStream());
			//service来处理(通过请求路径来实例化servlet—servletMapping)
			HttpServlet httpServlet = MyTomcat.servletMapping.get(request.getUrl().replace("/",""));

			//判断取出的HttpServlet对象是否为空
			if(httpServlet != null){//存在对应的servlet
				//调用servlet执行方法
				httpServlet.service(request,response);
			}else{//如果找不到对应的servlet信息
				//返回response请求头+请求信息
				String res = Response.responseHeader + "connection default...";
				//
				OutputStream outputStream = socket.getOutputStream();
				//
				outputStream.write(res.getBytes("utf-8"));
				//冲刷
				outputStream.flush();
				//关闭流对象
				outputStream.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//关闭socket连接
			if(socket != null){
				try{
					socket.close();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
	}
}

Thus a simple realization of the principle of tomcat is complete, you need to go to the source to add a link description

We start the project, access, the connection is successful
Here Insert Picture Description
Here Insert Picture Description

Guess you like

Origin blog.csdn.net/yang134679/article/details/89055006