Action類是用戶請(qǐng)求和業(yè)務(wù)邏輯之間的橋梁,每個(gè)Action充當(dāng)客戶的一項(xiàng)業(yè)務(wù)代理。在RequestProcessor類預(yù)處理請(qǐng)求時(shí),在創(chuàng)建了Action的實(shí)例后,就調(diào)用自身的processActionPerform()方法,該方法在調(diào)用Action類的execute()。
Action的excute()方法調(diào)用模型的業(yè)務(wù)方法,完成用戶請(qǐng)求,然后根據(jù)執(zhí)行結(jié)果把請(qǐng)求轉(zhuǎn)發(fā)給其他合適的WEB組件。
一、Action類緩存
struts應(yīng)用的生命周期中RequestProcessor只保證一個(gè)Action實(shí)例,所有的客戶請(qǐng)求都共享這個(gè)實(shí)例.所有請(qǐng)求可以同時(shí)執(zhí)行它的excute()方法。RequestProcessor類包含一個(gè)HashMap,作為存放所有Action實(shí)例的緩存。每個(gè)Action實(shí)例在緩存中存放的key為Action類名。在RequestProcessor類的processActionCreate()方法中,首先檢查在HashMap中是否存在Action實(shí)例,如果有直接使用,否則創(chuàng)建一個(gè)新的。創(chuàng)建Action實(shí)力的代碼位于同步代碼塊中,以保證只有一個(gè)線程創(chuàng)建Action實(shí)例,然后放在HashMap中。供其他線程使用。
如下代碼
二.創(chuàng)建支持多線程的Action
1.什么是線程安全的代碼
在多線程環(huán)境下能正確執(zhí)行的代碼就是線程安全的。
安全的意思是能正確執(zhí)行,否則后果是程序執(zhí)行錯(cuò)誤,可能出現(xiàn)各種異常情況。
2.如何編寫線程安全的代碼
很多書籍里都詳細(xì)講解了如何這方面的問題,他們主要講解的是如何同步線程對(duì)共享資源的使用的問題。主要是對(duì)synchronized關(guān)鍵字的各種用法,以及鎖的概念。
Java1.5中也提供了如讀寫鎖這類的工具類。這些都需要較高的技巧,而且相對(duì)難于調(diào)試。
但是,線程同步是不得以的方法,是比較復(fù)雜的,而且會(huì)帶來性能的損失。等效的代碼中,不需要同步在編寫容易度和性能上會(huì)更好些。
我這里強(qiáng)調(diào)的是什么代碼是始終為線程安全的、是不需要同步的。如下:
1)常量始終是線程安全的,因?yàn)橹淮嬖谧x操作。
2)對(duì)構(gòu)造器的訪問(new 操作)是線程安全的,因?yàn)槊看味夹陆ㄒ粋€(gè)實(shí)例,不會(huì)訪問共享的資源。
3)最重要的是:局部變量是線程安全的。因?yàn)槊繄?zhí)行一個(gè)方法,都會(huì)在獨(dú)立的空間創(chuàng)建局部變量,它不是共享的資源。局部變量包括方法的參數(shù)變量。
Servlet是在多線程環(huán)境下的。即可能有多個(gè)請(qǐng)求發(fā)給一個(gè)servelt實(shí)例,每個(gè)請(qǐng)求是一個(gè)線程。 struts下的action也類似,同樣在多線程環(huán)境下,你也必須編寫線程安全的Action類。
保證線程安全的原則就是僅僅使用局部變量,謹(jǐn)慎使用實(shí)例變量(擁有狀態(tài)的實(shí)例,尤其是擁有業(yè)務(wù)對(duì)象狀態(tài)的實(shí)例). 如果要用到那些有狀態(tài)的實(shí)例,唯一和最好的辦法是在Action類中,僅僅在Action類的execute()方法中使用局部變量,對(duì)于每個(gè)調(diào)用execute()方法的線程,JVM會(huì)在每個(gè)線程的堆棧中創(chuàng)建局部變量,因此每個(gè)線程擁有獨(dú)立的局部變量,不會(huì)被其他線程共享.當(dāng)線程執(zhí)行完execute()方法后,它的局部變量就會(huì)被銷毀.
如果Action類的實(shí)例變量是必須的話,需要采用JAVA同步機(jī)制(synchronized)對(duì)訪問共享資源的代碼塊進(jìn)行同步
三、Struts的幾種Action
Struts提供了一些現(xiàn)成的Action類,直接使用可以大大節(jié)省時(shí)間,如下
ForwardAction
可以轉(zhuǎn)發(fā)到其他web組件,僅僅提供一個(gè)轉(zhuǎn)發(fā)功能,不作處理。
IncludeAction
包含其他web組件。
DiapatchAction
通常一個(gè)Action只完成一個(gè)操作,用這個(gè)Action可以完成一組相關(guān)的操作。
LookupDispatchAction
他是DiapatchAction的子類,也可以定義多個(gè)方法,但主要用于一個(gè)表單里有多個(gè)按鈕,而這些按鈕又有一個(gè)共同的名字的場(chǎng)合。
SwitchAction
用于子模塊之間的切換。
四.ActionForward類
Action類的excute()方法返回一個(gè)ActionForward對(duì)象,它代表了web資源的邏輯抽象,這里的web資源可以是jsp頁面、Java servlet、或Action。
從excute返回ActionForward可以有兩種方法。
1) 動(dòng)態(tài)創(chuàng)建一個(gè)ActionForward實(shí)例
return new ActionForward(”Failure”,”login.jsp”,true);
2) 調(diào)用ActionMappin實(shí)例的findForward方法
這個(gè)方法先從action級(jí)別找,然后在<global-forwards />級(jí)別找
return mapping.findForward(“Failure”);
Action的excute()方法調(diào)用模型的業(yè)務(wù)方法,完成用戶請(qǐng)求,然后根據(jù)執(zhí)行結(jié)果把請(qǐng)求轉(zhuǎn)發(fā)給其他合適的WEB組件。
一、Action類緩存
struts應(yīng)用的生命周期中RequestProcessor只保證一個(gè)Action實(shí)例,所有的客戶請(qǐng)求都共享這個(gè)實(shí)例.所有請(qǐng)求可以同時(shí)執(zhí)行它的excute()方法。RequestProcessor類包含一個(gè)HashMap,作為存放所有Action實(shí)例的緩存。每個(gè)Action實(shí)例在緩存中存放的key為Action類名。在RequestProcessor類的processActionCreate()方法中,首先檢查在HashMap中是否存在Action實(shí)例,如果有直接使用,否則創(chuàng)建一個(gè)新的。創(chuàng)建Action實(shí)力的代碼位于同步代碼塊中,以保證只有一個(gè)線程創(chuàng)建Action實(shí)例,然后放在HashMap中。供其他線程使用。
如下代碼
- protected ?Action?processActionCreate(HttpServletRequest?request, ??
- ???????????????????????????????????????HttpServletResponse?response, ??
- ???????????????????????????????????????ActionMapping?mapping) ??
- ?????? throws ?IOException?{ ??
- ??
- ?????? //?Acquire?the?Action?instance?we?will?be?using?(if?there?is?one) ??
- ??????String?className?=?mapping.getType(); ??
- ?????? if ?(log.isDebugEnabled())?{ ??
- ??????????log.debug( "?Looking?for?Action?instance?for?class?" ?+?className); ??
- ??????} ??
- ??
- ?????? //?:TODO:?If?there?were?a?mapping?property?indicating?whether ??
- ?????? //?an?Action?were?a?singleton?or?not?([true]), ??
- ?????? //?could?we?just?instantiate?and?return?a?new?instance?here? ??
- ??
- ??????Action?instance?=? null ; ??
- ?????? synchronized ?(actions)?{ ??
- ??
- ?????????? //?Return?any?existing?Action?instance?of?this?class ??
- ??????????instance?=?(Action)?actions.get(className); ??
- ?????????? if ?(instance?!=? null )?{ ??
- ?????????????? if ?(log.isTraceEnabled())?{ ??
- ??????????????????log.trace( "??Returning?existing?Action?instance" ); ??
- ??????????????} ??
- ?????????????? return ?(instance); ??
- ??????????} ??
- ??
- ?????????? //?Create?and?return?a?new?Action?instance ??
- ?????????? if ?(log.isTraceEnabled())?{ ??
- ??????????????log.trace( "??Creating?new?Action?instance" ); ??
- ??????????} ??
- ?????????? ??
- ?????????? try ?{ ??
- ??????????????instance?=?(Action)?RequestUtils.applicationInstance(className); ??
- ?????????????? //?:TODO:?Maybe?we?should?propagate?this?exception ??
- ?????????????? //?instead?of?returning?null. ??
- ??????????}? catch ?(Exception?e)?{ ??
- ??????????????log.error( ??
- ??????????????????getInternal().getMessage( "actionCreate" ,?mapping.getPath()), ??
- ??????????????????e); ??
- ?????????????????? ??
- ??????????????response.sendError( ??
- ??????????????????HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ??
- ??????????????????getInternal().getMessage( "actionCreate" ,?mapping.getPath())); ??
- ?????????????????? ??
- ?????????????? return ?( null ); ??
- ??????????} ??
- ?????????? ??
- ??????????instance.setServlet( this .servlet); ??
- ??????????actions.put(className,?instance); ??
- ??????} ??
- ??
- ?????? return ?(instance); ??
- ??
- ??}??
protected Action processActionCreate(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws IOException { // Acquire the Action instance we will be using (if there is one) String className = mapping.getType(); if (log.isDebugEnabled()) { log.debug(" Looking for Action instance for class " + className); } // :TODO: If there were a mapping property indicating whether // an Action were a singleton or not ([true]), // could we just instantiate and return a new instance here? Action instance = null; synchronized (actions) { // Return any existing Action instance of this class instance = (Action) actions.get(className); if (instance != null) { if (log.isTraceEnabled()) { log.trace(" Returning existing Action instance"); } return (instance); } // Create and return a new Action instance if (log.isTraceEnabled()) { log.trace(" Creating new Action instance"); } try { instance = (Action) RequestUtils.applicationInstance(className); // :TODO: Maybe we should propagate this exception // instead of returning null. } catch (Exception e) { log.error( getInternal().getMessage("actionCreate", mapping.getPath()), e); response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, getInternal().getMessage("actionCreate", mapping.getPath())); return (null); } instance.setServlet(this.servlet); actions.put(className, instance); } return (instance); }
二.創(chuàng)建支持多線程的Action
1.什么是線程安全的代碼
在多線程環(huán)境下能正確執(zhí)行的代碼就是線程安全的。
安全的意思是能正確執(zhí)行,否則后果是程序執(zhí)行錯(cuò)誤,可能出現(xiàn)各種異常情況。
2.如何編寫線程安全的代碼
很多書籍里都詳細(xì)講解了如何這方面的問題,他們主要講解的是如何同步線程對(duì)共享資源的使用的問題。主要是對(duì)synchronized關(guān)鍵字的各種用法,以及鎖的概念。
Java1.5中也提供了如讀寫鎖這類的工具類。這些都需要較高的技巧,而且相對(duì)難于調(diào)試。
但是,線程同步是不得以的方法,是比較復(fù)雜的,而且會(huì)帶來性能的損失。等效的代碼中,不需要同步在編寫容易度和性能上會(huì)更好些。
我這里強(qiáng)調(diào)的是什么代碼是始終為線程安全的、是不需要同步的。如下:
1)常量始終是線程安全的,因?yàn)橹淮嬖谧x操作。
2)對(duì)構(gòu)造器的訪問(new 操作)是線程安全的,因?yàn)槊看味夹陆ㄒ粋€(gè)實(shí)例,不會(huì)訪問共享的資源。
3)最重要的是:局部變量是線程安全的。因?yàn)槊繄?zhí)行一個(gè)方法,都會(huì)在獨(dú)立的空間創(chuàng)建局部變量,它不是共享的資源。局部變量包括方法的參數(shù)變量。
Servlet是在多線程環(huán)境下的。即可能有多個(gè)請(qǐng)求發(fā)給一個(gè)servelt實(shí)例,每個(gè)請(qǐng)求是一個(gè)線程。 struts下的action也類似,同樣在多線程環(huán)境下,你也必須編寫線程安全的Action類。
保證線程安全的原則就是僅僅使用局部變量,謹(jǐn)慎使用實(shí)例變量(擁有狀態(tài)的實(shí)例,尤其是擁有業(yè)務(wù)對(duì)象狀態(tài)的實(shí)例). 如果要用到那些有狀態(tài)的實(shí)例,唯一和最好的辦法是在Action類中,僅僅在Action類的execute()方法中使用局部變量,對(duì)于每個(gè)調(diào)用execute()方法的線程,JVM會(huì)在每個(gè)線程的堆棧中創(chuàng)建局部變量,因此每個(gè)線程擁有獨(dú)立的局部變量,不會(huì)被其他線程共享.當(dāng)線程執(zhí)行完execute()方法后,它的局部變量就會(huì)被銷毀.
如果Action類的實(shí)例變量是必須的話,需要采用JAVA同步機(jī)制(synchronized)對(duì)訪問共享資源的代碼塊進(jìn)行同步
三、Struts的幾種Action
Struts提供了一些現(xiàn)成的Action類,直接使用可以大大節(jié)省時(shí)間,如下
ForwardAction
可以轉(zhuǎn)發(fā)到其他web組件,僅僅提供一個(gè)轉(zhuǎn)發(fā)功能,不作處理。
IncludeAction
包含其他web組件。
DiapatchAction
通常一個(gè)Action只完成一個(gè)操作,用這個(gè)Action可以完成一組相關(guān)的操作。
LookupDispatchAction
他是DiapatchAction的子類,也可以定義多個(gè)方法,但主要用于一個(gè)表單里有多個(gè)按鈕,而這些按鈕又有一個(gè)共同的名字的場(chǎng)合。
SwitchAction
用于子模塊之間的切換。
四.ActionForward類
Action類的excute()方法返回一個(gè)ActionForward對(duì)象,它代表了web資源的邏輯抽象,這里的web資源可以是jsp頁面、Java servlet、或Action。
從excute返回ActionForward可以有兩種方法。
1) 動(dòng)態(tài)創(chuàng)建一個(gè)ActionForward實(shí)例
return new ActionForward(”Failure”,”login.jsp”,true);
2) 調(diào)用ActionMappin實(shí)例的findForward方法
這個(gè)方法先從action級(jí)別找,然后在<global-forwards />級(jí)別找
return mapping.findForward(“Failure”);
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
