spring的最大作用ioc/di,將類與類的依賴關(guān)系寫(xiě)在配置文件中,
程序在運(yùn)行時(shí)根據(jù)配置文件動(dòng)態(tài)加載依賴的類,
降低的類與類之間的藕合度。
它的原理是在applicationContext.xml加入bean標(biāo)簽,
在bean標(biāo)簽中通過(guò)class屬性說(shuō)明具體類名,
通過(guò)property標(biāo)簽說(shuō)明該類的屬性名,
通過(guò)constructor-args說(shuō)明構(gòu)造子的參數(shù)。
其一切都是返射,當(dāng)通過(guò)applicationContext.getBean("id名稱")得到一個(gè)類實(shí)例時(shí),
就是以bean標(biāo)簽的類名、屬性名、構(gòu)造子的參數(shù)為準(zhǔn),
通過(guò)反射實(shí)例對(duì)象,喚起對(duì)象的set方法設(shè)置屬性值,
通過(guò)構(gòu)造子的newInstance實(shí)例化得到對(duì)象。
正因?yàn)閟pring一切都是反射,反射比直接調(diào)用的處理速度慢,
所以這也是spring的一個(gè)問(wèn)題。
spring第二大作用就是aop,其機(jī)理來(lái)自于代理模式,
代理模式有三個(gè)角色分別是通用接口、代理、真實(shí)對(duì)象代理、
真實(shí)對(duì)象實(shí)現(xiàn)的是同一接口,將真實(shí)對(duì)象作為代理的一個(gè)屬性,
向客戶端公開(kāi)的是代理,當(dāng)客戶端調(diào)用代理的方法時(shí),
代理找到真實(shí)對(duì)象,調(diào)用真實(shí)對(duì)象方法,
在調(diào)用之前之后提供相關(guān)的服務(wù),如事務(wù)、安全、日志。
其名稱分別是代理、真實(shí)對(duì)象、裝備、關(guān)切點(diǎn)、連接點(diǎn)。
主要是可擴(kuò)展性。如果現(xiàn)在你的客戶覺(jué)得訪問(wèn)效率太低,程序不用hibernate了,
要使用jdbc,比如:UserDaoHibernateImpl(原來(lái)),現(xiàn)在修改為UserDaoJdbcImpl.
這個(gè)時(shí)候你要怎么辦?直接去修改源代碼?你原來(lái)不用接口進(jìn)行引用,肯定是new 了一個(gè)
UserDaoHibernateImpl出來(lái),如果多個(gè)地方都用到,你不但要去修改源代碼,還要修改很多地方,
而是用spring的依賴注入呢,你只需要修改下配置,把bean的class屬性給修改下,換下配置什么的
就可以了,降低后期維護(hù)成本
因?yàn)閣eb應(yīng)用大了,servletClass多了,所以用到struts來(lái)減輕我們的負(fù)擔(dān),使得模塊更清晰,和更利于復(fù)用和管理。
因?yàn)閣eb應(yīng)用大了,表、字段多了,寫(xiě)sql語(yǔ)句會(huì)寫(xiě)死人,且比較容易出錯(cuò),所以用到hibernate來(lái)獲得它給我們的面向?qū)ο蟛僮鲾?shù)據(jù)庫(kù)的服務(wù),省去了寫(xiě)n多sql的煩心事,且使我們的程序更加面向?qū)ο?
因?yàn)檫壿嫼徒M件模塊多了,因?yàn)閷佣嗔耍谑俏覀兛紤]整一個(gè)spring,一來(lái)包裝hibernate,提供更簡(jiǎn)便的服務(wù)接口及更易于管理的事務(wù)服務(wù),二來(lái)代理了我們的服務(wù)層和dao層,使得這兩層與實(shí)際的控制單元的關(guān)系變成ioc框架來(lái)管理,任何一方的修改都不會(huì)牽扯到雙方都要修改的問(wèn)題。總之spring就是把雜亂的dao、service、action給串了起來(lái),變成了一個(gè)個(gè)可在程序外控制的模塊,使其可以自由的組合在一起,即可獲得想要的服務(wù)也不用煩他們之間的關(guān)系。
CopyRight@BUG
Struts framework的工作原理和組件
對(duì)于Struts 如何控制、處理客戶請(qǐng)求,讓我們通過(guò)對(duì)struts的四個(gè)核心組件介紹來(lái)具體說(shuō)明。這幾個(gè)組件就是:ActionServlet。Action Classes,Action Mapping(此處包括ActionForward),ActionFrom Bean。
Struts ActionServlet控制器對(duì)象
ActionServlet繼承自javax.servlet.http.HttpServlet類,其在Struts framework中扮演的角色是中心控制器。它提供一個(gè)中心位置來(lái)處理全部的終端請(qǐng)求。控制器ActionServlet主要負(fù)責(zé)將HTTP的客戶請(qǐng)求信息組裝后,根據(jù)配置文件的指定描述,轉(zhuǎn)發(fā)到適當(dāng)?shù)奶幚砥鳌?/p>
按照Servelt的標(biāo)準(zhǔn),所有得Servlet必須在web配置文件(web.xml)聲明。同樣,ActoinServlet必須在Web Application配置文件(web.xml)中描述,有關(guān)配置信息如下。
<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

</servlet>


全部的請(qǐng)求URI以*.do的模式存在并映射到這個(gè)servlet,其配置如下:
1
<servlet-mapping>
2
3
4
5
<servlet-name>action</servlet-name>
6
7
8
9
<url-pattern>*.do</url-pattern>
10
11
12
13
</servlet-mapping>
14
15
一個(gè)該模式的請(qǐng)求URI符合如下格式:
http://www.my_site_name.com/mycontext/actionName.do
中心控制器為所有的表示層請(qǐng)求提供了一個(gè)集中的訪問(wèn)點(diǎn)。這個(gè)控制器提供的抽象概念減輕了開(kāi)發(fā)者建立公共應(yīng)用系統(tǒng)服務(wù)的困難,如管理視圖、會(huì)話及表單數(shù)據(jù)。它也提供一個(gè)通用機(jī)制如錯(cuò)誤及異常處理,導(dǎo)航,國(guó)際化,數(shù)據(jù)驗(yàn)證,數(shù)據(jù)轉(zhuǎn)換等。
當(dāng)用戶向服務(wù)器端提交請(qǐng)求的時(shí)候,實(shí)際上信息是首先發(fā)送到控制器ActionServlet,一旦控制器獲得了請(qǐng)求,其就會(huì)將請(qǐng)求信息傳交給一些輔助類(help classes)處理。這些輔助類知道如何去處理與請(qǐng)求信息所對(duì)應(yīng)的業(yè)務(wù)操作。在Struts中,這個(gè)輔助類就是org.apache.struts.action.Action。通常開(kāi)發(fā)者需要自己繼承Aciton類,從而實(shí)現(xiàn)自己的Action實(shí)例。
Struts Action Classes
ActionServlet把全部提交的請(qǐng)求都被控制器委托到RequestProcessor對(duì)象。RequestProcessor使用struts-config.xml文件檢查請(qǐng)求URI找到動(dòng)作Action標(biāo)示符。
一個(gè)Action 類的角色,就像客戶請(qǐng)求動(dòng)作和業(yè)務(wù)邏輯處理之間的一個(gè)適配器(Adaptor),其功能就是將請(qǐng)求與業(yè)務(wù)邏輯分開(kāi)。這樣的分離,使得客戶請(qǐng)求和Action類之間可以有多個(gè)點(diǎn)對(duì)點(diǎn)的映射。而且Action類通常還提供了其它的輔助功能,比如:認(rèn)證(authorization)、日志(logging)和數(shù)據(jù)驗(yàn)證(validation)。
1
public ActionForward execute(ActionMapping mapping,ActionFormform,javax.servlet.ServletRequestrequest,javax.servlet.ServletResponse response)throwsjava.io.IOException,javax.servlet.ServletException
2
3
Action最為常用的是execute()方法。(注意,以前的perform方法在struts1.1中已經(jīng)不再支持),還有一個(gè)execute()方法,請(qǐng)參考apidoc,在此不在說(shuō)明。
當(dāng)Controller收到客戶的請(qǐng)求的時(shí)候,在將請(qǐng)求轉(zhuǎn)移到一個(gè)Action實(shí)例時(shí),如果這個(gè)實(shí)例不存在,控制器會(huì)首先創(chuàng)建,然后會(huì)調(diào)用這個(gè)Action實(shí)例的execute()方法。Struts Framework為應(yīng)用系統(tǒng)中的每一個(gè)Action類只創(chuàng)建一個(gè)實(shí)例。因?yàn)樗械挠脩舳际褂眠@一個(gè)實(shí)例,所以你必須確定你的Action 類運(yùn)行在一個(gè)多線程的環(huán)境中。下圖顯示了一個(gè)execute()方法如何被訪問(wèn):
Action實(shí)例的execute()方法
注意,客戶自己繼承的Action子類,必須重寫(xiě)execute()方法,因?yàn)锳ction類在默認(rèn)情況下是返回null的。
Struts Action Mapping
上面講到了一個(gè)客戶請(qǐng)求是如何被控制器轉(zhuǎn)發(fā)和處理的,但是,控制器如何知道什么樣的信息轉(zhuǎn)發(fā)到什么樣的Action類呢?這就需要一些與動(dòng)作和請(qǐng)求信息相對(duì)應(yīng)的映射配置說(shuō)明。在struts 中,這些配置映射信息是存儲(chǔ)在特定的XML文件(比如struts-config.xml)。
這些配置信息在系統(tǒng)啟動(dòng)的時(shí)候被讀入內(nèi)存,供struts framework在運(yùn)行期間使用。在內(nèi)存中,每一個(gè)<action>元素都與org.apache.struts.action.ActionMapping類的一個(gè)實(shí)例對(duì)應(yīng)。下表就顯示了一個(gè)登陸的配置映射。
1
<action-mappings>
2
3
4
5
<action path="/logonAction"
6
7
8
9
type="com.test.LogonAction"
10
11
12
13
name="LogonForm"
14
15
16
17
scope="request"
18
19
20
21
input="logoncheck.jsp"
22
23
24
25
validate="false">
26
27
28
29
<forward name="welcome" path="/welcome.jsp"/>
30
31
32
33
<forward name="failure" path="/logon_failure.jsp "/>
34
35
36
37
</action>
38
39
40
41
</action-mappings>
42
43
44
45
46
47
48
49
50
51
52
53
<form-beans>
54
55
56
57
<form-bean name="LoginForm"
58
59
60
61
type="com.test.LoginForm"/>
62
63
64
65
</form-beans>
66
67
上面的配置表示:當(dāng)可以通過(guò)/logonAction.do(此處假設(shè)配置的控制器映射為*.do)提交請(qǐng)求信息的時(shí)候,控制器將信息委托com.test.LogonAction處理。調(diào)用LogonAction實(shí)例的execute()方法。同時(shí)將Mapping實(shí)例和所對(duì)應(yīng)的LogonForm Bean信息傳入。其中name=LogonForm,使用的form-bean元素所聲明的ActionForm Bean。有關(guān)form-bean的申明如下顯示。
使用ActionForward導(dǎo)航
元素<forward>則表示了當(dāng)Action實(shí)例的execute()方法運(yùn)行完畢或,控制器根據(jù)Mapping可將響應(yīng)信息轉(zhuǎn)到適當(dāng)?shù)牡胤健H缟厦娆F(xiàn)實(shí),如果客戶登陸成功,則調(diào)用welcome forward,將成功信息返回到/welcome.jsp頁(yè)面。在你的execute()方法的結(jié)尾可以使用下面的實(shí)例代碼而返回welcome forward。當(dāng)然你的welcome forward必須在action元素屬性中定義,正如上面所聲明的那樣。
return (mapping.findForward("welcome"));
ActionForward對(duì)象是配置對(duì)象。這些配置對(duì)象擁有獨(dú)一無(wú)二的標(biāo)識(shí)以允許它們按照有意義的名稱如“success”,“failure”等來(lái)檢索。ActionForward對(duì)象封裝了向前進(jìn)的URL路徑且被請(qǐng)求處理器用于識(shí)別目標(biāo)視圖。ActionForward對(duì)象建立自<forward>元素位于struts-config.xml。下面是一個(gè)Struts中<forward>元素例子,屬于<action>元素范圍。
1
<action path="/editCustomerProfile"
2
3
type="packageName.EditCustomerProfileAction"
4
5
name="customerProfileForm" scope="request">
6
7
<forward name="success" path="/MainMenu.jsp"/>
8
9
<forward name="failure" path="/CustomerService.jsp"/>
10
11
</action>
12
13
基于執(zhí)行請(qǐng)求處理器的execute(…)方法的結(jié)果,當(dāng)傳遞一個(gè)值匹配指定于<forward>元素中name屬性的值的時(shí)候,下一個(gè)視圖可以在execute(…)方法中被開(kāi)發(fā)者用方便的方法org.apache.struts.action.ActionMapping.findForward(…)選擇。ActionMapping.findForward(…)方法既從它的本地范圍又從全局范圍提供一個(gè)ActionForward對(duì)象,該對(duì)象返回至RequestProcessor以RequestDispatcher.forward(…)或response.sendRedirect(…)調(diào)用下一個(gè)視圖。當(dāng)<forward>元素有redirect=“false”屬性或redirect屬性不存在的時(shí)候,RequestDispatcher.forward(…)被執(zhí)行;當(dāng)redirect=“true”是,將調(diào)用sendRedirect(…)方法。下例舉例說(shuō)明了redirect屬性的用法:
1
<forward name="success" path="/Catalog.jsp" redirect="true"/>
如果redirect=true, URL建立如/contextPath/path因?yàn)镠ttpServletResponse.sendRedirect(…)中解釋URL采用”/”開(kāi)頭相對(duì)于servlet容器根目錄。
如果redirect=false, URI建立如/path因?yàn)镾ervletContext.getRequestDisptacher(…)采用虛擬目錄相關(guān)URL。
在此稍稍說(shuō)一下有關(guān)global-forwards的概念。其在配置文件中描述了整個(gè)應(yīng)用系統(tǒng)可以使用的ActionForward,而不是僅僅是一個(gè)特定的Action。
1
<global-forwards>
2
3
<forward name="logout" path="/logout.do"/>
4
5
<forward name="error" path="/error.jsp"/>
6
7
</global-forwards>
Struts ActionForm Bean捕獲表單數(shù)據(jù)
在上面講解ActionServlet,Action Classes和Action Mapping的時(shí)候,我們都提到了ActionForm Bean的概念。一個(gè)應(yīng)用系統(tǒng)的消息轉(zhuǎn)移(或者說(shuō)狀態(tài)轉(zhuǎn)移)的非持久性數(shù)據(jù)存儲(chǔ),是由ActionForm Bean的負(fù)責(zé)保持的。
ActionForm派生的對(duì)象用于保存請(qǐng)求對(duì)象的參數(shù),因此它們和用戶緊密聯(lián)系。
一個(gè)ActionForm類被RequestProcessor建立。這是發(fā)生在已完成向前進(jìn)到一個(gè)URL,該URL為映射到控制器servlet而不是JSP和相應(yīng)的動(dòng)作映射指定的表單屬性的。在這個(gè)情況下,如果沒(méi)有在指定的活動(dòng)范圍內(nèi)找到,RequestProcessor將嘗試尋找可能導(dǎo)致創(chuàng)建一個(gè)新ActionForm對(duì)象的表單bean。該ActionForm對(duì)象在指定的活動(dòng)范圍內(nèi)被用<action>元素的name屬性找到;
RequestProcessor將隨后重新安排表單屬性,用請(qǐng)求時(shí)參數(shù)填充表單,隨即調(diào)用表單對(duì)象的validate(…)方法以履行服務(wù)器端用戶輸入驗(yàn)證。僅當(dāng)ActionMapping對(duì)象中validate屬性被設(shè)為true時(shí),validate(…)方法被調(diào)用;這就是默認(rèn)的行為。request.getParameterValues(parameterName)被用于得到一個(gè)String[]對(duì)象,它用來(lái)表單填充;驗(yàn)證的結(jié)果應(yīng)該是一個(gè)ActionErrors對(duì)象,用org.apache.struts.taglib.html.ErrorsTag來(lái)顯示驗(yàn)證錯(cuò)誤給用戶。ActionForm也可以被用于為當(dāng)前用戶保存即將被一個(gè)視圖引用的中間模型狀態(tài)。
當(dāng)一個(gè)表單對(duì)象被RequestProcessor找到,它被傳遞到請(qǐng)求處理器的execute(…)方法。一個(gè)ActionForm對(duì)象也可以被請(qǐng)求處理器建立。表單對(duì)象建立目的是提供中間模型狀態(tài)給使用請(qǐng)求范圍JSP;這將確保對(duì)象不會(huì)在有效性過(guò)期后仍然存在。默認(rèn)的,所有的表單都被保存為會(huì)話范圍。會(huì)話中表單對(duì)象脫離有效性的存在可能導(dǎo)致浪費(fèi)內(nèi)存,同樣的,請(qǐng)求處理器必須跟蹤保存在會(huì)話中的表單對(duì)象的生命周期。一個(gè)好的捕獲表單數(shù)據(jù)的實(shí)踐是為橫跨多用戶交互的相關(guān)表單用一個(gè)單獨(dú)的表單bean。表單bean也可以在反饋的時(shí)候用來(lái)儲(chǔ)存能夠被自定義標(biāo)簽改變的中間模型狀態(tài)。在視圖中標(biāo)簽用法避免結(jié)合Java代碼,因此要成一個(gè)好的任務(wù)劃分,web生產(chǎn)組主要處理標(biāo)志,而應(yīng)用開(kāi)發(fā)組主要處理Java代碼。標(biāo)簽因素退出訪問(wèn)中間模型狀態(tài)的邏輯;當(dāng)訪問(wèn)嵌套的對(duì)象或當(dāng)通過(guò)聚集列舉時(shí)這個(gè)邏輯可能很復(fù)雜。
注意:在struts1.1中,ActionForm的校驗(yàn)功能,逐漸被剝離出來(lái)(當(dāng)然依然可以使用)。使用了validator framework對(duì)整個(gè)應(yīng)用系統(tǒng)的表單數(shù)據(jù)驗(yàn)證進(jìn)行統(tǒng)一管理。相信信息請(qǐng)參考:http://home.earthlink.net/~dwinterfeldt
在ActionForm的使用中,Struts提倡使用到值對(duì)象(Value Object)。這樣將客戶或開(kāi)發(fā)人員,對(duì)數(shù)據(jù)狀態(tài)與對(duì)象狀態(tài)能夠更加清晰的理解和使用。
對(duì)于每一個(gè)客戶請(qǐng)求,Struts framework在處理ActionForm的時(shí)候,一般需要經(jīng)歷如下幾個(gè)步驟:
(1)檢查Action的映射,確定Action中已經(jīng)配置了對(duì)ActionForm的映射
(2)根據(jù)name屬性,查找form bean的配置信息
(3)檢查Action的formbean的使用范圍,確定在此范圍下,是否已經(jīng)有此form bean的實(shí)例。
(4)假如當(dāng)前范圍下,已經(jīng)存在了此form bean的實(shí)例,而是對(duì)當(dāng)前請(qǐng)求來(lái)說(shuō),是同一種類型的話,那么就重用。
(5)否則,就重新構(gòu)建一個(gè)form bean的實(shí)例
(6)form bean的reset()方法備調(diào)用
(7)調(diào)用對(duì)應(yīng)的setter方法,對(duì)狀態(tài)屬性賦值
(8)如果validatede的屬性北設(shè)置為true,那么就調(diào)用form bean的validate()方法。
(9)如果validate()方法沒(méi)有返回任何錯(cuò)誤,控制器將ActionForm作為參數(shù),傳給Action實(shí)例的execute()方法并執(zhí)行。
注意:直接從ActionFrom類繼承的reset()和validate()方法,并不能實(shí)現(xiàn)什么處理功能,所以有必要自己重新覆蓋。
Struts的其他組件
Struts framework本身提供了很多可擴(kuò)展的組件或sub framework,方便的開(kāi)發(fā)人員在其構(gòu)架上構(gòu)建web層的應(yīng)用系統(tǒng)。比如upload,collections ,logging等等。讓我們來(lái)看看兩個(gè)比較重要的組件:validationg framework和struts taglib。有關(guān)其他組件請(qǐng)參考Struts用戶手冊(cè)(http://jakarta.apache.org/struts/userGuide)。
Validation Framework for Struts
在struts1.1中,新增了validation framework。增加了對(duì)form數(shù)據(jù)提交的驗(yàn)證。將原本需要在ActionFrom Bean的validate()進(jìn)行的驗(yàn)證通過(guò)配置文件的描述進(jìn)行驗(yàn)證。
有關(guān)其詳細(xì)信息,請(qǐng)參考http://home.earthlink.net/~dwinterfeldt 。個(gè)人建議對(duì)于小型應(yīng)用系統(tǒng)可以采用這種配置方式,但是對(duì)于應(yīng)用系統(tǒng)中有大量web層表單應(yīng)用的系統(tǒng),并且業(yè)務(wù)需求變動(dòng)比較大的,使用validation framework 可能會(huì)加重開(kāi)發(fā)難度、系統(tǒng)維護(hù)難度。可以借鑒validation framework的Javascript Validator Tag。
Struts TagLib
struts提供了一組可擴(kuò)展的自定義標(biāo)簽庫(kù)(TagLib),可以簡(jiǎn)化創(chuàng)建用戶界面的過(guò)程。目前包括:Bean Tags,HTML Tags,Logic Tags,Nested Tags,Template Tags 這幾個(gè)Taglib。有關(guān)Struts Taglib的結(jié)構(gòu)和使用,可以參考前面有關(guān)Cutomer Tag Lib的介紹,有關(guān)起詳細(xì)資料,請(qǐng)參考
BeanUtils
這個(gè)組件的全稱是Bean Introspection Utilites。是屬于Jakarta Commons項(xiàng)目組的。主要是幫助構(gòu)建javabean的屬性操作的(getter,setter),已經(jīng)提供一種動(dòng)態(tài)定義和訪問(wèn)bean的屬性。有關(guān)詳細(xì)信息,請(qǐng)參考。
http://jakarta.apache.org/commons/beanutils.html
如果各位對(duì)這方面有很興趣,可以參考一些有關(guān)java反射(Reflectio)方面的資料。
Collections
這個(gè)組件主要是提供了一些集合或列表對(duì)象,在原有的java collections framework的基礎(chǔ)上進(jìn)行了擴(kuò)展。詳細(xì)資料請(qǐng)參考:
http://jakarta.apache.org/commons/collections.html 以及
http://cvs.apache.org/viewcvs/~checkout~/jakarta-commons/collections/STATUS.html?rev=1.13
Digester
這個(gè)組件翻譯成中文的意思是“匯編”。其主要功能是根據(jù)xml配置文件,初始化系統(tǒng)的一些java類對(duì)象。Digester幫助你指定XML與java對(duì)象之間映射模型,而且允許客戶話定制映射規(guī)則(rules)。詳細(xì)資料請(qǐng)參考
本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/fasttalk/archive/2005/03/19/323752.aspx