- Struts2技術內幕:深入解析Struts架構設計與實現原理
- 陸舟
- 97字
- 2018-12-31 20:03:41
第一部分 知識準備篇
對任何事物的研究,總是需要由表及里、由淺入深地進行。作為本書研究對象的Struts2,是一個Web開發框架。因而在本書的開篇,我們試圖向讀者闡述一些Web開發的基本概念以及開發框架的學習方法。這些內容不僅是全書的精神綱領,也是我們進行后續討論的基礎核心。從這一部分的篇名“知識準備篇”可以看出,本篇的主要目的是為之后我們深入研究框架的實現機理打好堅實的理論基礎。
“工欲善其事,必先利其器”。在本書的第1章,我們將首先為讀者介紹搭建Struts2開發環境的步驟。一個好的開發環境,是進行框架研究的必要條件。尤其是當我們需要對一個開源框架進行源代碼級別的分析時,好的開發環境就猶如一把利劍,能夠為我們掃清所有的障礙。除了介紹環境搭建和源碼調試的具體方法之外,我們在第1章中還將給出獲取Struts2相關資料的途徑和方法,并對Struts2項目的結構做初步的介紹。
面對紛繁復雜的框架,有的讀者或許已經迷失其中,有的讀者或許已經精通使用這些框架的方法并總結出一些行之有效的最佳實踐。本書的第2章,我們試圖帶領讀者去探尋日常開發中最為本質的問題:什么是面向對象的概念?什么是框架?我們為什么要引入框架進行編程?在解決這些根本問題的過程中,我們也會同時給出一系列Web開發模式和Web開發過程中的最佳實踐,并以此為基礎總結出Web開發中可能遇到的主要問題。在第2章的最后,我們還試圖總結出正確學習開源框架的方法,這些方法不僅能夠幫助那些迷茫于框架之中的程序員找到正確的方向,同時對那些有一定經驗的程序員也有相當的借鑒作用。
在了解了框架存在的意義之后,本書的第3章將正式揭開Struts2的神秘面紗,并從宏觀上講述Struts2作為一個表示層框架是如何解決Web開發中的種種問題的。第3章的內容將涵蓋Struts2的方方面面,從Struts2的歷史發展、Struts2的外部環境、Struts2的宏觀運行主線、Struts2的微觀構成等不同的角度,為讀者介紹Struts2的概況。
本篇中所有內容的側重點,都將圍繞著“方法論”這三個字展開。因為本書的主旨不僅僅是研究Struts2這個框架本身,更是想通過對Struts2的研究,總結出一套完整的并且行之有效的Web開發的經驗和方法。所謂“授人以魚不如授人以漁”,希望讀者在閱讀本書的過程中,始終能夠站在一個比Struts2本身更加高的高度來看待整個Web開發,這樣才能在不斷發展的歷史洪流中立于不敗之地。
第1章 厲兵秣馬—-開發環境準備
1.1 準備源代碼閱讀環境
在開發與分析任何一個開源框架之前,都需要安裝與配置基本的開發環境和源代碼的閱讀環境。這一系列內容將包括:安裝與配置JDK、安裝開發調試IDE、安裝與配置Web服務器、搭建開發調試環境等。
1.1.1 安裝與配置JDK
Struts2的運行環境要求Java 5以上的版本,所以JDK的版本必須為1.5或者1.5以上。打開http://www.oracle.com/technetwork/java/javase/downloads/index.html頁面,我們可以下載到最新的JDK安裝程序,下載頁面如圖1-1所示。本書所有的示例代碼都運行在JDK 1.6之上,大家可以下載這個版本的JDK運行本書中的所有代碼示例。

圖1-1 JDK下載首頁
安裝完JDK后,需要正確配置Java運行時必需的環境變量值,它們是:JAVA_HOME、CLASSPATH和PATH。無論是什么操作系統,都能夠支持多個JDK版本的共存,讀者可以根據應用程序的實際需求對不同的JDK版本進行管理。
正確管理JDK版本的方式,是在JVM運行時指定JDK版本對應的環境變量。為了方便起見,我們往往為操作系統本身指定一個系統級別的環境變量。例如,Windows平臺上的系統環境變量可以在“系統屬性”的“高級”選項卡中找到,并在其中配置JAVA_HOME、PATH和CLASSPATH值。圖1-2是Windows XP操作系統中為系統添加CLASSPATH環境變量的例子。

圖1-2 Windows XP上配置CLASSPATH
多JRE共存時的版本管理
Java語言對于運行環境的管理比較寬松,在一個操作系統中可以同時運行多個Java程序的進程,每個Java進程所依賴的JRE版本也可以各不相同。當某一個Java進程啟動時,操作系統會依次按照Java啟動進程的當前目錄、當前目錄的父目錄、PATH值中所指定的目錄進行JRE尋址,找到第一個返回的JRE版本并運行。因此,一個簡單而有效的指定JRE尋址的方式是在啟動Java進程的腳本中通過指定當前運行程序的PATH值來定制特定版本的JRE的執行環境,從而達到對不同版本的JRE進行管理的目的。
JRE管理和CLASSPATH的加載順序問題是Java開發中最為基本的問題,它牽涉的是Java程序所依賴的最為基本的底層環境的配置。尤其是當一個應用程序運行在一個高級的商業應用服務器如Websphere或Weblogic之上時,我們應該密切關注程序的JRE運行參數和版本以及CLASSPATH的加載順序(先加載優先原則),因為這些商業應用服務器往往有自定義的JRE管理機制和CLASSPATH的加載方式,而這兩大內容,也將直接決定Web應用的運行特征。因此,在商用服務器中,我們往往通過自行修改服務器的啟動腳本來設定服務器運行所依賴的JAR版本和Library加載方式(在某些服務器中,可以通過控制臺進行配置)。
安裝并配置完成后,我們可以在命令行窗口中輸入java -version命令來檢測一下當前的JDK運行版本。如果配置完全正確,當前客戶端的JRE運行版本會顯示出來,如圖1-3所示。

圖1-3 JDK安裝成功
1.1.2 安裝Eclipse與源碼調試
在成功安裝和配置JDK后,我們還需要安裝進行Java開發調試的IDE。目前比較常用的Java開發IDE主要有Eclipse和NetBeans等,讀者可以任意選擇自己習慣的IDE作為開發工具。在本書中,我們以Eclipse為例,著重介紹在Eclipse中開發與調試源碼的方法。讀者也可以舉一反三,在其他IDE中做相應的嘗試。
Eclipse是一個界面友好的開源IDE,并支持成千上萬種不同的插件,為我們進行代碼分析和源碼調試提供了極大的便利。我們可以在Eclipse的官方網站(http://www. eclipse.org/)找到Eclipse的各個版本并下載安裝。
本書不會對Eclipse的使用細節進行詳細介紹,不過為了幫助讀者更好地進行開源框架的研究,尤其是對開源框架源碼的解讀,我們在本章中將陸續給出一些結合Eclipse進行源碼閱讀的方法和最佳實踐。相信這些方法對各個層次的讀者都會有一定的啟示。
在本節中,我們將首先列出一些Eclipse IDE中常用的快捷鍵(參見圖1-4、圖1-5和圖1-6),這些快捷鍵在進行源碼分析時非常有用。

圖1-4 在Eclipse中使用Ctrl+Shift+T

圖1-5 在Eclipse中使用Ctrl+T

圖1-6 在Eclipse中使用Ctrl+ Shift + G
Ctrl+Shift+T—根據類名查找相應的類
Ctrl+T—選中某個類或方法,使用此快捷鍵能夠查看類或方法的組織結構
Ctrl+Shift+G—選中某個類或方法,使用此快捷鍵能夠查找所有調用類或者方法的出處
快捷鍵是日常開發調試中最為仰仗的一個技巧。Eclipse中的快捷鍵可謂博大精深,我們在這里不再一一列舉。讀者可以在實際開發中不斷摸索并牢記這些快捷鍵,因為它們也是日常開發中必不可少的一部分。讀者也可參照Eclipse中的這些快捷鍵,在其他的IDE中找到相應的快捷鍵設置。
1.1.3 安裝與配置Web服務器
本書所涉及的絕大多數內容都屬于Web開發的相關范疇,因而在JDK和Eclipse安裝完成之后,我們需要緊接著安裝Web服務器用以提供Web程序的運行環境。
在眾多的Web應用服務器中,Apache開源社區的Tomcat是最常用的Web服務器之一,讀者可以在http://tomcat.apache.org找到各個版本的Tomcat服務器,本書以Tomcat 6.028為例,請大家下載適合自己的版本并安裝。
安裝完成后,可以在Tomcat安裝目錄下的bin目錄中找到運行Tomcat的命令,運行成功的示意圖如圖1-7所示。
另外一款非常流行的輕量級的Web應用服務器是Jetty。相對于Tomcat來說,Jetty具有無須安裝(其API以一組JAR包的形式發布)、速度更快等特點,成為當前眾多程序員進行Web開發調試的首選。在1.1.4節中,我們將結合Eclipse IDE為大家講解使用Jetty進行Web開發和調試的過程。

圖1-7 Tomcat安裝成功
1.1.4 在Eclipse中使用Jetty搭建Web開發環境
在Eclipse IDE中建立了一個Web項目后,我們可以通過引入Jetty搭建起一個不依賴任何插件的Web開發調試環境。使用Jetty搭建Web開發環境的基本步驟如下。
1.1.4.1 構建項目的基本目錄結構
搭建Web開發調試環境的第一個步驟是建立一個Web項目的基本目錄結構,如圖1-8所示。

圖1-8 Web項目的基本目錄結構
這里簡單解釋一下這些基本目錄結構的作用:
src(source folder)—存放所有的Java源代碼
conf(source folder)—存放所有的配置文件
test(source folder)—存放所有的Java測試代碼和調試代碼
web—Web項目的根目錄,其子目錄WEB-INF以及classes和lib是構成Web項目所必需的基本結構
lib—存放JAR包,但是這里存放的JAR文件僅在開發調試時使用
讀者可以根據項目的實際情況,創建適合于項目自身需求的目錄結構,并導入到Eclipse中使之成為Eclipse項目,之后我們的開發調試都將圍繞著Web項目的目錄結構展開。
目前,使用Maven作為開發環境進行構建的開發人員越來越多。Maven是一個非常優秀的項目構建和項目管理的工具。我們在這里并未介紹Maven的主要原因在于Maven的使用需要額外的開發環境搭建,甚至可能需要編寫符合項目自身條件的POM文件,而這些內容并非本書介紹的重點。因而,對其有興趣的讀者可以自行使用Maven進行項目構建,而使用Maven進行項目構建和JAR文件依賴關系的管理,也是我們向讀者推薦的做法。
1.1.4.2 引入Jetty服務器
搭建Web開發環境的第二步,是引入Jetty服務器作為我們的Web容器。引入Jetty的方法非常簡單,只需要將Jetty服務器相關的JAR文件加入到項目的CLASSPATH中即可。整個過程如圖1-9所示。

圖1-9 將構成Jetty服務器必要的JAR包加到CLASSPATH中
這個步驟完成之后,我們就可以將Jetty作為我們的Web容器提供者。在這里,我們可以看到Jetty服務器相對于其他Web服務器的一個重要區別在于它不需要額外安裝,引入Jetty的過程只不過是將幾個JAR文件加入到CLASSPATH中而已。這樣一來,也就不存在平臺依賴性和兼容性問題了。
1.1.4.3 啟動Jetty進行開發調試
啟動Jetty服務器進行基本的Web開發調試的步驟非常簡單,只需要在項目中編寫一個JettyStarter的Java類,并將這個類作為一個基本的Application執行即可。JettyStarter的源碼如代碼清單1-1所示。
代碼清單1-1 JettyStarter.java
package runtime; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Server; import org.mortbay.jetty.nio.SelectChannelConnector; import org.mortbay.jetty.webapp.WebAppContext; /** * Jetty Server 啟動類 * * @author */ public class JettyStarter { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { long begin = System.currentTimeMillis(); Connector connector = new SelectChannelConnector(); connector.setPort(Integer.getInteger("jetty.port", 80).intValue()); WebAppContext webapp = new WebAppContext("web", "/struts_example"); Server server = new Server(); server.setConnectors(new Connector[] { connector }); server.setHandler(webapp); server.start(); System.out.println("Jetty Server started, use " + (System.currentTimeMillis() - begin) + " ms"); } }
有了JettyStarter這個類之后,我們可以直接將這個類以Application方式來運行。此時,Jetty服務器就會啟動(如圖1-10所示),從而成為一個Web容器的提供者。當然,我們也可以使用調試模式(Debug)執行這個類,從而使得整個Jetty服務器處于調試模式。

圖1-10 JettyStarter啟動界面
啟動成功后,我們會在控制臺看到成功啟動的日志:
[main] INFO org.mortbay.log - Logging to org.slf4j.impl.SimpleLogger via org.mortbay.log.Slf4jLog [main] INFO org.mortbay.log - jetty-6.1.7 [main] INFO org.mortbay.log - Started SelectChannelConnector@127.0.0.1:8080 Jetty Server started, use 1547 ms
此時,Jetty服務器被引入作為Web應用的開發調試服務器,Web開發調試環境也就成功搭建起來。我們可以通過瀏覽器對Web應用進行訪問,而其中的IP地址、端口、Web應用的入口名稱,都可以在JettyStarter這個Java類中進行API級別的相應設置。
如果JettyStarter運行在調試模式下,我們就可以在Web項目中加入熟悉的調試元素,例如加入斷點(Breakpoint)、加入監視(Watch)、單步運行(Step by),從而對整個項目的運行狀態進行調試和監控。
相比許多其他的開發環境搭建方式,本書所介紹的Web開發環境至少擁有以下的好處:
開發環境的建立并不依賴于任何IDE或者相關的插件,只需要運行某個Java類就可以進行調試
開發環境的建立不依賴于任何外部Web服務器的安裝,無論將項目遷移到什么樣的IDE或者操作系統,只要是有Java運行環境的地方,都可以直接運行
在項目中內置開發環境的做法,降低了程序員的學習成本
1.2 獲取Struts2
1.2.1 Struts2的相關資源下載
在Struts的官方網站(http://struts.apache.org)可以找到所有Struts項目相關的信息。由于歷史原因,Struts項目分為兩個截然不同并互不兼容的版本Struts1.X和Struts2. X(我們通常把Struts1.X的版本稱為Struts,而Struts2.X的版本稱為Struts2)。讀者在獲取相關信息時,需要正確區分不同版本的Struts項目,本書講述的所有內容都是圍繞著Struts2.X進行的。有關Struts項目的發展歷史和它們之間的不同,在其他章節中將會做出更加詳細的介紹。Struts的官方網站如圖1-11所示。

圖1-11 Sturts2的主頁
在左側的“Documentation”分類中,我們能夠找到Struts2的最新版本Struts 2.2.1 (GA)的鏈接,點擊該鏈接后就進入到了Struts2相應版本的主頁,其中可以找到Struts2的下載鏈接(一個很大的藍色Download Now按鈕),如圖1-12所示。

圖1-12 Struts 2.2.1主頁
點擊“Download Now”按鈕,將會看到Struts2的下載頁面,其中包含各種不同類型的Struts2的下載包,如圖1-13所示。

圖1-13 Struts2的下載頁面
在這里點擊下載struts-2.2.1-all.zip,就能獲得Struts2項目所有的相關資源。在其中,我們可以看到Struts2的分發包、Struts2的文檔(Reference)、Struts2的源碼、Struts2的示例項目等。接下來,我們就來看看Struts2項目基本的目錄組織結構。
1.2.2 Struts2項目的目錄組織結構
打開struts-2.2.1-all.zip并將其解壓到任意目錄后,我們可以在其中找到Struts2的所有相關資源,如圖1-14所示。
Struts2項目的目錄結構中主要包含了4個目錄:apps、docs、lib和src,這些目錄中所存放的基本內容分別介紹如下。
apps—存放了所有Struts2的示例項目
位于apps目錄下的所有war都是可以部署到Web服務器中直接運行的Web應用。這些Struts2的示例項目對學習Struts2有相當大的指導作用。當我們對Struts2的特性使用有疑問時,可以通過直接研究這些項目的源碼獲得足夠的支持。

圖1-14 Struts2分發包的目錄結構
docs—存放了所有Struts2與XWork的文檔
docs目錄中存放的Struts2與XWork的相關文檔基本上是以Wiki Page的形式出現的。這主要是由于Struts2來源于Webwork2,因而其文檔的表現形式也是一脈相承的。Wiki Page形式的文檔的好處在于可以將需要表述的框架特性劃分為若干個專題,針對每個專題,有相應的理論知識講解和示例代碼的印證。
lib—存放了所有Struts2相關的JAR文件以及Struts2運行時所依賴的JAR文件
lib目錄是一個完整的依賴資源集合。Struts2項目運行所需要的JAR文件都位于這個目錄下。我們可以看到,Struts2的許多特性都是以插件的形式提供的,因而在lib目錄下除了Struts2項目的基本依賴之外,絕大多數都是插件資源。
src—存放了所有Struts2的源碼,以Maven所指定的項目結構目錄存放
Struts2本身是根據Maven所指定的項目目錄結構進行編寫的,所以src目錄的組織結構也與Maven所規定的目錄結構相同。這種組織結構的好處在于我們可以在src目錄中找到所有Struts2相關資源的單個源碼文件。源碼的另外一種組織形式我們將在下一節中著重介紹,讀者可以就兩種不同的形式進行比較。
1.3 Struts2源碼的初步研究
1.3.1 源碼的組織形式
如果仔細瀏覽Struts2分發包中的src目錄,我們會發現在Struts2的分發包中提供的源碼是以目錄形式存放的。這種源碼組織形式允許讀者訪問單個源碼文件,并可以在資源管理器中清晰地看到源碼的目錄組織結構。除了這種基于目錄形式的源碼組織方式以外,還有另外一種組織源碼的方式,就是將所有的源碼打包成一個JAR文件或者ZIP文件。這種單個文件形式的源碼在結合IDE進行管理時更加簡單,故而受到廣大程序員的歡迎。
雖然Struts2的分發包中沒有提供這種形式的源碼,我們依然可以在網絡上查找得到,例如在http://search.maven.org/中,我們可以查詢到Struts2各個版本的分發包和對應的源碼文件。打開上述鏈接后,我們可以根據實際要求進行源碼查詢,如圖1-15所示。

圖1-15 Struts2源代碼查詢
點擊查詢后,我們就能在查詢結果中看到以JAR文件形式進行管理的資源文件,如圖1-16所示。

圖1-16 以JAR文件形式管理的Struts Core的各項資源列表
其中不僅包含Struts2的JAR文件(struts2-core-2.2.3.jar),還包含對應的源碼文件(struts2-core-2.2.3-sources.jar),大家可以直接點擊鏈接進行下載。
提示 細心的讀者或許可以發現,上面提供的含有Struts2源碼的網站,實際上是一個代碼資源庫的一部分(Maven2提供的一個網絡代碼庫,用于在Maven2的項目建立時,作為一個基本依賴)。實際上在這個站點中,我們還可以找到許多其他開源框架的各種形式的源代碼,本書中所依賴的絕大多數的源代碼都是從此處獲取的。
1.3.2 調試Struts2源碼
在Struts2的分發包中,我們可以獲取Struts2的絕大多數信息,包括Struts2的Library文件、Struts2運行時依賴的Library文件和Struts2的源碼等。接下來,我們將重點介紹一下如何在Eclipse IDE中調試Struts2的源碼。讀者也可以順著思路,在其他的IDE中獲得相應的支持。
什么是調試Struts2源碼呢?我們在日常開發中,經常聽到的是調試某一段應用程序。將應用程序運行于調試(Debug)模式下,我們就可以采用IDE提供的一些特性進行程序調試:設置斷點(Breakpoint)、加入監視(Watch)、單步運行(Step by)等等。通過對程序的調試,能夠迅速了解程序運行的狀態,從而幫助我們快速定位問題并解決問題。我們在這里所說的調試Struts2的源碼,實際上是在向讀者推薦一種閱讀源碼的方式。
傳統的閱讀開源框架源碼的方式,是以逐個package或者逐個module的方式對框架的源碼進行閱讀。不過我們在這里明確表示反對這種閱讀源碼的方式。因為任何一個程序只有處于運行狀態時,才能突顯出其內在的價值。我們鼓勵讀者從程序運行角度來看問題,而不是死板地對著源代碼本身。對于一個程序員來說,只有抓住一個程序或者框架的運行時狀態,才能夠對它們有更加深刻的理解。一個靜態的程序是死的,只有處于運行狀態的程序,我們才能看到其真正的生命力。接下來,我們就來看看在Eclipse中對一個開源框架進行源碼調試的步驟和方法。
首先在Eclipse中創建一個新的項目,加入運行Struts2所需要的JAR文件,并將它們加到項目的CLASSPATH中,成功后的界面如圖1-17所示。

圖1-17 Eclipse中新建項目截圖
接下來,我們來為加入到CLASSPATH中的這些JAR文件附上其所對應的源代碼。以“struts2-core-2.2.1.jar”為例,右鍵單擊“struts2-core-2.2.1.jar”,選擇Properties(Alt+ Enter)選項卡,彈出JAR文件的屬性選項框,如圖1-18所示。

圖1-18 為JAR文件附上源碼包
選擇選項卡左側的“Java Source Attachment”選項,點擊輸入框右側的按鈕,指定相應的源代碼所在的目錄或者源代碼所在的JAR文件(ZIP文件),點擊OK按鈕,Library文件就被附上了相應的源代碼(此時,我們會發現JAR文件形式的源碼組織形式在管理上的方便性,我們甚至可以把源碼文件存放到Workspace的某個Repository目錄后被所有的Library文件引用)。
在Library文件被附上源代碼之后,展開Library文件,并雙擊其中的class文件,就能看到class文件所對應的源碼,如圖1-19所示。

圖1-19 在Eclipse中查看源碼
Library文件被附上其對應的源碼后,我們就可以使用Eclipse IDE中的功能和快捷鍵對源碼進行查看和分析了。
除了基本的源碼查看功能,Eclipse IDE還能夠對正在運行的程序進行源碼級別的調試。例如,當一個程序運行在調試(Debug)模式時,我們可以直接打開Struts2的源碼,使用斷點功能,進入單步調試模式,并查看當前Struts2中類的運行狀態,如圖1-20所示。

圖1-20 在Eclipse中調試源碼
為Library附上源碼,是Eclipse IDE在源碼級別調試上的一個亮點。這為廣大程序員進行框架級別的源碼調試帶來了極大的便利。在進行框架研究時,我們實際上根本無須將龐大的框架源程序作為一個項目下載到本地并花大力氣把項目搭建起來。通過為Library附上源碼的方式,我們可以輕易地查看框架的源碼、獲得框架中的實現類之間的邏輯結構和層次關系。
調試源碼是除了日志輸出以外,最有效甚至是唯一的了解程序內部運行時狀態的方式。因而,調試源碼也是本書最為推薦的一種源碼級別學習方法,讀者不僅可以將這種學習方法運用在Struts2上面,也可將其用于其他的開源框架上。
1.4 小結
本章中,我們首先向讀者介紹了開發Struts2應用程序所必需的開發環境的搭建過程。這一過程包含:安裝與配置JDK、安裝與配置Eclipse、安裝與配置Web服務器。除此之外,著重介紹了在Eclipse中搭建Web開發環境并進行源碼級別調試的詳細過程。
讀者應該明確的是:學習一個框架,尤其是分析框架的內部實現機理,最為有效的途徑就是對框架進行源碼級別的調試并在調試的過程中深入探究框架內部元素在程序運行過程中的執行順序和執行狀態。這也是本書花許多筆墨向讀者介紹開發環境搭建過程的初衷。希望廣大讀者能夠融會貫通并舉一反三,根據實際情況搭建起自己順手的開發環境。
閱讀完本章后,大家是否已經能夠熟練掌握開發環境的搭建了呢?
如何在Eclipse中使用Jetty搭建Web開發環境?
Struts2的分發包中包含哪些主要內容?
開源項目的源代碼有哪些組織形式?
如何獲取一個開源框架的源碼?
如何在項目中進行框架的源碼調試?
- UNIX編程藝術
- Modular Programming with Python
- 造個小程序:與微信一起干件正經事兒
- MATLAB 2020 從入門到精通
- Linux網絡程序設計:基于龍芯平臺
- Internet of Things with Intel Galileo
- 鋒利的SQL(第2版)
- Building Serverless Applications with Python
- Arduino家居安全系統構建實戰
- Learning Unreal Engine Android Game Development
- RealSenseTM互動開發實戰
- Arduino Wearable Projects
- 超簡單:用Python讓Excel飛起來(實戰150例)
- 大數據時代的企業升級之道(全3冊)
- Java EE架構設計與開發實踐