Java web learning notes 3: tomcat implementation principle

Posted by joquius on Sat, 12 Feb 2022 07:09:22 +0100

Hit in front: part of the picture is cut from the horse soldier teacher servlet and jsp
Lecture notes.
Video link: https://www.bilibili.com/video/BV1cV411H7RY?p=1

**Operation principle of tomcat:
*

Interactive process:
The client sends a request to the server. tomcat request receives the request and presents it to the service request object. The request object selects the applet written in advance to process the request and respond to complete the service. In this process, there are many applets in the webserver container. How does the service know which one to call? The applet contains the processing of requests. But at the beginning, we must first handle the encapsulation of request and response objects.
Request message format:

package com.msb;

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

public class MyRequest {
	private String requestMethod;
	private String requestUrl;
	public MyRequest(InputStream inputStream) throws IOException {
		//Create buffer
		byte[] buffer=new byte[1024];
		int len=0;
		String str=null;
		if((len=inputStream.read(buffer))>0) {
			str=new String(buffer,0,len);
		}
		String data=str.split("\n")[0];
		String[] params=data.split(" ");
		this.requestMethod=params[0];
		this.requestUrl=params[1];
	}
	public String getRequestMethod() {
		return requestMethod;
	}
	public void setRequestMethod(String requestMethod) {
		this.requestMethod = requestMethod;
	}
	public String getRequestUrl() {
		return requestUrl;
	}
	public void setRequestUrl(String requestUrl) {
		this.requestUrl = requestUrl;
	}
	
}

Here is a simple package of request, just the simulation principle.
Code interpretation: data transmission or stream transmission. The request object receives the inputstream stream, sets up buffer segmentation and parses it into string type data processing.

package com.msb;

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

public class MyResponse {
	private OutputStream outputStream;
	public MyResponse(OutputStream outputStream) {
		this.outputStream=outputStream;
	}
	public void write(String str) throws IOException {
		StringBuilder builder = new StringBuilder();
		builder.append("HTTP/1.1 200 OK\n")
				.append("Content-Type:text/html\n")
				.append("\r\n")
				.append("<html>")
				.append("<body>")
				.append("<h1>"+str+"</h1>")
				.append("</body>")
				.append("</html>");
		this.outputStream.write(builder.toString().getBytes());
		
	}
}

Code interpretation: response converts the processed string into a stream response. Note "append (" \ r\n ")" encapsulation
After encapsulation, we found that: in fact, this process is the process of request and response. You can drop any applet you want. We can make a mapping relationship between each requesturl and the applet encapsulation class, because each applet has the same method, but the method body is different, so we can use an abstract class to let them inherit, Or use interfaces to regulate them.

package com.msb;

public abstract class MyHttpServlet {
	public static final String METHOD_GET="GET";
	public static final String METHOD_POST="POST";
	
	public abstract void doGet(MyRequest request,MyResponse response);
	public abstract void doPost(MyRequest request,MyResponse response);
	
	
	//Determine which method to call based on the request
	public void service(MyRequest request,MyResponse response) {
		if(METHOD_GET.equals(request.getRequestMethod())) {
			doGet(request,response);
		}else if(METHOD_POST.equals(response)) {doPost(request,response);}
	}
}
package com.msb;

import java.io.IOException;

public class MyServlet extends MyHttpServlet {

	@Override
	public void doGet(MyRequest request, MyResponse response) {
		try {
			response.write("doget:MyServlet");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public void doPost(MyRequest request, MyResponse response) {
		try {
			response.write("doPost:MyServlet");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Mapping relationship:

package com.msb;

import java.util.HashMap;

public class MyMapping {
	public static HashMap<String,String> mapping=new HashMap<String,String>();
	
	static {
		mapping.put("/MyTomCat", "com.msb.MyServlet");
		
	}

	public static HashMap<String, String> getMapping() {
		return mapping;
	}

	
}

Back to figure 1:

We have encapsulated the service, interface and applet, but we still lack network interaction and service applet interaction. server completes this process.

package com.msb;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

//Define the receiving program of the server to receive socket requests

public class MyServer {

	//Define the receiver of the server and accept socket requests
	
	@SuppressWarnings("deprecation")
	public static void startServer(int port) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
		ServerSocket serverSocket = new ServerSocket(port);
		Socket socket=null;
		while(true) {
			socket=serverSocket.accept();
			InputStream inputStream = socket.getInputStream();
			OutputStream outputStream = socket.getOutputStream();
			MyRequest request=new MyRequest(inputStream);
			MyResponse response = new MyResponse(outputStream);
			String clazzName = new MyMapping().getMapping().get(request.getRequestUrl());
			if(clazzName!=null) {
				Class<? extends MyHttpServlet> clazz = (Class<? extends MyHttpServlet>)Class.forName(clazzName);
				MyHttpServlet newInstance = clazz.newInstance();
				newInstance.service(request, response);
				
			}
		}
		
	}
	public static void main(String[] args) {
		try {
			startServer(1775);
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Code interpretation: static method startserver method parameter: port number. Pass the parameters to the server socket, and the iron bolt (dead loop) realizes the long service. The server receives the request and assigns it to the socket for processing. The socket obtains the stream, passes it, and creates MyRequest and myresponse objects. The key code is string clazzname = new mymapping() getMapping(). get(request.getRequestUrl()); Get the applet that requests the url mapping call, then create the applet object with the reflection mechanism, and call the doget/dopost method to process the request and respond.
Browser request result after running:

However, there are still some problems, such as multithreading and high concurrency, which can be implemented later.

Topics: Java Tomcat