簡介 我見過許多項目開發者實現自己專有的MVC框架
這些開發者並不是因為想實現不同於Struts的某些功能
而是還沒有意識到怎麼去擴展Struts
通過開發自己的MVC框架
你可以掌控全局
但同時這也意味著你必須付出很大的代價
在項目計劃很緊的情況下也許根本就不可能實現
Struts不但功能強大也易於擴展
你可以通過三種方式來擴展Struts:
PlugIn
在應用啟動或關閉時須執行某業務邏輯
創建你自己的PlugIn類
RequestProcessor
在請求處理階段一個特定點欲執行某業務邏輯
創建你自己的RequestProcessor
例如
你想繼承RequestProcessor來檢查用戶登錄及在執行每個請求時他是否有權限執行某個動作
ActionServlet
在應用啟動或關閉或在請求處理階段欲執行某業務邏輯
繼承ActionServlet類
但是必須且只能在PligIn和RequestProcessor都不能滿足你的需求時候用
本文會列舉一個簡單的Struts應用來示范如何使用以上三種方式擴展Struts
在本文末尾資源區有每種方式的可下載樣例源代碼
Struts Validation 框架和 Tiles 框架是最成功兩個的Struts擴展例子
我是假設讀者已經熟悉Struts框架並知道怎樣使用它創建簡單的應用
如想了解更多有關Struts的資料請參見資源區
PlugIn 根據Struts文檔
PlugIn是一個須在應用啟動和關閉時需被通知的模塊定制資源或服務配置包
這就是說
你可以創建一個類
它實現PlugIn的接口以便在應用啟動和關閉時做你想要的事
假如創建了一個web應用
其中使用Hibernate做為持久化機制
當應用一啟動
就需初始化Hinernate
這樣在web應用接收到第一個請求時
Hibernate已被配置完畢並待命
同時在應用關閉時要關閉Hibernate
跟著以下兩步可以實現Hibernate PlugIn的需求
創建一個實現PlugIn接口的類
如下
public class HibernatePlugIn implements PlugIn{ private String configFile; // This method will be called at application shutdown time public void destroy() { System
out
println(
Entering HibernatePlugIn
destroy()
); //Put hibernate cleanup code here System
out
println(
Exiting HibernatePlugIn
destroy()
); } //This method will be called at application startup time public void init(ActionServlet actionServlet
ModuleConfig config) throws ServletException { System
out
println(
Entering HibernatePlugIn
init()
); System
out
println(
Value of init parameter
+ getConfigFile()); System
out
println(
Exiting HibernatePlugIn
init()
); } public String getConfigFile() { return name; } public void setConfigFile(String string) { configFile = string; }}
實現PlugIn接口的類必須是實現以下兩個方法
init() 和destroy()
在應用啟動時init()被調用
關閉destroy()被調用
Struts允許你傳入初始參數給你的PlugIn類
為了傳入參數你必須在PlugIn類裡為每個參數創建一個類似JavaBean形式的setter方法
在HibernatePlugIn類裡
欲傳入configFile的名字而不是在應用裡將它硬編碼進去
在struts
condig
xml裡面加入以下幾行告知Struts這個新的PlugIn
<struts
config>
<!
Message Resources
> <message
resources parameter=
sample
resources
ApplicationResources
/> <!
Declare your plugins
> <plug
in className=
com
sample
util
HibernatePlugIn
> <set
property property=
configFile
value=
/hibernate
cfg
xml
/> </plug
in></struts
config>
ClassName屬性是實現PlugIn接口類的全名
為每一個初始化傳入PlugIn類的初始化參數增加一個<set
property>元素
在這個例子裡
傳入config文檔的名稱
所以增加了一個config文檔路徑的<set
property>元素
Tiles和Validator框架都是利用PlugIn給初始化讀入配置文件
另外兩個你還可以在PlugIn類裡做的事情是
假如應用依賴於某配置文件
那麼可以在PlugIn類裡檢查其可用性
假如配置文件不可用則拋出ServletException
這將導致ActionServlet不可用
PlugIn接口的init()方法是你改變ModuleConfig方法的最後機會
ModuleConfig方法是描述基於Struts模型靜態配置信息的集合
一旦PlugIn被處理完畢
Struts就會將ModuleCOnfig凍結起來
請求是如何被處理的 ActionServlet是Struts框架裡唯一一個Servlet
它負責處理所有請求
它無論何時收到一個請求
都會首先試著為現有請求找到一個子應用
一旦子應用被找到
它會為其生成一個RequestProcessor對象
並調用傳入HttpServletRequest和HttpServletResponse為參數的process()方法
大部分請處理都是在RequestProcessor
process()發生的
Process()方法是以模板方法(Template Method)的設計模式來實現的
其中有完成request處理的每個步驟的方法
所有這些方法都從process()方法順序調用
例如
尋找當前請求的ActionForm類和檢查當前用戶是否有權限執行action mapping都有幾個單獨的方法
這給我們提供了極大的彈性空間
Struts的RequestProcessor對每個請求處理步驟都提供了默認的實現方法
這意味著
你可以重寫你感興趣的方法
而其余剩下的保留默認實現
例如
Struts默認調用request
isUserInRole()檢查用戶是否有權限執行當前的ActionMapping
但如果你需要從數據庫中查找
那麼你要做的就是重寫processRoles()方法
並根據用戶角色返回true 或 false
首先我們看一下process()方法的默認實現方式
然後我將解釋RequestProcessor類裡的每個默認的方法
以便你決定要修改請求處理的哪一部分
public void process(HttpServletRequest request
HttpServletResponse response) throws IOException
ServletException { // Wrap multipart requests with a special wrapper request = processMultipart(request); // Identify the path component we will // use to select a mapping String path = processPath(request
response); if (path == null) { return; } if (log
isDebugEnabled()) { log
debug(
Processing a
+ request
getMethod() +
for path
+ path +
); } // Select a Locale for the current user if requested processLocale(request
response); // Set the content type and no
caching headers // if requested processContent(request
response); processNoCache(request
response); // General purpose preprocessing hook if (!processPreprocess(request
response)) { return; } // Identify the mapping for this request ActionMapping mapping = processMapping(request
response
path); if (mapping == null) { return; } // Check for any role required to perform this action if (!processRoles(request
response
mapping)) { return; } // Process any ActionForm bean related to this request ActionForm form = processActionForm(request
response
mapping); processPopulate(request
response
form
mapping); if (!processValidate(request
response
form
mapping)) { return; } // Process a forward or include specified by this mapping if (!processForward(request
response
mapping)) { return; } if (!processInclude(request
response
mapping)) { return; } // Create or acquire the Action instance to // process this request Action action = processActionCreate(request
response
mapping); if (action == null) { return; } // Call the Action instance itself ActionForward forward = processActionPerform(request
response
action
form
mapping); // Process the returned ActionForward instance processForwardConfig(request
response
forward); }
processMultipart(): 在這個方法中
Struts讀取request以找出contentType是否為multipart/form
data
假如是
則解析並將其打包成一個實現HttpServletRequest的包
當你成生一個放置數據的HTML FORM時
request的contentType默認是application/x
www
form
urlencoded
但是如果你的form的input類型是FILE
type允許用戶上載文件
那麼你必須把form的contentType改為multipart/form
data
如這樣做
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28376.html