Eingehende Analyse von Tomcat - benutzerdefinierter Tomcat (1)

    Als Java-Backend-Entwicklung ist Tomcat eine Technologie, die wir oft verwenden, aber die meiste Zeit verwenden wir sie nur und verstehen ihr wahres Prinzip nicht. Als am weitesten verbreiteter Servlet-Container sind seine hervorragende Architektur und seine Ideen wert, gelernt zu werden. Zu wissen, wie es funktioniert, hat auch unsere Technologie stark verbessert. Beginnen Sie also jetzt damit, dem Buch „Eingehende Analyse von Tomcat“ zu folgen, um Schritt für Schritt ein tiefes Verständnis von Tomcat zu erlangen

1. Konzeptvorstellung

1. Die Rolle des Servlet-Containers

    Der Servlet-Container empfängt hauptsächlich Client-Anfragen, erstellt für jede Anfrage eine Anfrageobjektanfrage und eine Antwortobjektantwort und ruft die Dienstmethode des Servlets mit der Anfrage und der Antwort als Parameter auf. Das Servlet liest die Informationen aus der Anfrage und sendet die Antwort Informationen durch die Antwort. .

2.HTTP

    Das HTTP-Protokoll ist ein Kommunikationsprotokoll, das auf TCP/IP basiert, um Daten zu übertragen, und es ist ein Protokoll, das auf "Request-Response" basiert. Der Client stellt eine Anfrage und der Server antwortet auf die Anfrage. Das Format der Anforderungsnachricht umfasst: Anforderungszeile, Anforderungsheader, Leerzeile und Anforderungsdaten. Wie zum Beispiel:

GET /hello HTTP/1.1
Host: localhost:8080
Connection: keep-alive
复制代码

    Das Antwortformat ist wie folgt:

HTTP/1.1 200 OK
content-encoding: gzip
content-length: 28
content-type: text/html; charset=UTF-8
date: Wed, 23 Mar 2022 14:11:40 GMT
复制代码

3. Steckdose

    Ein Socket ist der Endpunkt einer Netzwerkverbindung. Sockets ermöglichen es Anwendungen, Daten aus dem Netzwerk zu lesen und Daten in das Netzwerk zu schreiben. Zwei Anwendungen auf unterschiedlichen Computern können kommunizieren, indem sie Byteströme über die Verbindung senden oder empfangen. Java verwendet die java.net.Socket-Klasse, um Sockets zu implementieren.

2. Implementieren Sie einen Webserver

    Ein einfachster Webserver enthält die folgenden Klassen: HttpServer (Webserver), Request (Anfrageobjekt), Response (Antwortobjekt).

public class HttpServer {
    /**
     * 存放静态资源的目录
     */
    public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
    /**
     * 关闭命令。若要关闭服务器,可以在请求路径后面拼接SHUTDOWN命令,比如:http://localhost:8080/SHUTDOWN
     */
    private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
    /**
     * 是否收到关闭的命令
     */
    private boolean shutdown = false;

    public static void main(String[] args) {
        HttpServer server = new HttpServer();
        server.await();
    }

    public void await() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            // 开启一个ServerSocket
            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        // 循环等待连接
        while (!shutdown) {
            Socket socket;
            InputStream input;
            OutputStream output;
            try {
                socket = serverSocket.accept();
                input = socket.getInputStream();
                output = socket.getOutputStream();
          
                Request request = new Request(input);
                // 对请求解析
                request.parse();
				
                Response response = new Response(output);
                response.setRequest(request);
                // 响应静态资源
                response.sendStaticResource();

                socket.close();
                // 接收到关闭命令
                shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
            } catch (IOException e) {
                e.printStackTrace();
                continue;
            }
        }
    }
}
复制代码
public class Request {

    private String uri;
    private InputStream input;

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public Request(InputStream input) {
        this.input = input;
    }

    /**
     * 用于解析http请求中的原始数据
     */
    public void parse() {
        StringBuffer request = new StringBuffer(2048);
        int i;
        byte[] buffer = new byte[2048];
        try {
            i = input.read(buffer);
        } catch (Exception e) {
            e.printStackTrace();
            i = -1;
        }
        for (int j = 0; j < i; j++) {
            request.append((char) buffer[j]);
        }
        System.out.println(request);
        uri = parseUri(request.toString());
    }

    /**
     * 从http请求行中获取uri
     *
     * @param requestString
     * @return
     */
    private String parseUri(String requestString) {
        int index1, index2;
        index1 = requestString.indexOf(" ");
        if (index1 != -1) {
            index2 = requestString.indexOf(" ", index1 + 1);
            if (index2 > index1) {
                return requestString.substring(index1 + 1, index2);
            }
        }
        return null;
    }
}
复制代码
public class Response {

    private static final int BUFFER_SIZE = 1024;

    Request request;

    OutputStream output;

    public Response(OutputStream output) {
        this.output = output;
    }

    public void setRequest(Request request) {
        this.request = request;
    }

    /**
     * 返回一个静态资源到浏览器
     */
    public void sendStaticResource() {
        byte[] bytes = new byte[BUFFER_SIZE];
        FileInputStream fis = null;
        try {
            File file = new File(HttpServer.WEB_ROOT, request.getUri());
            // 在项目的根路径下读取是否存在静态资源,如果存在则返回静态资源,不存在则返回404
            if (file.exists()) {
                String header = "HTTP/1.1 200 OK\n" +
                        "Content-Type: text/html\n" +
                        "\r\n";
                output.write(header.getBytes());
                fis = new FileInputStream(file);
                int ch = fis.read(bytes, 0, BUFFER_SIZE);
                while (ch != -1) {
                    output.write(bytes, 0, ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                }
            } else {
                String errorMessage = "HTTP/1.1 404 File Not Found\n" +
                        "Content-Type: text/html\n" +
                        "\r\n" +
                        "<html><body><h1>File Not Found</h1></body></html>";

                output.write(errorMessage.getBytes());
                output.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
复制代码

    Erstellen Sie einen Webroot-Ordner im Projektstammverzeichnis und erstellen Sie eine neue index.html. Starten Sie HttpServer und geben Sie in Ihrem Browser http://localhost:8080/index.html ein .

    Die Eingabe anderer Pfade ohne Ressourcen gibt Folgendes zurück:

    Der obige Code wird gehostet unter: gitee.com/bailiny/my-…

Supongo que te gusta

Origin juejin.im/post/7078308260784111653
Recomendado
Clasificación