[java][Servlet]Servlet 簡介-Servlet 到 Spring MVC 的簡化之路-Servlet/Tomcat/ Spring 之間的關係

[java][Servlet]Servlet 簡介-Servlet 到 Spring MVC 的簡化之路-Servlet/Tomcat/ Spring 之間的關係

溫習一下這個傳統的方式,jsp+JavaBeans,這種混合模式很虐心呀,jsp在裏面夾雜着,現在大家都直接搞前後端分離了。

注:Spring MVC這種方式,也早就不用了。

既然要搞一下商業軟件的破解什麼的,還是要溫習一下古老技術,不然破解起來有點喫力。

Servlet 教程

Servlet 爲創建基於 web 的應用程序提供了基於組件、獨立於平臺的方法,可以不受 CGI 程序的性能限制。Servlet 有權限訪問所有的 Java API,包括訪問企業級數據庫的 JDBC API。

本教程將講解如何使用 Java Servlet 來開發基於 web 的應用程序。

誰適合閱讀本教程?

本教程是專爲 Java 程序員設計的。在閱讀本教程之前,需要先了解 Java Servlet 框架和它的 API。學習完本教程後,您會發現自己已經達到使用 Java Servlet 的中等水平,後續您可以自行通過更深入的學習和實踐完成進階。

閱讀本教程前,您需要了解的知識:

在您開始閱讀本教程之前,最好對 Java 編程語言有一個很好的理解。如果您對 web 應用程序和互聯網如何工作的有基本的認識,將有助於您理解本教程。

Servlet 相關教程

  • Java 教程
  • Jsp 教程

Servlet 簡介

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、數據庫或其他軟件進行交互。

Servlet 架構

下圖顯示了 Servlet 在 Web 應用程序中的位置。

Servlet 架構

Servlet 任務

Servlet 執行以下主要任務:

  • 讀取客戶端(瀏覽器)發送的顯式的數據。這包括網頁上的 HTML 表單,或者也可以是來自 applet 或自定義的 HTTP 客戶端程序的表單。
  • 讀取客戶端(瀏覽器)發送的隱式的 HTTP 請求數據。這包括 cookies、媒體類型和瀏覽器能理解的壓縮格式等等。
  • 處理數據並生成結果。這個過程可能需要訪問數據庫,執行 RMI 或 CORBA 調用,調用 Web 服務,或者直接計算得出對應的響應。
  • 發送顯式的數據(即文檔)到客戶端(瀏覽器)。該文檔的格式可以是多種多樣的,包括文本文件(HTML 或 XML)、二進制文件(GIF 圖像)、Excel 等。
  • 發送隱式的 HTTP 響應到客戶端(瀏覽器)。這包括告訴瀏覽器或其他客戶端被返回的文檔類型(例如 HTML),設置 cookies 和緩存參數,以及其他類似的任務。

Servlet 包

Java Servlet 是運行在帶有支持 Java Servlet 規範的解釋器的 web 服務器上的 Java 類。

Servlet 可以使用 javax.servlet 和 javax.servlet.http 包創建,它是 Java 企業版的標準組成部分,Java 企業版是支持大型開發項目的 Java 類庫的擴展版本。

這些類實現 Java Servlet 和 JSP 規範。在寫本教程的時候,二者相應的版本分別是 Java Servlet 2.5 和 JSP 2.1。

Java Servlet 就像任何其他的 Java 類一樣已經被創建和編譯。在您安裝 Servlet 包並把它們添加到您的計算機上的 Classpath 類路徑中之後,您就可以通過 JDK 的 Java 編譯器或任何其他編譯器來編譯 Servlet。

下一步呢?

接下來,本教程會帶你一步一步地設置您的 Servlet 環境,以便開始後續的 Servlet 使用。因此,請繫緊您的安全帶,隨我們一起開始 Servlet 的學習之旅吧!相信您會很喜歡這個教程的。

Servlet 到 Spring MVC 的簡化之路

背景

Servlet和JSP是開發Java Web應用程序的兩種基本技術,Spring MVC是Spring框架中用於開發Web應用的一個模塊。相信大家也和我一樣,是從編寫Servelt和JSP開始,然後一步步向Spring MVC靠攏。那麼Spring MVC到底簡化了Servlet什麼地方,使Spring MVC成爲Web應用開發的首選框架呢,本文將會就這個方面進行探討。

Servlet簡介

什麼是Servlet

Servlet是一種基於Java語言,用於創建Web應用程序。在Servlet之前,CGI(通用網關接口)腳本語言作爲服務端編程語言很受歡迎,但是這門技術有很多的缺點:

  • CGI(通用網關接口) CGI即使可以讓服務器能夠調用外部程序,並將HTTP請求信息傳遞給外部程序處理,對於每一個請求,會啓動一個新的進程。

     

  • CGI技術的缺點

  1. 客戶端數量增加時,響應時間更多
  2. 每一個其請求,需要啓動一個新的進程,消耗大量的系統資源
  3. 使用平臺依賴語言,如:C、C++、Perl
  • Servlet

     

  • Servlet的優點

  1. 更好的性能:每個請求創建的是線程,而不是進程
  2. 可移植性:使用Java跨平臺語言
  3. 更強大:Servlet有JVM管理,不需要擔心內存泄露、溢出等

Servlet的演化

  • Servlet的基本目錄

    在tomcat/webapps目錄下創建上述目錄結構,所有HTML,靜態文件直接保存在應用程序目錄下,所有的Servlet類保存在web-inf/classe目錄或子目錄下,web.xml(部署描述符)文件保存在web-inf目錄下。

     

  • Servlet接口 在最基本的Servlet類中,需要實現Servlet接口定義的init()、servic()、destroy()、getServletConfig()和geServletInfo()方法,其中業務邏輯在service中編寫,在service方法中最常用的是通過PrintWriter對象進行內容的輸出。

  • 演進1:GenericServlet抽象類 實現Servlet接口的時候必須將所有的方法實現,即使方法中沒有任何代碼。在GenericServlet抽象類的幫助下,只需要重寫service方法即可。

  • 演進2:HttpServlet抽象類 HttpServlet覆蓋了GenericServlet類,將ServletRequest和ServletResponse對象分別封裝爲HttpServletRequest和HttpServletResponse對象。HttpServlet同時實現了service方法,在請求進來時,Web容器首先調用HttpServlet的service方法,並根據請求的類型調用doGet或doPost方法,搜易我們只需要覆蓋doGet()和goPost()方法即可。

演進3:JSP的加入

寫過Servlet的朋友應該知道,Servlet的最大缺點就是在Servlet類中編寫大量繁雜的HTML代碼,使得Java代碼與HTML代碼糅雜在一起,所以JSP應運而生。
JSP本質也是Servelt,然而其不需要編譯,JSP頁面是一個以.jsp擴展名的文本文件。簡單的JSP頁面在第一次請求後被翻譯爲(JSP名)_jsp的servlet,翻譯之後的Servelt可以看到:_jspInit(),_jspDestory(),_jspService()這樣的方法其實都是和Servlet相對應的。

演進4:Spring橫空出世

Spring提供了強大的控制反轉(IOC)和依賴注入(DI)功能,達到項目組件的解耦。

演進5:Spring Web模塊 - Spring MVC

學過Servlet的朋友應該知道,當要使用Servlet完成的複雜的功能時,需要編寫多個Servlet類,並且在web.xml進行註冊,這對於完成複雜的Web應用,代碼編寫會變得很複雜,開發成本也會很高。所以Spring提供了強大的Web開發框架Spring MVC。Spring MVC是Spring產品的一部分,享有Spring松耦合等所有優點。
Spring MVC是一個模型-視圖-控制器的Web框架,建立在前端控制器servlet(DispatcherServlet),它負責發送每個請求到合適的處理程序,使用視圖來返回響應結果。
Spring MVC的架構:

 

Spring web MVC框架提供了MVC(模型 - 視圖 - 控制器)架構和用於開發靈活和鬆散耦合的Web應用程序的組件。MVC模式導致應用程序的不同方面(輸入邏輯,業務邏輯和UI邏輯)分離,同時提供這些元素之間的鬆散耦合

  • 模型(Model):封裝了應用程序的數據,通常由POJO類組成
  • 視圖(View):負責渲染模型數據,一般來說它生成客戶端瀏覽器可以解釋HTML輸出
  • 控制器(Controller):負責處理用戶請求並構建適當的模型,並將其傳遞給視圖進行渲染

DispatcherServlet組件類 Spring MVC框架是圍繞DispatcherServlet設計的,它處理所有的請求和響應。Spring MVC DispatcherServlet的工作流程:

 

DispatcherServlet處理HTTP請求的工作流程

  1. 接受HTTP請求後,DispatcherServlet
  2. 會查詢HandlerMapping以調用相應的Controller(根據請求的url)
  3. Controller接受請求並根據請求的類型Get/Post調用相應的服務方法,服務方法進行相應的業務處理,並設置模型數據,最後將視圖名稱返回給DispatcherServlet
  4. DispatcherServlet根據返回的視圖名稱從ViewResolver獲取對應的視圖
  5. DispatcherServlet將模型數據傳遞到最終的視圖,並將視圖返回給瀏覽器。

總結

至此Servlet到Spring MVC的演化之路落下帷幕,只能感慨,技術的變更和迭代速度遠遠超乎我們的意料,我們只有不斷地學習,才能跟上時代的潮流。

Servlet/Tomcat/ Spring 之間的關係

0.基礎知識

在idea中打開servlet的源碼:

 

 

可以看見servlet就是一個接口;接口就是規定了一些規範,使得一些具有某些共性的類都能實現這個接口,從而都遵循某些規範。

有的人往往以爲就是servlet直接處理客戶端的http請求,其實並不是這樣,servlet並不會去監聽8080端口;直接與客戶端打交道是“容器”,比如常用的tomcat。

客戶端的請求直接打到tomcat,它監聽端口,請求過來後,根據url等信息,確定要將請求交給哪個servlet去處理,然後調用那個servlet的service方法,service方法返回一個response對象,tomcat再把這個response返回給客戶端。

 

 

1. Servlet的生命週期

 

從創建到毀滅:

 

  1. 調用 init() 方法初始化
  2. 調用 service() 方法來處理客戶端的請求
  3. 調用 destroy() 方法釋放資源,標記自身爲可回收
  4. 被垃圾回收器回收

 

由上面可以看見,servlet的init方法和destroy方法,一般容器調用這兩個方法之間的過程,就叫做servlet的生命週期。

調用的整個過程就如上圖所示。

當請求來容器第一次調用某個servlet時,需要先初始化init(),

但當某個請求再次打到給servlet時,容器會起多個線程同時訪問一個servlet的service()方法。

 

 

由此可以看出,多個客戶訪問同一service()方法,會涉及線程安全的問題。

 

如果service()方法沒有訪問Servlet的成員變量也沒有訪問全局的資源比如靜態變量、文件、數據庫連接等,而是隻使用了當前線程自己的資源,比如非指向全局資源的臨時變量、request和response對象等。該方法本身就是線程安全的,不必進行任何的同步控制。

如果service()方法訪問了Servlet的成員變量,但是對該變量的操作是隻讀操作,該方法本身就是線程安全的,不必進行任何的同步控制。

如果service()方法訪問了Servlet的成員變量,並且對該變量的操作既有讀又有寫,通常需要加上同步控制語句。

如果service()方法訪問了全局的靜態變量,如果同一時刻系統中也可能有其它線程訪問該靜態變量,如果既有讀也有寫的操作,通常需要加上同步控制語句。

如果service()方法訪問了全局的資源,比如文件、數據庫連接等,通常需要加上同步控制語句。

 

 

面試問題:Servlet如何同時處理多個請求訪問? 

單實例多線程: 主要是請求來時,會由線程調度者從線程池李取出來一個線程,來作爲響應線程。這個線程可能是已經實例化的,也可能是新創建的。


Servlet容器默認是採用單實例多線程的方式處理多個請求的: 
1.當web服務器啓動的時候(或客戶端發送請求到服務器時),Servlet就被加載並實例化(只存在一個Servlet實例); 
2.容器初始化化Servlet主要就是讀取配置文件(例如tomcat,可以通過servlet.xml的設置線程池中線程數目,初始化線程池通過web.xml,初始化每個參數值等等。 
3.當請求到達時,Servlet容器通過調度線程(Dispatchaer Thread) 調度它管理下線程池中等待執行的線程(Worker Thread)給請求者; 
4.線程執行Servlet的service方法; 
5.請求結束,放回線程池,等待被調用; 
(注意:避免使用實例變量(成員變量),因爲如果存在成員變量,可能發生多線程同時訪問該資源時,都來操作它,照成數據的不一致,因此產生線程安全問題)

 

從上面可以看出: 
第一:Servlet單實例,減少了產生servlet的開銷; 
第二:通過線程池來響應多個請求,提高了請求的響應時間; 
第三:Servlet容器並不關心到達的Servlet請求訪問的是否是同一個Servlet還是另一個Servlet,直接分配給它一個新的線程;如果是同一個Servlet的多個請求,那麼Servlet的service方法將在多線程中併發的執行; 
第四:每一個請求由ServletRequest對象來接受請求,由ServletResponse對象來響應該請求;

 

 

 

 

 2. Spring 

 

 任何Spring Web的entry point,都是servlet。

 

大名頂頂的spring框架已經風靡多時,一個事物的出現和流行都是會有原因的,那麼爲什麼spring 框架會出現呢?原因就是爲了簡化java開發

spring的核心就是通過依賴注入、面向切面編程aop、和模版技術,解耦業務與系統服務,消除重複代碼。藉助aop,可以將遍佈應用的關注點(如事物和安全)從它們的應用對象中解耦出來。

 

 

 Spring 中的Bean

 1) POJO和JavaBean的區別 : 

"Plain Ordinary Java Object",簡單普通的java對象。主要用來指代那些沒有遵循特定的java對象模型,約定或者框架的對象。

POJO的內在含義是指那些:
有一些private的參數作爲對象的屬性,然後針對每一個參數定義get和set方法訪問的接口。
沒有從任何類繼承、也沒有實現任何接口,更沒有被其它框架侵入的java對象。

JavaBean 是一種JAVA語言寫成的可重用組件。JavaBean符合一定規範編寫的Java類,不是一種技術,而是一種規範。大家針對這種規範,總結了很多開發技巧、工具函數。符合這種規範的類,可以被其它的程序員或者框架使用。它的方法命名,構造及行爲必須符合特定的約定:

  1. 所有屬性爲private。

  2. 這個類必須有一個公共的缺省構造函數。即是提供無參數的構造器。

  3. 這個類的屬性使用getter和setter來訪問,其他方法遵從標準命名規範。

  4. 這個類應是可序列化的。實現serializable接口。

因爲這些要求主要是靠約定而不是靠實現接口,所以許多開發者把JavaBean看作遵從特定命名約定的POJO。

 

spring中,應用對西那個生存於spring容器中,spring 容器創建對象,裝配它們,管理它們的整個生命週期。spring容器通過依賴注入,管理構成應用的組件,它會創建相互協作的組件之間的關聯。

2) Bean的生命週期

 

 

 Spring MVC

 

 

 

 

 Spring MVC的運行流程:

 

 

 

 

參考:

https://www.runoob.com/servlet/servlet-intro.html

https://juejin.im/post/6844903570681135117

https://www.cnblogs.com/shawshawwan/p/9002126.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章