Implement simple tomcat

Posted by Sesquipedalian on Mon, 11 May 2020 16:41:20 +0200

Since our Web application is running in tomcat, the request must arrive at Tomcat first. Tomcat actually handles the request as follows.

  • First, provide Socket service

The start of Tomcat must be Socket service, but it only supports HTTP protocol!

In fact, we can expand our thinking here. Since Tomcat is based on Socket, what about BIO or NIO or AIO?

  • Second, request distribution

To know that a Tomcat can provide services for multiple Web applications, it is obvious that Tomcat can distribute URL s to different Web applications.

  • Third, you need to encapsulate the request and response as request/response

We have never encapsulated request/response in the Web application layer. We all use it directly. That's because Tomcat has done a good job for you!

Screenshot of project directory

code

MyReques

MyRequest: used to process requests, obtain request paths and request methods

public class MyRequest {

    private String url;
    private String method;


    public MyRequest(InputStream inputStream) throws IOException {

        byte[] bytes = new byte[1024];
        int length = 0;
        String httpRequest = "";
        if ((length = inputStream.read(bytes)) != 0){
            httpRequest = new String (bytes,0,length);
        }

        String httpHeader = httpRequest.split("\n")[0];
        method = httpHeader.split("\\s")[0];
        url = httpHeader.split("\\s")[1];
        System.out.println("[my request] method-->" + method + "\turl -->" + url);
    }
    getter/setter ......
}
MyResponse

MyResponse: corresponding the result to the browser

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; charset=UTF-8\n")
                .append("\r\n")
                .append("<html><body>")
                .append(content)
                .append("</body></html>");

            outputStream.write(httpResponse.toString().getBytes());
            outputStream.close();
    }
}
MyServlet

MyServlet: abstract class, real response request class, implementation of business logic,

public abstract class MyServlet {

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

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

    public void service(MyRequest request,MyResponse response){

        if ("get".equalsIgnoreCase(request.getMethod())){
            doGet(request,response);
        }else if ("post".equalsIgnoreCase(request.getMethod())){
            doPst(request,response);
        }
    }
}
public class HelloServlet extends MyServlet {
    public void doGet(MyRequest request, MyResponse response) {
        try {
            response.write("HelloServlet Processing get request...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void doPst(MyRequest request, MyResponse response) {
        try {
            response.write("HelloServlet Processing post request...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class HiServlet extends MyServlet {
    public void doGet(MyRequest request, MyResponse response) {
        try {
            response.write("HiServlet Processing get request...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void doPst(MyRequest request, MyResponse response) {
        try {
            response.write("HiServlet Processing post request...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Servlet configuration
public class ServletMapping {

    private String url;
    private String servletName;
    private String clazz;

    public ServletMapping(String url, String servletName, String clazz) {
        this.url = url;
        this.servletName = servletName;
        this.clazz = clazz;
    }
    getter/setter.......
}
public class ServletMappingConfig {

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

    static {
        servletMappingList.add(new ServletMapping("/hello","HelloServlet","com.cjervin.mytomcat.HelloServlet"));
        servletMappingList.add(new ServletMapping("/hi","HiServlet","com.cjervin.mytomcat.HiServlet"));
    }
}
Main startup class
public class MyCat {

    private int port = 8080;

    private Map<String,Object> servletMap = new HashMap<String, Object>(16);

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

    //Startup class
    public static void main(String[] args) {
        new MyCat(8080).start();
    }

    public void start(){
        //Initialize servlet configuration
        initServletMapping();

        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("[ my tomcat started ...]");
            while (true){
                Socket socket = serverSocket.accept();
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();

                MyRequest myRequest = new MyRequest(inputStream);
                MyResponse myResponse = new MyResponse(outputStream);
		//Distribution request
                dispatch(myRequest,myResponse);
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private void dispatch(MyRequest request, MyResponse response) {

        String className = (String)servletMap.get(request.getUrl());
        if (className == null){
            return;
        }
        try {
            Class<MyServlet> clazz = (Class<MyServlet>)Class.forName(className);
            MyServlet myServlet = clazz.newInstance();
            myServlet.service(request, response);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    private void initServletMapping() {
        for (ServletMapping servletMapping :ServletMappingConfig.servletMappingList) {
            servletMap.put(servletMapping.getUrl(),servletMapping.getClazz());
        }
    }
}

test

Start project test

As you can see, the simple tomcat can be completed here according to different requests. You think it's time to try it.

Source address: https://gitee.com/changxiaojie/myproject.git

reference resources: https://mp.weixin.qq.com/s/zQFml2IFW29uLFXuzBoz8g

Topics: Programming Tomcat socket mycat git