走進JavaWeb技術世界6:Tomcat5整體架構剖析

本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到個人倉庫裏查看html

https://github.com/h2pl/Java-...

喜歡的話麻煩點下Star哈前端

文章首發於個人我的博客:java

www.how2playlife.com

本文是微信公衆號【Java技術江湖】的《走進JavaWeb技術世界》其中一篇,本文部份內容來源於網絡,爲了把本文主題講得清晰透徹,也整合了不少我認爲不錯的技術博客內容,引用其中了一些比較好的博客文章,若有侵權,請聯繫做者。python

該系列博文會告訴你如何從入門到進階,從servlet到框架,從ssm再到SpringBoot,一步步地學習JavaWeb基礎知識,並上手進行實戰,接着瞭解JavaWeb項目中常常要使用的技術和組件,包括日誌組件、Maven、Junit,等等內容,以便讓你更完整地瞭解整個JavaWeb技術體系,造成本身的知識框架。爲了更好地總結和檢驗你的學習成果,本系列文章也會提供每一個知識點對應的面試題以及參考答案。mysql

若是對本系列文章有什麼建議,或者是有什麼疑問的話,也能夠關注公衆號【Java技術江湖】聯繫做者,歡迎你參與本系列博文的創做和修訂。android

文末贈送8000G的Java架構師學習資料,須要的朋友能夠到文末了解領取方式,資料包括Java基礎、進階、項目和架構師等免費學習資料,更有數據庫、分佈式、微服務等熱門技術學習視頻,內容豐富,兼顧原理和實踐,另外也將贈送做者原創的Java學習指南、Java程序員面試指南等乾貨資源)
<!-- more -->git

jsp做爲Servlet技術的擴展,常常會有人將jsp和Servlet搞混。本文,將爲你們帶來servlet和jsp的區別,但願對你們有所幫助。程序員

servlet和jsp的區別

一、Servlet在Java代碼中能夠經過HttpServletResponse對象動態輸出HTML內容。github

二、JSP是在靜態HTML內容中嵌入Java代碼,而後Java代碼在被動態執行後生成HTML內容。面試

servlet和jsp各自的特色

一、Servlet雖然可以很好地組織業務邏輯代碼,可是在Java源文件中,由於是經過字符串拼接的方式生成動態HTML內容,這樣就容易致使代碼維護困難、可讀性差。

二、JSP雖然規避了Servlet在生成HTML內容方面的劣勢,可是在HTML中混入大量、複雜的業務邏輯。

經過MVC雙劍合璧

JSP和Servlet都有自身的適用環境,那麼有沒有什麼辦法可以讓它們發揮各自的優點呢?答案是肯有的,MVC模式就可以完美解決這一問題。

MVC模式,是Model-View-Controller的簡稱,是軟件工程中的一種軟件架構模式,分爲三個基本部分,分別是:模型(Model)、視圖(View)和控制器(Controller):

Controller——負責轉發請求,對請求進行處理

View——負責界面顯示

Model——業務功能編寫(例如算法實現)、數據庫設計以及數據存取操做實現

在JSP/Servlet開發的軟件系統中,這三個部分的描述以下所示:

229cf9ff5b1729eaf408fac56238eeb3_hd

一、Web瀏覽器發送HTTP請求到服務端,而後被Controller(Servlet)獲取並進行處理(例如參數解析、請求轉發)

二、Controller(Servlet)調用核心業務邏輯——Model部分,得到結果

三、Controller(Servlet)將邏輯處理結果交給View(JSP),動態輸出HTML內容

四、動態生成的HTML內容返回到瀏覽器顯示

MVC模式在Web開發中有很大的優點,它完美規避了JSP與Servlet各自的缺點,讓Servlet只負責業務邏輯部分,而不會生成HTML代碼;同時JSP中也不會充斥着大量的業務代碼,這樣能大提升了代碼的可讀性和可維護性。

JavaWeb基礎知識

1、Servlet 是什麼?

Java Servlet 是運行在 Web 服務器或應用服務器上的程序,它是做爲來自 Web 瀏覽器或其餘 HTTP 客戶端的請求和 HTTP 服務器上的數據庫或應用程序之間的中間層。

使用 Servlet,您能夠收集來自網頁表單的用戶輸入,呈現來自數據庫或者其餘源的記錄,還能夠動態建立網頁。

Java Servlet 一般狀況下與使用 CGI(Common Gateway Interface,公共網關接口)實現的程序能夠達到殊途同歸的效果。可是相比於 CGI,Servlet 有如下幾點優點:

  • 一、性能明顯更好。
  • 二、Servlet 在 Web 服務器的地址空間內執行。這樣它就沒有必要再建立一個單獨的進程來處理每一個客戶端請求。
  • 三、Servlet 是獨立於平臺的,由於它們是用 Java 編寫的。
  • 四、服務器上的 Java 安全管理器執行了一系列限制,以保護服務器計算機上的資源。所以,Servlet 是可信的。
  • 五、Java 類庫的所有功能對 Servlet 來講都是可用的。它能夠經過 sockets 和 RMI 機制與 applets、數據庫或其餘軟件進行交互。

2、Servlet的生命週期

Servlet 生命週期可被定義爲從建立直到毀滅的整個過程。如下是 Servlet 遵循的過程:

  • 一、Servlet 經過調用 init () 方法進行初始化。
  • 二、Servlet 調用 service() 方法來處理客戶端的請求。
  • 三、Servlet 經過調用 destroy() 方法終止(結束)。
  • 四、最後,Servlet 是由 JVM 的垃圾回收器進行垃圾回收的。

init() 方法

init 方法被設計成只調用一次。它在第一次建立 Servlet 時被調用,在後續每次用戶請求時再也不調用。所以,它是用於一次性初始化,就像 Applet 的 init 方法同樣。

Servlet 建立於用戶第一次調用對應於該 Servlet 的 URL 時,可是您也能夠指定 Servlet 在服務器第一次啓動時被加載。

service() 方法

service() 方法是執行實際任務的主要方法。Servlet 容器(即 Web 服務器)調用 service() 方法來處理來自客戶端(瀏覽器)的請求,並把格式化的響應寫回給客戶端。

每次服務器接收到一個 Servlet 請求時,服務器會產生一個新的線程並調用服務。service() 方法檢查 HTTP 請求類型(GET、POST、PUT、DELETE 等),並在適當的時候調用 doGet、doPost、doPut,doDelete 等方法。

 destroy() 方法

destroy() 方法只會被調用一次,在 Servlet 生命週期結束時被調用。destroy() 方法可讓您的 Servlet 關閉數據庫鏈接、中止後臺線程、把 Cookie 列表或點擊計數器寫入到磁盤,並執行其餘相似的清理活動。

在調用 destroy() 方法以後,servlet 對象被標記爲垃圾回收。

 示例

執行後:

之後繼續請求時:

可見,就緒請求時只有service()方法執行!

相關面試題

怎樣理解Servlet的單實例多線程?**

不一樣的用戶同時對同一個業務(如註冊)發出請求,那這個時候容器裏產生的有是幾個servlet實例呢?

答案是:只有一個servlet實例。一個servlet是在第一次被訪問時加載到內存並實例化的。一樣的業務請求共享一個servlet實例。不一樣的業務請求通常對應不一樣的servlet。

因爲Servlet/JSP默認是以多線程模式執行的,因此,在編寫代碼時須要很是細緻地考慮多線程的安全性問題。

JSP的中存在的多線程問題:

當客戶端第一次請求某一個JSP文件時,服務端把該JSP編譯成一個CLASS文件,並建立一個該類的實例,而後建立一個線程處理CLIENT端的請求。若是有多個客戶端同時請求該JSP文件,則服務端會建立多個線程。每一個客戶端請求對應一個線程。以多線程方式執行可大大下降對系統的資源需求,提升系統的併發量及響應時間。

對JSP中可能用的的變量說明以下:

實例變量: 實例變量是在堆中分配的,並被屬於該實例的全部線程共享,因此不是線程安全的。

JSP系統提供的8個類變量

JSP中用到的OUT,REQUEST,RESPONSE,SESSION,CONFIG,PAGE,PAGECONXT是線程安全的(由於每一個線程對應的request,respone對象都是不同的,不存在共享問題),APPLICATION在整個系統內被使用,因此不是線程安全的。

局部變量: 局部變量在堆棧中分配,由於每一個線程都有它本身的堆棧空間,因此是線程安全的

靜態類: 靜態類不用被實例化,就可直接使用,也不是線程安全的

外部資源: 在程序中可能會有多個線程或進程同時操做同一個資源(如:多個線程或進程同時對一個文件進行寫操做).此時也要注意同步問題.

Servlet單實例多線程機制:

Servlet採用多線程來處理多個請求同時訪問。servlet依賴於一個線程池來服務請求。線程池其實是一系列的工做者線程集合。Servlet使用一個調度線程來管理工做者線程。

當容器收到一個Servlet請求,調度線程從線程池中選出一個工做者線程,將請求傳遞給該工做者線程,而後由該線程來執行Servlet的service方法。

當這個線程正在執行的時候,容器收到另一個請求,調度線程一樣從線程池中選出另外一個工做者線程來服務新的請求,容器並不關心這個請求是否訪問的是同一個Servlet.當容器同時收到對同一個Servlet的多個請求的時候,那麼這個Servlet的service()方法將在多線程中併發執行。

Servlet容器默認採用單實例多線程的方式來處理請求,這樣減小產生Servlet實例的開銷,提高了對請求的響應時間,對於Tomcat能夠在server.xml中經過<Connector>元素設置線程池中線程的數目。 

如何開發線程安全的Servlet

一、實現 SingleThreadModel 接口

該接口指定了系統如何處理對同一個Servlet的調用。若是一個Servlet被這個接口指定,那麼在這個Servlet中的service方法將不會有兩個線程被同時執行,固然也就不存在線程安全的問題。這種方法只要將前面的Concurrent Test類的類頭定義更改成:

<pre>Public class Concurrent Test extends HttpServlet implements SingleThreadModel {
…………
} </pre>

同步對共享數據的操做

使用synchronized 關鍵字能保證一次只有一個線程能夠訪問被保護的區段

避免使用實例變量

本實例中的線程安全問題是由實例變量形成的,只要在Servlet裏面的任何方法裏面都不使用實例變量,那麼該Servlet就是線程安全的。

1) Struts2的Action是原型,非單實例的;會對每個請求,產生一個Action的實例來處理

Struts1 Action是單實例的

mvc的controller也是如此。所以開發時要求必須是線程安全的,由於僅有Action的一個實例來處理全部的請求。單例策略限制了Struts1 Action能做的事,而且要在開發時特別當心。Action資源必須是線程安全的或同步的。

2) Struts1的Action,Spring的Ioc容器管理的bean 默認是單實例的.

Spring的Ioc容器管理的bean 默認是單實例的。

Struts2 Action對象爲每個請求產生一個實例,所以沒有線程安全問題。(實際上,servlet容器給每一個請求產生許多可丟棄的對象,而且不會致使性能和垃圾回收問題)。

當Spring管理Struts2的Action時,bean默認是單實例的,能夠經過配置參數將其設置爲原型。(scope="prototype )

5、servlet與jsp的區別

1.jsp經編譯後就變成了Servlet.(JSP的本質就是Servlet,JVM只能識別java的類,不能識別JSP的代碼,Web容器將JSP的代碼編譯成JVM可以識別的java類)

2.jsp更擅長表現於頁面顯示,servlet更擅長於邏輯控制.

3.Servlet中沒有內置對象,內置對象都是必須經過HttpServletRequest對象,HttpServletResponse對象以及HttpServlet對象獲得.Jsp是Servlet的一種簡化,使用Jsp只須要完成程序員須要輸出到客戶端的內容,Jsp中的Java腳本如何鑲嵌到一個類中,由Jsp容器完成。而Servlet則是個完整的Java類,這個類的Service方法用於生成對客戶端的響應。

4.對於靜態HTML標籤,Servlet都必須使用頁面輸出流逐行輸出

參考文章

https://www.w3cschool.cn/serv...
https://blog.csdn.net/qq_1978...
https://blog.csdn.net/qiuhuan...
https://blog.csdn.net/zt15732...
https://blog.csdn.net/android...

微信公衆號

我的公衆號:黃小斜

黃小斜是跨考軟件工程的 985 碩士,自學 Java 兩年,拿到了 BAT 等近十家大廠 offer,從技術小白成長爲阿里工程師。

做者專一於 JAVA 後端技術棧,熱衷於分享程序員乾貨、學習經驗、求職心得和程序人生,目前黃小斜的CSDN博客有百萬+訪問量,知乎粉絲2W+,全網已有10W+讀者。

黃小斜是一個斜槓青年,堅持學習和寫做,相信終身學習的力量,但願和更多的程序員交朋友,一塊兒進步和成長!

原創電子書:
關注危險公衆號【黃小斜】後回覆【原創電子書】便可領取我原創的電子書《菜鳥程序員修煉手冊:從技術小白到阿里巴巴Java工程師》這份電子書總結了我2年的Java學習之路,包括學習方法、技術總結、求職經驗和麪試技巧等內容,已經幫助不少的程序員拿到了心儀的offer!

程序員3T技術學習資源: 一些程序員學習技術的資源大禮包,關注公衆號後,後臺回覆關鍵字 「資料」 便可免費無套路獲取,包括Java、python、C++、大數據、機器學習、前端、移動端等方向的技術資料。

技術公衆號:Java技術江湖

若是你們想要實時關注我更新的文章以及分享的乾貨的話,能夠關注個人微信公衆號【Java技術江湖】

這是一位阿里 Java 工程師的技術小站。做者黃小斜,專一 Java 相關技術:SSM、SpringBoot、MySQL、分佈式、中間件、集羣、Linux、網絡、多線程,偶爾講點Docker、ELK,同時也分享技術乾貨和學習經驗,致力於Java全棧開發!

(關注公衆號後回覆」Java「便可領取 Java基礎、進階、項目和架構師等免費學習資料,更有數據庫、分佈式、微服務等熱門技術學習視頻,內容豐富,兼顧原理和實踐,另外也將贈送做者原創的Java學習指南、Java程序員面試指南等乾貨資源)

Java工程師必備學習資源: 一些Java工程師經常使用學習資源,關注公衆號後,後臺回覆關鍵字 「Java」 便可免費無套路獲取。

個人公衆號

相關文章
相關標籤/搜索