官术网_书友最值得收藏!

1.2 Java Web開發的進化史

Web應用最初是指通過Web瀏覽器提供用戶界面的軟件系統,例如博客、網上購物、搜索引擎等。后來隨著RESTful Services、微服務等概念的興起,各種API也被包含在Web應用的范疇。

Web應用程序很簡單,僅由靜態或動態交互式的頁面組成。靜態頁面存儲在Web服務器的文件系統中,向所有訪問者顯示固定的內容。而動態頁面是由動態生成HTML的程序構建的。這種類型的Web應用程序可以根據不同用戶的請求提供各種不同的信息,目前主流的Web應用都是動態應用。

那么Web應用是如何工作的呢?通常,訪問一個靜態Web應用的步驟如下:

(1)用戶在瀏覽器中輸入URL。

(2)瀏覽器通過互聯網向Web服務器發送請求。

(3)Web服務器檢查請求,并基于請求服務器查找其本地存在的靜態頁面。

(4)Web服務器將響應發送到瀏覽器。

(5)瀏覽器獲取HTML及相關資源,最終渲染為完整的用戶可視化界面。

靜態Web應用的訪問過程如圖1-9所示。

圖1-9 靜態Web應用訪問過程示例

動態Web應用的內容根據用戶請求的差異而有所不同。在Java生態中,最初是以Servlet規范和JSP規范來支持動態Web開發的。對于這種類型的應用程序,Web服務器通過Servlet插件構建動態頁面,Servlet插件也稱為Servlet容器。動態Web應用的訪問過程如圖1-10所示。

圖1-10 動態Web應用的訪問過程

1.2.1 應用服務器

1.2.1.1 什么是應用服務器

在Java生態中,構建動態Web應用需要借助Servlet容器。提供Servlet容器功能的軟件就是應用服務器,而只能提供靜態資源訪問能力的軟件則被稱為Web服務器。Servlet容器也被稱為Servlet引擎,它為Java Servlet組件提供了非常高效的運行環境。

主流的應用服務器既可以作為Servlet容器,也可以充當Web服務器,這種將Servlet容器和Web服務器合二為一的方式在開發階段比較常見,便于開發團隊調試應用程序。但我們不建議在正式的生產環境中使用,因為兩種服務器的核心功能是完全不同的,應當各司其職。

目前,主流的部署方式是使用Web服務器處理所有的靜態請求,并通過特定的連接方式與應用服務器相連,將動態請求交由應用服務器處理,然后由Web服務器一并返回客戶端。

在當前的Java生態中,主流的Java應用服務器有Apache Tomcat、GlassFish、Jetty、JBoss等,下面將以Apache Tomcat為例,演示如何將Java Web應用部署到應用服務器,以供客戶端訪問。

1.2.1.2 Apache Tomcat下載和安裝

我們可以直接從官網下載Apache Tomcat,根據應用程序所使用的各種規范版本(比如JDK版本)的不同,其所需的Apache Tomcat版本也不一樣,請讀者參考Apache Tomcat的官方規范兼容文檔選擇正確的Apache Tomcat版本。在本書中筆者使用JDK 8進行開發,因此選擇了能支持JDK 8的最低兼容版本Apache Tomcat 9。

從官網下載壓縮包apache-tomcat-9.0.41.zip,并解壓縮,其目錄結構如圖1-11所示。

圖1-11 Apache Tomcat目錄結構

圖1-11中目錄的具體功能如下:

? bin:它用于存放批處理和shell腳本,例如Apache Tomcat的開始和停止的相關腳本,其內容如圖1-12所示。

圖1-12 Apache Tomcat bin目錄

? conf:它用于存放Apache Tomcat相關配置文件,其內容如圖1-13所示。

圖1-13 Apache Tomcat conf目錄

? lib:Apache Tomcat服務器依賴項目庫目錄,其中包含Apache Tomcat服務器運行環境所需的jar包,其內容如圖1-14所示。

圖1-14 Apache Tomcat lib目錄

? webapps:Apache Tomcat的默認Web應用程序部署目錄,即打包出的Java Web應用將會被放在該目錄,如圖1-15所示。

圖1-15 Apache Tomcat webapps目錄

在了解了各個目錄的基本功能以后,接下來我們驗證解壓后的Apache Tomcat是否可以正常工作。在命令行界面進入bin目錄運行startup.sh文件,對使用macOS的用戶來說,如果命令行界面出現類似“Cannot find ./catalina.sh”的錯誤,說明當前系統用戶對該目錄下的腳本沒有執行權限,需要運行以下命令對操作用戶賦權:

成功啟動Apache Tomcat的日志如圖1-16所示。

圖1-16 Tomcat啟動成功日志

如果Apache Tomcat以默認配置啟動,打開任意瀏覽器并輸入http://localhost:8080,就可以訪問Apache Tomcat的管理界面,如圖1-17所示。

圖1-17 Apache Tomcat的管理界面

1.2.2 青銅Servlet

從Java Web應用的發展歷程來看,Servlet技術是Java對Web應用的早期支持方式,當我們回過頭來看當年的Servlet和Java Web技術,就如同回顧人類歷史上的青銅時代。

1.2.2.1 什么是Servlet

Servlet是一個新造詞,是由server(服務器)和let(表示很小的東西的詞根)而來,因此,Servlet顧名思義表示一種小型的服務。

一個Servlet就是一個Java類,它主要用于擴展處理請求——響應應用服務器處理請求的能力。對于此類應用程序,Java Servlet技術定義了特定于HTTP的Servlet類。

我們可以將Servlet看成是在服務器上運行的Java應用程序編程接口(API),它攔截客戶端發出的請求并生成與之對應的響應。在Servlet規范中,javax.servlet包和javax.servlet.http包提供用于編寫Servlet的接口和類。

在Servlet容器中,一個Servlet是何時被創建又在何時被銷毀的呢?在Servlet規范中,諸如Servlet創建和Servlet銷毀之類的行為被稱為Servlet的生命周期。在了解Servlet生命周期之前,需要先簡單了解Servlet接口。

javax.servlet.servlet接口的定義如表1-1所示(未全部列出)。

表1-1 Servlet接口定義

Servlet的生命周期如圖1-18所示。

圖1-18 Servlet生命周期

下面介紹生命周期的5個步驟。

(1)加載Servlet類

當容器收到對Servlet的第一個請求時,類加載器會加載Servlet類。

(2)創建Servlet實例

容器在加載Servlet類后創建Servlet實例,Servlet實例在Servlet生命周期中只創建一次。

(3)調用init()方法

init()方法用于初始化Servlet。它是javax.servlet.Servlet接口的生命周期方法。容器在創建Servlet實例后只調用init()方法一次。

(4)調用Service()方法

Servlet容器在收到用戶請求時,會嘗試調用Servlet實例的service()方法。如果Servlet尚未被實例化,則執行步驟(1)~(3),再調用service()方法。

(5)調用destroy()方法

Servlet容器在刪除Servlet實例之前將調用該實例的destroy()方法。destroy()方法為服務器提供了清理資源(例如內存、線程等)的機會。

1.2.2.2 使用Servlet實現HelloWorld

首先,創建一個Servlet的項目,目前Maven的archetype已經不再支持最新版的Servlet規范,所以需要有一些前提準備。

創建新的項目可以通過Maven或IDE來直接創建,本節將演示如何使用IntelliJ IDEA來創建一個Servlet項目。

(1)在IntelliJ IDEA中選擇新建項目,其界面如圖1-19所示。

圖1-19 IntelliJ IDEA創建項目

(2)選擇從archetype創建項目,所選archetype類型為maven-archetype-webapp,然后單擊Next按鈕,其界面如圖1-20所示。

圖1-20 IntelliJ利用archetype創建項目

(3)輸入項目名servlet-demo,填寫項目路徑、GroupId、ArtifactId,再單擊Next按鈕即可,指定項目信息如圖1-21所示。

圖1-21 指定項目信息

項目創建成功,其結構如圖1-22所示。

圖1-22 Servlet項目結構

目前,Maven和Servlet的最新版存在兼容性問題,需要webapp/WEB-INF/web.xml文件做一些修改,由于其默認支持Servlet 2.3,所以讀者需要手動添加依賴,具體代碼如下:

基于Servlet 4規范創建Servlet程序有兩種方式,第一種是傳統的使用web.xml注冊的方式,第二種是新型的使用WebServlet注釋的方式,第一種方式的執行步驟如下。

第一步:實現Servlet類。實現Servlet有三種方式:實現Servlet接口、繼承GenericServlet類、繼承HttpServlet類。

本示例程序以繼承HttpServlet類的方式實現,示例代碼如下:

第二步:注冊Servlet。

編輯src/main/webapp/WEB-INF/web.xml文件即可注冊Servlet,代碼如下:

如上代碼所示,Servlet注冊信息主要有兩項內容:

? 通過<Servlet-name>標簽注冊com.broadview.servlet.OldServlet,并將其命名為oldDemo。

? 通過<url-pattern>標簽注冊訪問oldDemo Servlet的URL,即/old。

由上可知,注冊信息的主要目的是定義訪問URL與Servlet之間的映射關系。

第三步:編譯打包。

進入項目的根目錄,并運行打包命令:

命令運行完畢,項目的target目錄會產生一個名為servlet-demo.war的文件,將此文件復制到1.2.1.2節所安裝的Tomcat的webapps目錄下。

第四步:添加Tomcat的管理權限。

在啟動Tomcat之前還需要為Tomcat設置管理員權限,進入Tomcat的config目錄,打開tomcat-users.xml文件,在該文件中添加以下代碼:

第五步:啟動Tomcat。

進入Tomcat的bin目錄運行以下命令:

如果Tomcat安裝正常,Servlet項目編寫、編譯和打包無誤,則會出現Tomcat started的啟動日志。

下面驗證Servlet應用是否能夠正常啟動,打開瀏覽器輸入http://localhost:8080/,進入Tomcat的管理界面,如圖1-23所示,此界面有管理Web應用的功能,單擊Manager App按鈕,輸入在tomcat-users.xml中配置的用戶名和密碼,進入Tomcat Web應用的管理界面,如圖1-24所示。

圖1-23 Tomcat管理界面

圖1-24 Tomcat Web應用管理界面

從圖1-24可見servlet-demo項目顯示在應用程序列表中,單擊該項目鏈接,會跳轉到該項目的主頁界面,如圖1-25所示。

圖1-25 項目主頁界面

由于Servlet實現了doGet()方法,所以用戶可以通過http://localhost:8080/servlet-demo/old來訪問此Servlet,URL中的servlet-demo部分為context path,訪問servlet-demo項目下的所有API都需要包含此路徑。URL中結尾處的“old”的作用是,將當前請求轉發到指定的Servlet實例。

在瀏覽器中輸入http://localhost:8080/servlet-demo/old,就可以查看對應Servlet的輸出,如圖1-26所示。

圖1-26 Servlet的輸出

上面這種需要在web.xml中注冊Servlet的方式是早期的Servlet開發方式,下面是使用WebServlet注釋的方式創建Servlet的示例代碼。

再重新打包編譯并復制war文件到Tomcat的webapps目錄。通過http://localhost:8080/servlet-demo/new訪問新的Servlet,其效果如圖1-27所示。

圖1-27 新式Servlet輸出

這種新方式無需在web.xml中注冊Servlet,編程體驗更加簡潔優雅。但是無論如何Servlet的開發方式都是相對原始的,其開發效率很難滿足當前多變的復雜的業務需求。因此,業界發明了更多的新技術以滿足日益增長的用戶需求。

1.2.3 鉑金Spring MVC

正如1.2.2節中所述,Servlet技術無法滿足日益復雜的業務需求,市場自然就會出現可以填補這種需求空白的技術,因此Spring MVC應運而生。

1.2.3.1 什么是Spring MVC

在了解Spring MVC之前,先簡單介紹一下MVC。MVC是一種實現應用程序表現層的常用模式,此模式定義了不同的組件、組件的職責及不同組件之間的關系。MVC模式有三個概念:

? 模型(Model):模型表示業務數據及用戶上下文中應用程序的“狀態”,例如電商網站中的訂單、用戶、物流信息等都屬于模型的范疇。

? 視圖(View):以某種特定的方式向用戶展示數據,可以簡單地理解為用戶界面,也支持與用戶的交互。

? 控制器(Controller):控制器處理前端用戶發送的操作請求、與服務層交互、更新模型,并根據執行結果將用戶定向到相應的視圖。

Spring MVC模塊為MVC模式提供了全面支持,它結合MVC模式的所有優點和Spring的便利性,使用DispatcherServlet實現了前端控制器模式(Front Controller Pattern)。

圖1-28描述了Spring MVC的主要組件和請求處理的流程。其中,通用服務為各類組件提供各種工具,包括i18n、主題和文件上傳。它們的配置定義在DispatcherServlet的WebApplicationContext中。

圖1-28 Spring MVC處理流程

圖1-28中的關鍵組件介紹如下:

? Filter:過濾器適用于每個請求,下一節將介紹幾種常用的過濾器及其用途。

? DispatcherServlet:DispatcherServlet分析請求并調度到相應的控制器進行處理。

? Handler Mapping:將傳入的請求映射到相應的處理程序(Spring MVC控制器類中的方法)。自Spring 2.5以來,在大多數情況下不需要配置,因為Spring MVC將自動注冊一個處理程序映射的實現,該實現是基于class或方法級別的@RequestMapping注解。

? Handler Interceptor:在Spring MVC中,可以注冊處理程序的攔截器,以實現常見的檢查邏輯。

? Handler Exception Resolver:在Spring MVC中,程序異常解析器接口(在org.springframe.Web.servlet中定義)旨在處理程序在處理請求期間拋出的異常。解析程序通過設置特定的響應狀態代碼處理某些標準的Spring MVC異常。此外也可通過@ExceptionHandler注解來處理異常程序。

? View解析器:Spring MVC控制器方法通常會返回邏輯視圖,想要定位到真正的頁面,可以通過View解析器來實現。

? View:View可以是物理視圖也可以是模板,Spring MVC會解析邏輯視圖配置,返回一種Freemarker模板或thymelea模板,該模板用于將數據模型中的數據合并到模板中,從而生成標準的輸出文本,包括HTML、XML、Java源碼等。

1.2.3.2 使用Spring MVC實現HelloWorld

使用Spring MVC實現HelloWorld,與直接使用Servlet構建HelloWorld類似,需要先創建一個Web應用項目,具體步驟請參照1.2.2.2節。

然后,在pom.xml文件中添加相關依賴項,具體代碼如下:

與定義傳統Servlet一樣,Spring MVC需要在web.xml中定義Servlet映射,具體代碼如下:

根據上面代碼中定義的servlet-name,按照Spring MVC的規范創建相應的Spring Bean的定義文件springmvcDemo-servlet.xml,具體代碼如下:

下面,我們來創建一個DemoController類,并定義一個方法來處理用戶請求,具體代碼如下:

在上述代碼中,@RestController注解表明DemoController類是被Spring MVC托管的controller類,@RequestMapping注解定義了訪問Service的方式。參照1.2.2節中的步驟使用mvn命令將項目打包,再將編譯后的springmvc-demo.war文件復制到Tomcat的webapps目錄下,重新啟動Tomcat(如果Tomcat是一直運行的,且本身是可以熱加載的,則無需重啟),再從瀏覽器中輸入http://localhost:8080/springmvc-demo/mvcdemo訪問Spring MVC應用,運行效果如圖1-29所示。

圖1-29 Spring MVC的運行效果

相較于傳統的Servlet,Spring MVC代碼簡潔了許多,只是額外多了DispatchServlet的Spring Bean配置文件。Spring MVC的功能十分豐富,本章只是做了基本演示,其他細節知識,請讀者通過Spring官網探索。

1.2.4 王者Spring Boot

1.2.4.1 什么是Spring Boot

雖然Spring MVC相較于傳統Servlet已經相對簡化,但仍需要web.xml和相應的Spring Bean的配置,這些文件煩瑣而又不可缺,從廣大開發者的角度出發,如果可以進一步省略這些文件,不但可以減少代碼量,而且可以使代碼更加優雅整潔。所以Spring Boot正是秉承約定大于配置(Convention Over Configuration)的精神出現了。

Spring Boot的主要目標是簡化傳統Spring應用的開發過程。使用Spring Boot可以減少大量的配置文件,其內置的Servlet容器可以簡化應用的部署過程,簡潔易用的工具可以使開發者從重復性工作中得到解放。簡而言之,Spring Boot并非要替代Spring框架,而是要簡化基于Spring框架的開發工作。

本章只是簡要地介紹Spring Boot應用開發的便利性,第2章我們將借助實戰項目深入了解Spring Boot。

1.2.4.2 使用Spring Boot實現HelloWorld

首先,我們通過Spring Boot Initializr官網來創建一個簡單的Spring Boot項目。打開Spring Boot Initializr官網選擇合適的Spring Boot版本及所需要的依賴,就可以創建一個Spring Boot項目,Spring Boot項目創建界面如圖1-30所示。

圖1-30 Spring Boot項目創建界面

然后,將產生的項目文件導入IDE中,Spring Boot項目默認有一個Spring Boot啟動類,在本例中啟動類是SpringbootdemoApplication,該類的定義代碼如下:

再創建一個DemoController類,實現一個HelloWorld,具體代碼如下:

只需以上兩個簡單的類,一個基于Spring Boot的簡版Web Service就創建成功了,此外,該項目在開發階段可以直接從IDE運行,無需額外的打包和部署操作。因為Spring Boot內置了Servlet容器(默認為Tomcat),所以Spring Boot項目可以直接運行。在本例中直接運行SpringbootdemoApplication類的main()方法即可(此類為應用啟動類),在IDE中運行方式如圖1-31所示。

圖1-31 在IDE中運行Spring Boot項目

如果一切運行正常,那么該應用會默認監聽8080端口。在瀏覽器中輸入http://localhost:8080/bootdemo,驗證應用是否正常啟動,Spring Boot運行效果如圖1-32所示。

圖1-32 Spring Boot運行效果

相對于Servlet和Spring MVC,基于Spring Boot構建的應用從代碼到配置都做了極大的簡化。

本章逐一使用不同時期的主流技術進行開發,理解這些技術之間的差異性是成為一名合格程序員的基本功,深入研究技術背后的工作原理是程序員進階的必備手段。在本書的后續章節,我們將深入了解各個技術的實現細節,來理解其背后的工作原理。就全書而言,本章只是一場簡單的熱身運動,后續的精彩內容將為各位讀者一一呈現。

主站蜘蛛池模板: 南丰县| 新乐市| 镇平县| 滁州市| 红原县| 玉门市| 乌海市| 平舆县| 桐梓县| 轮台县| 沙田区| 洛南县| 澜沧| 淮南市| 鄂伦春自治旗| 巩留县| 克拉玛依市| 胶南市| 永修县| 明溪县| 闽侯县| 文成县| 栾城县| 安阳市| 建湖县| 哈密市| 金湖县| 敦化市| 文安县| 浮山县| 玉溪市| 都昌县| 宁陕县| 吴江市| 德兴市| 枣阳市| 台北县| 尤溪县| 鄢陵县| 靖州| 来安县|