JavaWeb中Tomcat底層機制和Servlet運行原理詳解
一. 一圖明理

二. 概念
Tomcat是一個開源的Java Web服務器,它是基于Java Servlet和JavaServer Pages(JSP)技術的。下面是關于Tomcat底層機制和Servlet運行原理的簡要說明:
- Tomcat底層機制:
- 網絡通信:Tomcat使用Java的Socket API來監(jiān)聽特定的端口(通常是8080),接收來自客戶端的HTTP請求。
- 線程池:Tomcat使用線程池來處理并發(fā)的請求。當有新的請求到達時,Tomcat會從線程池中獲取一個空閑線程來處理該請求,這樣可以提高處理效率。
- 生命周期管理:Tomcat負責管理Servlet和其他Web組件的生命周期,包括初始化、請求處理和銷毀等階段。(init(), run())
- 請求處理管道:Tomcat通過請求處理管道來處理HTTP請求。請求經過一系列的處理器,如身份驗證、日志記錄和安全檢查等,最終被交給適當的Servlet進行處理。(handle())
- 連接池:Tomcat使用連接池來管理與數據庫的連接。這樣可以提高性能,并避免頻繁地創(chuàng)建和銷毀數據庫連接。(handle())
- Servlet運行原理:
- Servlet容器:Tomcat是一個Servlet容器,它負責加載、初始化和管理Servlet。當Tomcat啟動時,它會讀取配置文件(如web.xml)來確定需要加載的Servlet類。
- 生命周期:每個Servlet都有自己的生命周期,包括初始化、請求處理和銷毀等階段。Tomcat會在適當的時間調用Servlet的生命周期方法(如init()、service()和destroy())。
- 請求處理:當Tomcat接收到HTTP請求時,它會根據請求的URL找到對應的Servlet,并將請求轉發(fā)給該Servlet進行處理。Servlet通過HttpServletRequest對象獲取請求的信息,并通過HttpServletResponse對象發(fā)送響應給客戶端。
- 多線程處理:Tomcat使用多線程來處理并發(fā)請求。每個請求都被分配給一個獨立的線程進行處理,這樣可以同時處理多個請求,提高服務器的性能。
三. 容器的理解
在tomcat底層實現中, servlet作為容器, 實現可以理解為HashMap, 鍵是servlet-name值是servlet-class, 而HashMap就是一個容器, 從容器中得到一個servlet實例, 對其進行初始化, 供web使用, 調用其中的service()方法, service()方法對HTTP請求的method進行判斷, 對每個相應的method都有相應的do方法, 可以使用.
四. 案例


不用tomcat以及servlet實現
五. 代碼分析和代碼實現


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 + "數字格式異常, 無法包裝");
}
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) {
}
}六. 注意

到此這篇關于JavaWeb中Tomcat底層機制和Servlet運行原理詳解的文章就介紹到這了,更多相關Tomcat底層機制和Servlet運行原理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Hibernate基于ThreadLocal管理Session過程解析
這篇文章主要介紹了Hibernate基于ThreadLocal管理Session過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10

