Struts2學習(一)————Struts2入門
首先推薦一本書,雖然我還沒看過,但是我以後肯定會看的,《Struts+技術內幕》提取密碼:kg6w 。現在只是停留在會使用struts2的層次,自己也想繼續深入研究,但是感覺自己的知識面還沒那麼廣,那就等以後工作之後,在回過頭來將那幾個框架研究一下,寫點有深度的文章,而此係列的文章,只是個人的學習記錄,將一些重點的東西記錄下來,以便以後的複習。謝謝
---WH
一、Struts2的介紹
講Struts2框架之前,我們需要知道框架是什麼呢?估計大多數初學者都只知道其名卻不知其意,框架就是一個半成品,別人將一些功能已經寫好了,我們只需要拿來用即可,像我們之前使用的dbutils框架,操作資料,只需要兩行程式碼,不用像一開始一樣,老老實實的寫一大堆程式碼,這就是開發框架的意義所在。簡化開發(個人對框架認識的理解,其他還有在框架上加自己的程式碼這些就不說了,肯定還有別的很多功能,這只是我最好理解的一種方式)。
而Struts2就是一個web層框架,並且是使用MVC設計模式實現的的一個框架,之前使用的是Serlvet+JSP來開發web專案,現在用Struts2框架來替代他,那Struts2到底有哪些優點呢?那就需要我們自己來研究它了。
請求 ----------- Servlet -------------- JSP serlvet+JSP
請求 ----------- Action -------------- JSP Struts
二、Struts2的架構圖分析
首先了解前,必須先要知道Struts2的架構圖,知道是如何工作的,做了哪些事情,可以不必那麼詳細的知道每一塊具體的細節,先讓我們自己有個大概的瞭解,這樣我們就更容易去接受它,使用它。
第一步:請求action,那麼就會經過StrutsPrepareAndExecuteFilter,這裡會做兩件事情,就是下面的兩步
第二步:通過ActionMapping將請求中的各種資料封裝起來,拿到請求中的各種引數資料,比如我們的action的名稱DemoAction
第三步:給自己找一個代理物件ActionProxy,來幫助我們處理事情。注意,這個ActionProxy實際上不做任何實事的,而是指揮別人做。
第四步:ActionProxy叫ConfigManager獲取struts.xml中的各種配置資訊,其中struts.xml就有action的類全限定類名等資訊,這樣就可以通過action的名字找到其位置了。
第五步:有了actionMapping獲取的請求資料和ConfigManager獲取的struts.xml中的資料,就叫ActionInvacation來查詢對應的action了
第六步:在找到action之前會經過一系列的攔截器,struts內部預設實現的。找到action後,就相當於我們的servlet,在其中執行一些業務程式碼,然後跳轉到目標頁面,響應回去。struts的整個過程即結束了。
就是這麼簡單,struts2的整個執行過程就這樣,而現在我們要寫一個struts2的hello world的話,根據struts2的架構圖,我們需要配置2個東西,第一個最關鍵的,在web.xml中配置strutsPrepareAndExecuteFilter即過濾器,配置了該過濾器,請求才會走struts2框架,第二個,struts.xml檔案,其中應該有的內容是通過action的名字就能夠找到其位置在哪裡,稍微會詳細講解。
三、struts2的hello world!
只需要五步,即可完成。
3.1、匯入jar包
3.2、在web.xml中配置過濾器
3.3、核心Action類。
3.4、配置struts.xml
3.5、測試
第一步:非常簡單,jar包肯定是記不住的,但是我們要會找。在下載的Struts的jar包中,我使用的是struts-2.3.15.1版本,其中的目錄結構需要了解。
這裡注意一點,lib下面有100多個jar包,並不需要匯入這麼多,我們在apps(案例)中找jar包即可,apps-blank.war是最簡單的案例,我們把其後綴名改為zip,然後解壓,找到其中的lib目錄下的jar包複製就行了
第二步:配置過濾器,這個也簡單,我們學過過濾器了,配置就跟配置servlet一樣。
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
第三步:編寫核心Action類
Action類可以有三種不同的型別
1、普通類,POJO,什麼介面也不實現,什麼類也不繼承
2、實現Action介面
3、繼承ActionSupport類。
這裡我們使用普通類即可,後面兩個在下面會講解到,最終我們會選擇使用繼承ActionSupport類,具體原因看下面。
第四步:編寫struts.xml
寫的時候忘記了格式,也沒關係,找模版。從圖中也可以看出,struts.xml檔案就放在src下即可
struts.xml的配置詳解
注意:action.class可以不寫,有預設值,為ActionSuppport類的全縣定名,下面會有講到,action.method也可以不寫,預設值為execute,result.name也可以不寫,預設值為success。
核心程式碼
<struts> <package name="default" namespace="/" extends="struts-default"> <action name="Demo01Action" class="com.wuhao.struts2.test.Demo01Action" method="execute"> <result name="success"> /index.jsp </result> </action> </package> </struts>
<struts> <package name="default" namespace="/" extends="struts-default"> <action name="Demo01Action" class="com.wuhao.struts2.test.Demo01Action" method="execute"> <result name="success"> /index.jsp </result> </action> </package> </struts>
第五步:測試
http://localhost:8080/struts2-hello/Demo01Action 其中用紅色標記的就是我們在struts.xml中設定的package的namespace+action中的name。通過/Demo01Action到struts.xml中就能找到在default包下的名為Demo01Action的action,然後通過class找到該action的所在位置,通過method找到需要執行的方法,通過方法的返回值找到result中是否有對應的值,找到了則進行跳轉。
根據這個例子,在回過頭去看看struts2的架構圖,然後在加以分析,
四、兩個重要的配置檔案
注意:這裡解釋一下struts.xml中的package繼承問題。上面繼承了一個struts-default的包,想要檢視它中的內容很簡單,在我們加入的struts2-core-2.3.15.1.jar包找到struts-default.xml,在該配置檔案中就有package為struts-default的內容。
第一個需要知道的配置檔案:struts-default.xml
從名字上看,就應該知道該是struts的一個預設的配置檔案,而我們前面編寫的一個startus.xml中應該會使用該預設配置檔案中的內容,其中的格式跟我們寫的struts.xml是一樣的。
分兩大部分,
第一部分 全是bean開頭的配置,暫時不管他是幹嘛用的,後面會學習,而我們的重點是第二部分
第二部分 看到了熟悉的內容,package,並且該package的名字為struts-default。這就是我們需要查詢的包,其中的內容包括了三個部分
1、<result-types></result-types>看到這裡我們就明白為什麼我們的結果中跳轉頁面的方式預設是dispatcher(轉發),因為在繼承的struts-default包中將其設定成了預設的,還有很多其他的type可選擇,比如其中的redirect,就是重定向,比如redirectAction,從一個action跳到另一個action中執行。比如stream,檔案上傳時用的,等等這些等後面會詳細講到。有個大概映像即可
2、<interceptors></interceptors>,這裡是一系列的過濾器,就是我們講的架構圖中的那一系列攔截器,就是在這裡給配置的。這裡具體不講解,後面會有章節進行講解,有映像即可
3、最後一個是兩個零碎的配置
321行:配置說預設的一個攔截器為defaultStack,這是一個攔截器棧,其內容在第二部分中,
323行,這裡說的class為在我們action中的class,如果不寫則為com.opensymphony.xwork2.ActionSupport。ActionSupport這個類就我們下面要講解的action繼承它來當action,那時候再與普通類當action有什麼區別。
總結:struts-default.xml的功能就是將一些已經有的功能加入到配置檔案中,然後讓我們編寫的struts.xml繼承其中的包,那麼我們就具備了這些功能,不用自己手動編寫了,如果想在上面新增功能,在編寫即可。到這裡為止應該就解決了為什麼要繼承struts-default這個包了把。
第二個配置檔案:default.properties,這是一個常量的配置檔案。其中放的都市常量。
比如:
struts.i18n.encoding=UTF-8 設定請求亂碼和響應亂碼的常量
struts.objectFactory = spring 這種帶spring的都市和spring整合時需要用到的。現在不用管
struts.multipart.saveDir= 檔案上傳時所存放的臨時路徑
struts.action.extension=action,, 訪問action時的字尾名可以為action,也可以什麼都不寫,就是通過這個常量設定
struts.enable.DynamicMethodInvocation = true 是否採用動態方法,比如Demo01Action!add 通過!add來動態確定執行的哪個方法,在配置檔案中就不用寫method屬性了
struts.devMode = false 開發者模式,如果改為true,則修改了struts等配置檔案,不用重啟伺服器即可生效,並且錯誤提示資訊更多
struts.ui.theme=xhtml struts自帶控制元件的一些佈局,但是一般使用simple,頁面的美化由美工處理。
以上說的都是一些常見的常量,其他的等遇到了在說,重點了解設定編碼和開發者模式和佈局。其中這些常量的值可以在struts.xml通過<constant name="" value="">來配置。
五、action訪問的兩種方式
前面幾個部分介紹了什麼是struts2?Struts2的helloworld,並且知道了struts2的架構流程圖。知道了struts2的兩個比較重要的配置檔案的內容,現在來說說對於action訪問的方式,在struts1中訪問action,一般是帶有後綴名為.do,而現在是為.action,為什麼能這樣寫的原因在上面說明了,default-properties檔案中就有這樣一個常量來說明使用什麼字尾訪問。可以為.action也可以不寫。所以在訪問action時,一般為:http://localhost:8080/xxx/xxxAction.action
但是寫了幾次helloworld之後,會發現一個缺點,一個action中有多少個方法,那麼就需要在struts.xml中配置多少個個action,並且每個action就method的值改變了,其他都不變,所以為了改變這種狀態,有三種方法可以解決。
動態方法的呼叫
在struts.xml中開啟動態方法的使用。struts.enable.DynamicMethodInvocation = true
那麼就可以直接使用http://localhost:8080/xxx/xxxAction!add 直接呼叫xxxAction中的add方法了,並且在struts.xml中的action配置中,就不需要配置method屬性的值了。這樣做就解決了寫死method值的問題
萬用字元的使用
這個比較重要,使用的比較多,即,<action name="userAction"> , action.name可以使用萬用字元星號(*),在action.class、aciton.method、result.name 處可以使用{n}方式匹配星號,舉個例子就明白了
案例一:<action name="userAction_*"> 在action.class、action.method、result.name三個地方可以使用{1}來獲取第一個星號所匹配的內容
請求路徑:..../userAction_add <action name="userAction_* class="..." method="{1}"/> 那麼{1}拿到的內容則是add,將執行add方法
案例二:<action name="userAction_*_*"> {1}匹配第一個* {2}匹配第二個*
請求路徑 :.../userAction_add_success <action name="userAction_*_*" method="{1}"><result name="{2}">
{1}匹配add方法,{2}匹配返回值的名稱success
案例三:使用*_*_*,通過{1}{2}{3}獲得,可以自己嘗試。
注意:package.namaspace的特點,當namespace為"/a"時,正常通過/a/xxxAction就能訪問到,但是如果/a/b/c/xxxAction是否能訪問到呢?答案是YES,因為會一層一層往下找,什麼意思呢?
http://localhost:8080/xxx/a/b/c/xxxAction 找不到,往下一層找
http://localhost:8080/xxx/a/b/xxxAction 找,也找不到,繼續往下
http://localhost:8080/xxx/a/xxxAction 我們這裡配置的namespace為"/a",所以就找到了,如果我們namespace="/",那麼/a/b/c/xxxAction就訪問不到了,只有/xxxAction能訪問到。但是如果namespace="",那就找得到,什麼都不寫的意思是不管什麼路徑都能匹配到。
六、action類實現的三種方式
6.1、普通類,上面寫helloworld就是使用的普通類
6.2、實現Action介面,重寫excute方法,介面中就宣告這一個方法。
6.3、繼承ActionSupport類,可以不必重寫execute方法,只需要寫自己想要的方法即可,一般開發中就使用這種方法,為什麼呢?因為方便,ActionSupport類提供了一些我們所需要的常量,比如success字串常量,內部還實現了execute方法,我們就不必自己寫了。那麼很多人就問,這不是多此一舉嗎?繼承它跟不繼承它的區別不大呀?哈哈,這樣舉個例子吧,你想追一個女孩子,有一天哪個女孩子哭了,擦淚的紙巾在女孩子的旁邊,那個女孩子完全可以自己拿紙巾,但是你為了追她,體現自己好的一面,肯定是自己去拿紙巾出來遞給她,雖然可能你拿比她自己拿更麻煩一點,但是這樣讓她對你更有好感呀, 那麼這個繼承actionSupport提供的一些常量等,也就是這個道理。並且它還不止止這點功能,它自己內部幫我實現了很多介面,後面會有講解到,現在就曉得,以後寫的話就通過這種方式去寫action類。
七、總結
這一節並沒有什麼特點難懂的東西,知道下面幾點即可
1、struts2的架構圖,並且知道一個請求過來都做了些什麼東西,是如何找到action的。
2、struts2的兩個重要的配置檔案,一個default-properties,一個struts-default.xml。知道這兩個配置檔案在哪裡,知道其中的一些大概的內容
3、struts.xml的編寫,和其中各種配置的含義
4、會編寫一個簡單的helloworld。