JavaWeb中Tomcat底層機制和Servlet運行原理詳解
一. 一圖明理
二. 概念
Tomcat是一個開源的Java Web服務器,它是基于Java Servlet和JavaServer Pages(JSP)技術(shù)的。下面是關(guān)于Tomcat底層機制和Servlet運行原理的簡要說明:
- Tomcat底層機制:
- 網(wǎng)絡通信:Tomcat使用Java的Socket API來監(jiān)聽特定的端口(通常是8080),接收來自客戶端的HTTP請求。
- 線程池:Tomcat使用線程池來處理并發(fā)的請求。當有新的請求到達時,Tomcat會從線程池中獲取一個空閑線程來處理該請求,這樣可以提高處理效率。
- 生命周期管理:Tomcat負責管理Servlet和其他Web組件的生命周期,包括初始化、請求處理和銷毀等階段。(init(), run())
- 請求處理管道:Tomcat通過請求處理管道來處理HTTP請求。請求經(jīng)過一系列的處理器,如身份驗證、日志記錄和安全檢查等,最終被交給適當?shù)腟ervlet進行處理。(handle())
- 連接池:Tomcat使用連接池來管理與數(shù)據(jù)庫的連接。這樣可以提高性能,并避免頻繁地創(chuàng)建和銷毀數(shù)據(jù)庫連接。(handle())
- Servlet運行原理:
- Servlet容器:Tomcat是一個Servlet容器,它負責加載、初始化和管理Servlet。當Tomcat啟動時,它會讀取配置文件(如web.xml)來確定需要加載的Servlet類。
- 生命周期:每個Servlet都有自己的生命周期,包括初始化、請求處理和銷毀等階段。Tomcat會在適當?shù)臅r間調(diào)用Servlet的生命周期方法(如init()、service()和destroy())。
- 請求處理:當Tomcat接收到HTTP請求時,它會根據(jù)請求的URL找到對應的Servlet,并將請求轉(zhuǎn)發(fā)給該Servlet進行處理。Servlet通過HttpServletRequest對象獲取請求的信息,并通過HttpServletResponse對象發(fā)送響應給客戶端。
- 多線程處理:Tomcat使用多線程來處理并發(fā)請求。每個請求都被分配給一個獨立的線程進行處理,這樣可以同時處理多個請求,提高服務器的性能。
三. 容器的理解
在tomcat底層實現(xiàn)中, servlet作為容器, 實現(xiàn)可以理解為HashMap, 鍵是servlet-name值是servlet-class, 而HashMap就是一個容器, 從容器中得到一個servlet實例, 對其進行初始化, 供web使用, 調(diào)用其中的service()方法, service()方法對HTTP請求的method進行判斷, 對每個相應的method都有相應的do方法, 可以使用.
四. 案例
不用tomcat以及servlet實現(xiàn)
五. 代碼分析和代碼實現(xiàn)
LxbRequestHandle類
package com.lxb.tomcat.handle; //-*- code = utf-8 -*- //@Time : 2023-07-20 13:22:00 //@Authors : 羅雄波 //@File : LxbRequestHandle.java //@Software : IntelliJ IDEA import com.lxb.tomcat.LxbTomcatV3; import com.lxb.tomcat.http.LxbHttpRequest; import com.lxb.tomcat.http.LxbHttpResponse; import com.lxb.tomcat.servlet.LxbHttpServlet; import com.lxb.tomcat.utils.WebUtils; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class LxbRequestHandle implements Runnable{ private Socket accept; public LxbRequestHandle(Socket socket) { this.accept = socket; } public void run() { try { LxbHttpRequest request = new LxbHttpRequest(accept); LxbHttpResponse response = new LxbHttpResponse(accept.getOutputStream()); String uri = request.getUri(); if(WebUtils.isHtml(uri)) { System.out.println(uri.substring(1)); String resp = WebUtils.readFile(uri.substring(1)); String responseInfo = LxbHttpResponse.respHeader + resp; OutputStream outputStream = response.getOutputStream(); outputStream.write(responseInfo.getBytes()); outputStream.flush(); outputStream.close(); accept.close(); return; } String servletName = LxbTomcatV3.servletMapping.get(uri); if(servletName == null) { servletName = ""; } LxbHttpServlet servlet = LxbTomcatV3.servlet.get(servletName); if(servlet != null) { servlet.service(request, response); } else { String resp = LxbHttpResponse.respHeader + "<h1>404 not found!!!</h>"; OutputStream responseOutputStream = response.getOutputStream(); responseOutputStream.write(resp.getBytes()); responseOutputStream.flush(); responseOutputStream.close(); } accept.close(); } catch (Exception e) { throw new RuntimeException(e); } finally { if (accept != null) { try { accept.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
LxbHttpRequest和LxbHttpResponse
package com.lxb.tomcat.http; //-*- code = utf-8 -*- //@Time : 2023-07-20 14:59:24 //@Authors : 羅雄波 //@File : LxbHttpRequest.java //@Software : IntelliJ IDEA import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.Socket; import java.util.HashMap; public class LxbHttpRequest { private Socket socket; private String method; private String uri; private HashMap<String, String> parameterMapping = new HashMap<String, String>(); public LxbHttpRequest(Socket socket) { this.socket = socket; try { ParseProcess(); } catch (Exception e) { throw new RuntimeException(e); } } public void ParseProcess() throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8")); String temp; temp = reader.readLine(); // GET /cal.html HTTP/1.1 String[] request = temp.split(" "); method = request[0]; int index = request[1].indexOf("?"); if (index == -1) { uri = request[1]; } else { uri = request[1].substring(0, index); String parameterPair = request[1].substring(index + 1); String[] parameters = parameterPair.split("&"); if (parameters[0] != null && !parameters[0].equals("")) { for (String parameter : parameters) { String[] split = parameter.split("="); if(split.length == 2) { parameterMapping.put(split[0], split[1]); } } } } } public String getMethod() { return method; } public String getUri() { return uri; } public String getParameter(String key) { if(parameterMapping.get(key) != null) { return parameterMapping.get(key); } else { return ""; } } @Override public String toString() { return "LxbHttpRequest" + "{ method = " + method + ", uri = " + uri + ", parameter = " + parameterMapping + "}"; } }
package com.lxb.tomcat.http; //-*- code = utf-8 -*- //@Time : 2023-07-20 15:49:29 //@Authors : 羅雄波 //@File : LxbHttpResponse.java //@Software : IntelliJ IDEA import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class LxbHttpResponse { private OutputStream outputStream = null; public static final String respHeader = "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html;charset=utf-8\r\n\r\n"; public LxbHttpResponse(OutputStream outputStream) { this.outputStream = outputStream; } public OutputStream getOutputStream() { return outputStream; } }
LxbTomcat
package com.lxb.tomcat; //-*- code = utf-8 -*- //@Time : 2023-07-20 15:37:29 //@Authors : 羅雄波 //@File : LxbTomcatV3.java //@Software : IntelliJ IDEA import com.lxb.tomcat.handle.LxbRequestHandle; import com.lxb.tomcat.servlet.LxbHttpServlet; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.junit.Test; import java.io.File; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.List; import java.util.concurrent.ConcurrentHashMap; public class LxbTomcatV3 { public static ConcurrentHashMap<String, LxbHttpServlet> servlet = new ConcurrentHashMap<String, LxbHttpServlet>(); public static ConcurrentHashMap<String, String> servletMapping = new ConcurrentHashMap<String, String>(); public static void main(String[] args) throws Exception { LxbTomcatV3 lxbTomcatV3 = new LxbTomcatV3(); lxbTomcatV3.Init(); lxbTomcatV3.run(); } public void run() { try { ServerSocket socket = new ServerSocket(8080); while (!socket.isClosed()) { Socket accept = socket.accept(); LxbRequestHandle requestHandle = new LxbRequestHandle(accept); new Thread(requestHandle).start(); } } catch (IOException e) { throw new RuntimeException(e); } } @Test public void Init() { String path = LxbTomcatV3.class.getResource("/").getPath(); // System.out.println(path); // 該類的路徑 /D:/NewExecllction/exicese%20code/lxb-tomcat/target/classes/com/lxb/tomcat/ // 根路徑 /D:/NewExecllction/exicese%20code/lxb-tomcat/target/classes/ SAXReader saxReader = new SAXReader(); try { Document document = saxReader.read(new File(path + "web.xml")); // System.out.println(document); Element rootElement = document.getRootElement(); List<Element> elements = rootElement.elements(); for (Element element : elements) { if ("servlet".equalsIgnoreCase(element.getName())) { Element servletName = element.element("servlet-name"); Element servletClass = element.element("servlet-class"); servlet.put(servletName.getText(), (LxbHttpServlet) Class.forName(servletClass.getText().trim()).newInstance()); } else if ("servlet-mapping".equalsIgnoreCase(element.getName())) { Element servletName = element.element("servlet-name"); Element servletUrl = element.element("url-pattern"); servletMapping.put(servletUrl.getText(), servletName.getText()); } } } catch (Exception e) { e.printStackTrace(); } System.out.println(servlet); System.out.println(servletMapping); } @Test public void test() { String path = LxbTomcatV3.class.getResource("/").getPath(); System.out.println(path + "web.xml"); } }
WebUtils
package com.lxb.tomcat.utils; //-*- code = utf-8 -*- //@Time : 2023-07-19 16:00:33 //@Authors : 羅雄波 //@File : WebUtils.java //@Software : IntelliJ IDEA import org.junit.Test; import java.io.*; public class WebUtils { public static int parseInt(String strNum, int defaultVal) { try { return Integer.parseInt(strNum); } catch (NumberFormatException e) { System.out.println(strNum + "數(shù)字格式異常, 無法包裝"); } return defaultVal; } public static boolean isHtml(String uri) { return uri.endsWith(".html"); } public static String readFile(String filename) { String path = com.lxb.tomcat.utils.WebUtils.class.getResource("/").getPath(); StringBuilder stringBuffer = new StringBuilder(); try { System.out.println(path + filename); BufferedReader bufferedReader = new BufferedReader(new FileReader(path + filename)); String buffer = null; while ((buffer = bufferedReader.readLine()) != null && !buffer.equals("")) { stringBuffer.append(buffer); } } catch (Exception e) { e.printStackTrace(); } return stringBuffer.toString(); } }
LxbCalServlet
package com.lxb.tomcat.servlet; //-*- code = utf-8 -*- //@Time : 2023-07-20 16:14:24 //@Authors : 羅雄波 //@File : LxbCalServlet.java //@Software : IntelliJ IDEA import com.lxb.tomcat.http.LxbHttpRequest; import com.lxb.tomcat.http.LxbHttpResponse; import com.lxb.tomcat.utils.WebUtils; import java.io.IOException; import java.io.OutputStream; public class LxbCalServlet extends LxbHttpServlet { @Override public void doGet(LxbHttpRequest request, LxbHttpResponse response) { doPost(request, response); } @Override public void doPost(LxbHttpRequest request, LxbHttpResponse response) { int num1 = WebUtils.parseInt(request.getParameter("num1"), 0); int num2 = WebUtils.parseInt(request.getParameter("num2"), 0); int result = num1 + num2; OutputStream outputStream = response.getOutputStream(); String resp = LxbHttpResponse.respHeader + "<h1>求和: " + num1 + "+" + num2 + " = " + result + "</h>"; try { outputStream.write(resp.getBytes()); outputStream.flush(); outputStream.close(); } catch (IOException e) { throw new RuntimeException(e); } } public void init() throws Exception { } public void destroy() { } }
LxbServlet
package com.lxb.tomcat.servlet; //-*- code = utf-8 -*- //@Time : 2023-07-20 16:09:43 //@Authors : 羅雄波 //@File : LxbServlet.java //@Software : IntelliJ IDEA import com.lxb.tomcat.http.LxbHttpRequest; import com.lxb.tomcat.http.LxbHttpResponse; import java.io.IOException; public interface LxbServlet { void init() throws Exception; void service(LxbHttpRequest request, LxbHttpResponse response) throws IOException; void destroy(); }
LxbHttpServlet
package com.lxb.tomcat.servlet; //-*- code = utf-8 -*- //@Time : 2023-07-20 16:11:02 //@Authors : 羅雄波 //@File : lxbHttpServlet.java //@Software : IntelliJ IDEA import com.lxb.tomcat.http.LxbHttpRequest; import com.lxb.tomcat.http.LxbHttpResponse; import java.io.IOException; public abstract class LxbHttpServlet implements LxbServlet{ public void service(LxbHttpRequest request, LxbHttpResponse response) throws IOException { if(request.getMethod().equals("GET")) { this.doGet(request, response); } else if(request.getMethod().equals("POST")) { this.doPost(request, response); } } public void doGet(LxbHttpRequest request, LxbHttpResponse response) { } public void doPost(LxbHttpRequest request, LxbHttpResponse response) { } }
六. 注意
到此這篇關(guān)于JavaWeb中Tomcat底層機制和Servlet運行原理詳解的文章就介紹到這了,更多相關(guān)Tomcat底層機制和Servlet運行原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Hibernate基于ThreadLocal管理Session過程解析
這篇文章主要介紹了Hibernate基于ThreadLocal管理Session過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10