Tomcat代码实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Neo233/article/details/83869164

最近开课学到了Tomcat,对这个挺感兴趣,就跟着网上的教程自己实现了一遍。

众所周知,Tomcat是一个满足Servlet规范的容器,在Java Web的项目中大量使用;一般来说,我们需要将Web应用打包成War文件部署到Tomcat服务器中,通过制定映射关系来制定路径,指明被哪个方法处理。Tomcat对于实际的请求会做出以下的操作:

  • 提供Socket服务,不过是支持HTTP的Socket
  • 进行请求的下发
  • 将请求与响应封装成response和request

下面上代码:

一.封装请求对象

import java.io.IOException;
import java.io.InputStream;
//封装请求对象,通过输入流,对 HTTP 协议进行解析,拿到 HTTP 请求头的方法以及 URl
public class MyRequest {
	private String url;
	private String method;
	public MyRequest(InputStream inputStream) throws IOException {
    	String httpRequest = " ";
    	byte[] httpRequestBytes = new byte[1024];
   		int length;
    	if ((length = inputStream.read(httpRequestBytes)) > 0) {
        	httpRequest = new String(httpRequestBytes, 0, length);
    	}
    	String httpHead = httpRequest.split("\n")[0];
    	url = httpHead.split("\\s")[1];
    	method = httpHead.split("\\s")[0];
 	}
	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;
	}
}
//通过Socket中的输入输出流,进行对网址的解析,分别将url和method进行分离。

二.封装响应对象

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

//封装响应对象,基于HTTP协议的格式进行输出
public class MyResponse {
    private OutputStream outputStream;

    public MyResponse(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><body>")
                           .append(content)
                           .append("<body><html>");
        outputStream.write(httpResponse.toString().getBytes());
        outputStream.close();
    }
}
//基于HTTP协议格式进行写入操作

三.Servlet请求处理基类

import java.io.IOException;

public class MyServlet  {
    public void doGet(MyRequest myRequest,MyResponse myResponse){
        try{
            myResponse.write(" get Hello World");
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    public void doPost(MyRequest myRequest,MyResponse myResponse){
        try{
            myResponse.write(" post Hello World");
        }catch (IOException e){
            e.printStackTrace();
        }
    }

  public  void service(MyRequest myRequest,MyResponse myResponse){
          if(myRequest.getMethod().equalsIgnoreCase("post")){
            doPost(myRequest,myResponse);
          }else if(myRequest.getMethod().equalsIgnoreCase("get")){
              doGet(myRequest,myResponse);
          }
  }
}
//Tomcat提供doPost(),doGet(),service()方法

四.Servletp配置

public class ServletMapping {
    private String servletName;
    private String url;
    private String clazz;

    public ServletMapping(String servletName,String url,String clazz){
        this.servletName = servletName;
        this.url = url;
        this.clazz = 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;
    }
}

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

public class ServletMappingConfig {
    public static List<ServletMapping> servletMappingList = new ArrayList<>();
    static {
        servletMappingList.add(new ServletMapping("Hello World","/world","MyServlet"));
    }
}
//通过设置映射关系对方法进行map映射调用。

五.启动类

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

//tomcat服务的启动类
public class MyTomcat {
    private int port ;
    private Map<String,String> urlServletMap = new HashMap<>();

    public static void main(String[] args) {
        new MyTomcat(8080).start();
    }

    public MyTomcat(int port){
        this.port = port;
    }

    public void start(){
        //初始化 URL与对应处理的servlet的关系
        initServletMapping();

        ServerSocket serverSocket = null;

        try{
            serverSocket = new ServerSocket(port);
            System.out.println("MyTomcat is start on " + port);

            while(true){
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();

                MyRequest myRequest = new MyRequest(inputStream);
                MyResponse myResponse = new MyResponse(outputStream);


                dispatch(myRequest,myResponse);
                socket.close();
            }
        }catch (IOException e){
           e.printStackTrace();
        }finally {
            if(serverSocket != null){
                try{
                    serverSocket.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    //初始化url 与对应servler的关系
    private void initServletMapping(){
        for(ServletMapping servletMapping : ServletMappingConfig.servletMappingList){
            urlServletMap.put(servletMapping.getUrl(),servletMapping.getClazz());
        }
    }

    //请求分发
    private void dispatch(MyRequest myRequest,MyResponse myResponse){
           String clazz = urlServletMap.get(myRequest.getUrl());

           //利用反射实例化具体的servlet处理请求
           try{
               Class<MyServlet> myServletClass =(Class<MyServlet>) Class.forName(clazz);
               MyServlet myServlet = myServletClass.newInstance();
               myServlet.service(myRequest,myResponse);
           }catch (ClassNotFoundException e){
              e.printStackTrace();
           }catch (InstantiationException e){
              e.printStackTrace();
           }catch (IllegalAccessException e){
              e.printStackTrace();
           }
    }
}
//解析HTTP协议,封装请求/响应对象,使用反射的实例化进行映射。

猜你喜欢

转载自blog.csdn.net/Neo233/article/details/83869164