迷你版Tomcat手写

版权声明: https://blog.csdn.net/Dongguabai/article/details/82988613

分析

一般我们使用Servlet,需要在web.xml文件中配置:

然后写一个TestServlet继承HttpSerevlet,重写doGet()和doPost()方法。

这时难免会有这样的疑问:

总体:

Request:

package com.dongguabai.tomcat.http;

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

/**
 * @author Dongguabai
 * @date 2018/10/9 21:10
 */
public class DongguabaiRequest {

    private String method;
    private String url;

    public DongguabaiRequest(InputStream is){
        String content = "";
        byte[] buff = new byte[1024];
        int len = 0;
        try {
            if ((len=is.read(buff))>0){
                content = new String(buff,0,len);
                //content
//                GET /web/user/query.json?name=zhangsan HTTP/1.1
//                User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134
//                Accept-Language: en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3
//                Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
//                Upgrade-Insecure-Requests: 1
//                Accept-Encoding: gzip, deflate
//                Host: localhost:18888
//                Connection: Keep-Alive
//                Cookie: expand_index=0; theme=bda-green-white
                //System.out.println(content);
                String line = content.split("\\n")[0];
                String[] arr = line.split("\\s");
                //获取方法参数也可以这么解析,这里就不演示了
                this.method = arr[0];
                this.url = arr[1].split("\\?")[0];

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String getMethod() {
        return method;
    }

    public String getUrl() {
        return url;
    }
}

Response:

package com.dongguabai.tomcat.http;

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

/**
 * @author Dongguabai
 * @date 2018/10/9 21:10
 */
public class DongguabaiResponse {

    private OutputStream os;

    public DongguabaiResponse(OutputStream os){
        this.os = os;
    }

    public void write(String outString) throws IOException {
        os.write(outString.getBytes());
    }
}

Servlet:

package com.dongguabai.tomcat.http;

/**
 * @author Dongguabai
 * @date 2018/10/9 21:10
 */
public abstract class DongguabaiServlet {

    /**
     * Does nothing, because this is an abstract class.
     */
    public DongguabaiServlet() {
        // NOOP
    }

    public void service(DongguabaiRequest request,DongguabaiResponse response) throws Exception{
        //由Servie方法觉得是执行post还是get方法
        if ("GET".equalsIgnoreCase(request.getMethod())){
            doGet(request,response);
        }else if ("POST".equalsIgnoreCase(request.getMethod())){
            doPost(request,response);
        }
    }

    public void destroy(DongguabaiRequest request,DongguabaiResponse response) throws Exception{

    }

    public abstract void doGet(DongguabaiRequest request, DongguabaiResponse response) throws Exception;

    public abstract void doPost(DongguabaiRequest request, DongguabaiResponse response) throws Exception;
}

demo:

package com.dongguabai.tomcat.servlet;

import com.dongguabai.tomcat.http.DongguabaiRequest;
import com.dongguabai.tomcat.http.DongguabaiResponse;
import com.dongguabai.tomcat.http.DongguabaiServlet;

/**
 * @author Dongguabai
 * @date 2018/10/9 21:13
 */
public class Demo1Servlet extends DongguabaiServlet {
    @Override
    public void doGet(DongguabaiRequest request, DongguabaiResponse response) throws Exception {
        doPost(request,response);
    }

    @Override
    public void doPost(DongguabaiRequest request, DongguabaiResponse response) throws Exception {
        response.write("this is demo1");
    }
}
package com.dongguabai.tomcat.servlet;

import com.dongguabai.tomcat.http.DongguabaiRequest;
import com.dongguabai.tomcat.http.DongguabaiResponse;
import com.dongguabai.tomcat.http.DongguabaiServlet;

/**
 * @author Dongguabai
 * @date 2018/10/9 21:13
 */
public class Demo2Servlet extends DongguabaiServlet {
    @Override
    public void doGet(DongguabaiRequest request, DongguabaiResponse response) throws Exception {
        doPost(request,response);
    }

    @Override
    public void doPost(DongguabaiRequest request, DongguabaiResponse response) throws Exception {
        response.write("this is demo2");
    }
}

Tomcat:

package com.dongguabai.tomcat;

import com.dongguabai.tomcat.http.DongguabaiRequest;
import com.dongguabai.tomcat.http.DongguabaiResponse;
import com.dongguabai.tomcat.http.DongguabaiServlet;
import com.dongguabai.tomcat.util.PropUtil;

import java.io.FileInputStream;
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;
import java.util.Properties;

/**
 * @author Dongguabai
 * @date 2018/10/9 21:04
 */
public class DongguabaiTomcat {

    private int defaultPort = 8888;
    private ServerSocket server;

    private Properties webXml = new Properties();
    private Map<String,DongguabaiServlet> servletMapping = new HashMap<>();

    private DongguabaiTomcat() {
    }

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

    private void start() {
        init();
        int port;
        try {
            String userPort = PropUtil.getProperty("port");
            port = Integer.valueOf(userPort);
        } catch (Exception e) {
            port = defaultPort;
            e.printStackTrace();
        }
        try {
            server = new ServerSocket(port);
            System.out.println("Tomcat已经启动了,监听端口为:" + port);
            //接收用户请求
            while (true) {
                Socket socket = server.accept();
                process(socket);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void init() {
        //根据web.properties,初始化ServletMapping
        try {
            //相当于WEB-INF下的web.xml
            String webInf = this.getClass().getResource("/").getPath();
            webXml.load(new FileInputStream(webInf + "web.properties"));
            for (Object o : webXml.keySet()) {
                String key = o.toString();
                if (key.endsWith(".url")) {
                    String servletName = key.replaceAll("\\.url$", "");
                    String url = webXml.getProperty(key);
                    String className = webXml.getProperty(servletName + ".className");
                    DongguabaiServlet servlet = (DongguabaiServlet) Class.forName(className).newInstance();
                    servletMapping.put(url,servlet);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void process(Socket client){
        //获取Socket对象,将Socket.getInputStream()封装成Request,Socket.getOuputStream()封装成Response
        try {
            try (OutputStream outputStream = client.getOutputStream();InputStream inputStream = client.getInputStream();) {
                DongguabaiRequest request = new DongguabaiRequest(inputStream);
                DongguabaiResponse response = new DongguabaiResponse(outputStream);
                //实现动态调用doGet/doPost方法,并且能够自定义返回结果
                //拿到用户请求的url
                String url = request.getUrl();
                if (servletMapping.containsKey(url)) {
                    servletMapping.get(request.getUrl()).service(request, response);
                }else {
                    response.write("404-NOT FOUND");
                }
                //因为http请求是短链接,这里要关闭
                client.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

测试结果:

猜你喜欢

转载自blog.csdn.net/Dongguabai/article/details/82988613