日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Tomcat工作原理及简单模拟实现

發布時間:2025/3/11 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tomcat工作原理及简单模拟实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Tomcat應該都不陌生,我們經常會把寫好的代碼打包放在Tomcat里并啟動,然后在瀏覽器里就能愉快的調用我們寫的代碼來實現相應的功能了,那么Tomcat是如何工作的?

一、Tomcat工作原理

我們啟動Tomcat時雙擊的startup.bat文件的主要作用是找到catalina.bat,并且把參數傳遞給它,而catalina.bat中有這樣一段話:

Bootstrap.class是整個Tomcat 的入口,我們在Tomcat源碼里找到這個類,其中就有我們經常使用的main方法:

這個類有兩個作用 :

  • 初始化一個守護進程變量、加載類和相應參數;

  • 解析命令,并執行。

源碼不過多贅述,我們在這里只需要把握整體架構,有興趣的同學可以自己研究下源碼。Tomcat的server.xml配置文件中可以對應構架圖中位置,多層的表示可以配置多個:

即一個由 Server->Service->Engine->Host->Context 組成的結構,從里層向外層分別是:

Server:服務器Tomcat的頂級元素,它包含了所有東西。

Service:一組 Engine(引擎) 的集合,包括線程池 Executor 和連接器 Connector 的定義。

Engine(引擎):一個 Engine代表一個完整的 Servlet引擎,它接收來自Connector的請求,并決定傳給哪個Host來處理。

Container(容器):Host、Context、Engine和Wraper都繼承自Container接口,它們都是容器。

Connector(連接器):將Service和Container連接起來,注冊到一個Service,把來自客戶端的請求轉發到Container。

Host:即虛擬主機,所謂的”一個虛擬主機”可簡單理解為”一個網站”。

Context(上下文 ): 即 Web 應用程序,一個 Context 即對于一個 Web 應用程序。

Context容器直接管理Servlet的運行,Servlet會被其給包裝成一個StandardWrapper類去運行。Wrapper負責管理一個Servlet的裝載、初始化、執行以及資源回收,它是最底層容器。

比如現在有以下網址,根據“/”切割的鏈接就會定位到具體的處理邏輯上,且每個容器都有過濾功能。

二、Tomcat實現思路

下面只是簡單實現效果,當瀏覽器訪問對應地址時:

實現以上效果整體思路如下:

1.ServerSocket占用8080端口,用while(true)循環等待用戶發請求。

2.拿到瀏覽器的請求,解析并返回URL地址,用I/O輸入流讀取本地磁盤上相應文件。

3.讀取文件,不存在構建響應報文頭、HTML正文內容,存在則寫到瀏覽器端。

三、實現Tomcat

工程文件結構和pom.xml文件:

1.HttpServer核心處理類,用于接受用戶請求,傳遞HTTP請求頭信息,關閉容器:

public class HttpServer {// 用于判斷是否需要關閉容器private boolean shutdown = false;public void acceptWait() {ServerSocket serverSocket = null;try {//端口號,最大鏈接數,ip地址serverSocket = new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));}catch (IOException e) {e.printStackTrace();System.exit(1); }// 等待用戶發請求while (!shutdown) {try {Socket socket = serverSocket.accept();InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();// 接受請求參數Request request = new Request(is);request.parse();// 創建用于返回瀏覽器的對象Response response = new Response(os);response.setRequest(request);response.sendStaticResource();//關閉一次請求的socket,因為http請求就是采用短連接的方式socket.close();//如果請求地址是/shutdown 則關閉容器if(null != request){shutdown = request.getUrL().equals("/shutdown");}}catch (Exception e) {e.printStackTrace();continue;}}}public static void main(String[] args) {HttpServer server = new HttpServer();server.acceptWait();} }

2.創建Request類,獲取HTTP的請求頭所有信息并截取URL地址返回:

public class Request {private InputStream is;private String url;public Request(InputStream input) {this.is = input;}public void parse() {//從socket中讀取一個2048長度字符StringBuffer request = new StringBuffer(Response.BUFFER_SIZE);int i;byte[] buffer = new byte[Response.BUFFER_SIZE];try {i = is.read(buffer);}catch (IOException e) {e.printStackTrace();i = -1;}for (int j=0; j<i; j++) {request.append((char) buffer[j]);}//打印讀取的socket中的內容System.out.print(request.toString());url = parseUrL(request.toString());}private String parseUrL(String requestString) {int index1, index2;index1 = requestString.indexOf(' ');//看socket獲取請求頭是否有值if (index1 != -1) {index2 = requestString.indexOf(' ', index1 + 1);if (index2 > index1)return requestString.substring(index1 + 1, index2);}return null;}public String getUrL() {return url;} }

3.創建Response類,響應請求讀取文件并寫回到瀏覽器

public class Response {public static final int BUFFER_SIZE = 2048;//瀏覽器訪問D盤的文件private static final String WEB_ROOT ="D:";private Request request;private OutputStream output;public Response(OutputStream output) {this.output = output;}public void setRequest(Request request) {this.request = request;}public void sendStaticResource() throws IOException {byte[] bytes = new byte[BUFFER_SIZE];FileInputStream fis = null;try {//拼接本地目錄和瀏覽器端口號后面的目錄File file = new File(WEB_ROOT, request.getUrL());//如果文件存在,且不是個目錄if (file.exists() && !file.isDirectory()) {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 {//文件不存在,返回給瀏覽器響應提示,這里可以拼接HTML任何元素String retMessage = "<h1>"+file.getName()+" file or directory not exists</h1>";String returnMessage ="HTTP/1.1 404 File Not Found\r\n" +"Content-Type: text/html\r\n" +"Content-Length: "+retMessage.length()+"\r\n" +"\r\n" +retMessage;output.write(returnMessage.getBytes());}}catch (Exception e) {System.out.println(e.toString() );}finally {if (fis!=null)fis.close();}} }

四、擴展點

1.在WEB_INF文件夾下讀取web.xml解析,通過請求名找到對應的類名,通過類名創建對象,用反射來初始化配置信息,如welcome頁面,Servlet、servlet-mapping,filter,listener,啟動加載級別等。

2.抽象Servlet類來轉碼處理請求和響應的業務。發過來的請求會有很多,也就意味著我們應該會有很多的Servlet,例如:RegisterServlet、LoginServlet等等還有很多其他的訪問。可以用到類似于工廠模式的方法處理,隨時產生很多的Servlet,來滿足不同的功能性的請求。

3.使用多線程。本文的代碼是死循環,且只能有一個鏈接,而現實中的情況是往往會有很多很多的客戶端發請求,可以把每個瀏覽器的通信封裝到一個線程當中。

近期熱門文章

  • Java 最常見的 200+ 面試題

轉發朋友圈,是對我最大的支持。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的Tomcat工作原理及简单模拟实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。