简易版Tomcat

一、绪论

tomcat实现了基于http协议的双向通信,为Servlet 3.0、JSP 2.2和EL 2.2等特性的支持。为实现以上功能,我们需要自定义Request,Response,Servlet,并通过Socket为浏览器和服务器建立通信通道

故,此次简易版Tomcat项目结构因如下所示

      

二、创建核心对象

2.1 MyRequest

简易request需要获取请求体中的访问路径、请求方法、参数内容

/**
 * @author sunyiran
 * @date 2018-09-28
 */
public class MyRequest {

    /**请求相对路径*/
    private String url;
    /**协议请求方式*/
    private String method;
    /**请求参数(简易版不处理)*/
    private HashMap<String,Object> params = new HashMap<>();


    public MyRequest(InputStream inputStream) throws IOException {
        //available()效率高但是不可靠
        byte[] b = new byte[inputStream.available()];
        inputStream.read(b);
        String head = new String(b);

        /*
         * http请求体内容格式
         * GET /favicon.ico HTTP/1.1
         * Host: localhost:8080
         * Connection: keep-alive
         * .......
         * */
        String[] info = head.split("\\n")[0].split("\\s");
        method = info[0];
        if (info.length > 1) {
            url = info[1];
        }
    }

    public String getUrl() {
        return url;
    }

    public String getMethod() {
        return method;
    }

    public HashMap<String, Object> getParams() {
        return params;
    }
}

2.2 MyResponse

/**
 * @author sunyiran
 * @date 2018-09-28
 */
public class MyResponse {

    private OutputStream outputStream;

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

    public void write(String content) {
        StringBuilder sb = new StringBuilder();
        //模拟http响应体
        sb.append("HTTP/1.1 200 OK \n")
                .append("Content-Type: text/html\n")
                .append("\r\n").append("<html><body>")
                .append(content).append("</body></html>");
        try {
            outputStream.write(sb.toString().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3 MyServlet

/**
 * @author sunyiran
 * @date 2018-09-28
 */
public abstract class MyServlet {

    public abstract void doPost(MyRequest request, MyResponse response);

    public abstract void doGet(MyRequest request, MyResponse response);

    /**
     * 处理请求
     *
     * @param request
     * @param response
     */
    public void service(MyRequest request, MyResponse response) {
        if (request.getMethod().equals("GET")) {
            doPost(request, response);
        } else {
            doGet(request, response);
        }
    }
}

2.4 MyCat

/**
 * @author sunyiran
 * @date 2018-09-28
 */
public class MyCat {

    /**
     * 默认端口
     */
    private int port = 8080;

    /**
     * servlet映射
     */
    private static Map<String, String> mappers = new HashMap<>();

    public void start() throws Exception {

        initMapping();
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("MyCat is starting ......");

        while (true) {
            //监听port端口
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            //请求分发
            dispatch(new MyRequest(inputStream), new MyResponse(outputStream));
        }
    }

    public void initMapping() {
        //测试映射
        mappers.put("/hello", "com.syr.HelloServlet");

    }

    /**
     * 根据请求寻找具体处理servlet
     *
     * @param request
     * @param response
     * @throws Exception
     */
    public void dispatch(MyRequest request, MyResponse response) throws Exception {
        String url = request.getUrl();
        if (url == null) {
            response.write("can not find the path");
            return;
        }
        if (url.equalsIgnoreCase("/favicon.ico")) {
            //可以自定义略缩图
            return;
        }
        if (!mappers.containsKey(url)) {
            response.write("can not find the path");
            return;
        }

        //反射获取处理对象
        Class<?> aClass = Class.forName(mappers.get(url));
        aClass.getMethod("service", MyRequest.class, MyResponse.class).invoke(aClass.newInstance(), request, response);

    }

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

2.5 HelloServlet(测试用)

/**
 * @author sunyiran
 * @date 2018-09-28
 */
public class HelloServlet extends MyServlet {

    @Override
    public void doPost(MyRequest request, MyResponse response) {
        doGet(request, response);
    }

    @Override
    public void doGet(MyRequest request, MyResponse response) {
        response.write("welcome to myCat");
    }
}

三、测试

猜你喜欢

转载自blog.csdn.net/qq_35813653/article/details/82892582