Action類是用戶請求和業務邏輯之間的橋梁,每個
Action充當客戶的一項業務代理。在RequestProcessor類預處理請求時,在創建了
Action的實例后,就調用自身的processActionPerform()方法,該方法再調用
Action類的execute()。
Action的excute()方法調用模型的業務方法,完成用戶請求,然后根據執行結果把請求轉發給其他合適的WEB組件。
一、Action類緩存
struts應用的生命周期中RequestProcessor只保證一個
Action實例,所有的客戶請求都共享這個實例.所有請求可以同時執行它的excute()方法。RequestProcessor類包含一個HashMap,作為存放所有
Action實例的緩存。每個
Action實例在緩存中存放的key為
Action類名。在RequestProcessor類的processActionCreate()方法中,首先檢查在HashMap中是否存在
Action實例,如果有直接使用,否則創建一個新的。創建
Action實力的代碼位于同步代碼塊中,以保證只有一個線程創建
Action實例,然后放在HashMap中。供其他線程使用。
如下代碼
protected Action processActionCreate(HttpServletRequest request,
HttpServletResponse response,
ActionMapping mapping)
throws IOException
{
String className = mapping.getType();
if (log.isDebugEnabled())
{
log.debug(" Looking for Action instance for class " + className);
}
Action instance = null;
synchronized (actions)
{
instance = (Action) actions.get(className);
if (instance != null)
{
if (log.isTraceEnabled())
{
log.trace(" Returning existing Action instance");
}
return (instance);
}
if (log.isTraceEnabled())
{
log.trace(" Creating new Action instance");
}
try
{
instance = (Action) RequestUtils.applicationInstance(className);
}
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);
}
二.創建支持多線程的Action
1.什么是線程安全的代碼
在多線程環境下能正確執行的代碼就是線程安全的。
安全的意思是能正確執行,否則后果是程序執行錯誤,可能出現各種異常情況。
2.如何編寫線程安全的代碼
很多書籍里都詳細講解了如何這方面的問題,他們主要講解的是如何同步線程對共享資源的使用的問題。主要是對synchronized關鍵字的各種用法,以及鎖的概念。
Java1.5中也提供了如讀寫鎖這類的工具類。這些都需要較高的技巧,而且相對難于調試。
但是,線程同步是不得以的方法,是比較復雜的,而且會帶來性能的損失。等效的代碼中,不需要同步在編寫容易度和性能上會更好些。
我這里強調的是什么代碼是始終為線程安全的、是不需要同步的。如下:
1)常量始終是線程安全的,因為只存在讀操作。
2)對構造器的訪問(new 操作)是線程安全的,因為每次都新建一個實例,不會訪問共享的資源。
3)最重要的是:局部變量是線程安全的。因為每執行一個方法,都會在獨立的空間創建局部變量,它不是共享的資源。局部變量包括方法的參數變量。
Servlet是在多線程環境下的。即可能有多個請求發給一個servelt實例,每個請求是一個線程。 struts下的action也類似,同樣在多線程環境下,你也必須編寫線程安全的Action類。
保證線程安全的原則就是僅僅使用局部變量,謹慎使用實例變量(擁有狀態的實例,尤其是擁有業務對象狀態的實例). 如果要用到那些有狀態的實例,唯一和最好的辦法是在Action類中,僅僅在Action類的execute()方法中使用局部變量,對于每個調用execute()方法的線程,JVM會在每個線程的堆棧中創建局部變量,因此每個線程擁有獨立的局部變量,不會被其他線程共享.當線程執行完execute()方法后,它的局部變量就會被銷毀.
如果Action類的實例變量是必須的話,需要采用JAVA同步機制(synchronized)對訪問共享資源的代碼塊進行同步
三、Struts的幾種Action
Struts提供了一些現成的Action類,直接使用可以大大節省時間,如下
ForwardAction
可以轉發到其他web組件,僅僅提供一個轉發功能,不作處理。
IncludeAction
包含其他web組件。
DiapatchAction
通常一個Action只完成一個操作,用這個Action可以完成一組相關的操作。
LookupDispatchAction
他是DiapatchAction的子類,也可以定義多個方法,但主要用于一個表單里有多個按鈕,而這些按鈕又有一個共同的名字的場合。
SwitchAction
用于子模塊之間的切換。
四.ActionForward類
Action類的excute()方法返回一個ActionForward對象,它代表了web資源的邏輯抽象,這里的web資源可以是jsp頁面、Java servlet、或Action。
從excute返回ActionForward可以有兩種方法。
1) 動態創建一個ActionForward實例
return new ActionForward(”Failure”,”login.jsp”,true);
2) 調用ActionMappin實例的findForward方法
這個方法先從action級別找,然后在<global-forwards />級別找
return mapping.findForward(“Failure”);
posted on 2009-04-05 11:19
lanxin1020 閱讀(192)
評論(0) 編輯 收藏 所屬分類:
struts1