细谈Web框架设计与实现
mvc模式也許是軟件設計中最經典的設計模式了,Smaltalk類庫的模型 視圖 控制器三元組結構觸動了軟件設計的靈感,清晰的層次結構、明確的職責范圍、流暢的工作流程使軟件設計增添了藝術的美感。Maverick框架便隱藏著這種美感,(名字中隱含著mvc的意思)。Maverick框架致力于實現mvc模式,其1.0版本于2001年早期發布,兩名主要開發者之一的Jeff Schnitzer也是開源社區著名測試工具JuitEE的創作者,目前的最新版本是2.2。
快速開始
?
在深入探索Maverick的基本理論和設計思想之前,讓我們通過對friendbook-jsp實例的配置,快速體驗一下Maverick的功能和魅力。
1、 下載Maverick基本框架和文檔。(參考資料有下載地址)Maverick分為基本框架和擴展框架,基本框架包括在Maverick-2.2.0.zip中,擴展框架包括opt-domity、 opt-betwixt 、opt-fop、 opt-velocity、opt-perl、opt-struts 可根據需要選擇下載。
2、 解壓縮Maverick-2.2.0.zip文件,在Maverick的examples目錄下運行ant ,在build文件夾下生成friendbook-jsp.war文件。
3、 假如我們用Tomcat 4.0進行調試,拷貝 friendbook-jsp.war 文件到 tomcat-4.0/webapps目錄中,拷貝Maverick / lib目錄下的log4j.jar文件到tomcat-4.0/lib下。如果你系統的jdk版本低于1.4還須拷貝Maverick/ lib目錄下的xml-apis.jar 文件到tomcat-4.0/lib下。
4、 啟動tomcat 在瀏覽器中鍵入:http://localhost:8080/friendbook-jsp,可以看到如下界面:
根據演示流程的運轉,打開源代碼,參考本文的技術介紹,就可以開始你的Maverick探索之旅了。
?
|
功能特征:
?
Maverick宣稱集成了Struts、Webword、Cooco 中最好的特性,是一個簡潔靈活、徹底實現mvc模式的抽象框架,允許你采用不同的模板和轉換技術實現表示層邏輯。具體特性如下
5、 簡潔實用、易于理解。遵循簡潔的設計是最好實現的原則,提供給你最需要的東西。其核心層設計簡潔、功能強大、擴展性強。
6、 采用插入式擴展集成的設計思想,核心工作流程簡潔明了,能在最短的時間內以最小的學習成本理解框架的精髓。擴展模塊范圍廣、功能強、能靈活運用。
7、 完全獨立的表示層設計。根據喜好可選擇JSP(基于JSTL標準) Velocity Domify/XSLT等。
8、 可配置的轉換管道。能實現Javabean數據到XML的透明轉換,包括支持XSLT, DVSL, FOP, Perl.等的轉換。
9、 基于標準XML的配置。
10、 同時支持Struts類型的獨立控制器和Webwork類型的 "throwaway" 控制器。
11、 多平臺的實現??蓴U展到.NET和PHP.
?
|
框架結構和流程分析:
?
Maverick框架是標準的mvc模型設計,有清晰的層次結構和職責劃分,下面是其實現簡圖:
其基本工作流程表述如下:
1、 和Struts框架一樣,Maverick使用一個統一的控制器servlet作為切入點,由org.infohazard.Maverick.Dontroller類實現,定義在web.xml文件中,所有的URL都映射到Controller類上。當一個HTTP請求發送到Controller類中時Controller從/WEB-INF/Maverickl.xml中獲得配置,生成org.infohazard.Maverick.flow.Controller對象的實例,此應用控制器一般繼承ThrowawayBean2超類。在此應說明的是Maverick不同于Struts,其請求控制器通常是javabean組件,不區分控制器(Action)和命令(ActionForm)這樣做的好處是每個新控制器不必是線程安全的,不必要支持并發調用,但同時也導致控制器實例的增值。
2、 應用控制器的組件屬性通過反射從請求參數中進行設置,使用Apache Commons BeanUtil包進行填充。
3、 調用應用控制器的perform()方法,在執行過程中通過ControllerContext對象的setModle()方法設置視圖所顯示的模型對象,并且在調用了業務對象之后返回Maverick.xml中定義的視圖名稱。
4、 由setModle()方法所設置的模型對象以關鍵字"modle"放置在servlet的請求屬性中。
5、 執行JSP 或Valocity的視圖模板?;蛴媚P蛯ο笊蒟ML,通過Maverick.xml中定義的xsl文件把xml轉化成XSLT并返回到客戶端。
上述工作流程僅描述了基于ThrowawayBean2超類的應用控制器配置,而Maverick提供了四種不同應用控制器類型的擴展: ThrowawayBean2、FormBeanUser、ThrowawayFormBeanUser、ControllerWithParams,這使Maverick的工作流程可由客戶自定義,實現了框架的高度可配置性。
Web.xml配置文件
?
配置Web.xml是開發Maverick的第一步,所有的命令(commons)都以"*.m"的擴展名映射到Controller servlet中。
| <web-app><display-name>Friendbook Web Application</display-name><servlet><servlet-name>dispatcher</servlet-name><display-name>Maverick Dispatcher</display-name><servlet-class>org.infohazard.Maverick.Dispatcher</servlet-class><load-on-startup>2</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcher</servlet-name><url-pattern>*.m</url-pattern></servlet-mapping> </web-app> |
?
從上述可看出Maverick.xml文件與struts是非常相似的。
Maverick.xml配置文件
?
Maverick的配置文件與struts相比是簡介易懂的,它沒有繁瑣的DTD困擾你,一切都簡潔明了,一目了然。如下所示:(選自Maverick下載包friendbook-jsp實例)
| <?xml version="1.0"?> <!--$Id: Maverick.xml,v 1.6 2003/01/12 04:03:22 lhoriman Exp $$Source: /cvsroot/mav/Maverick/examples/friendbook-jsp/WEB-INF/Maverick.xml,v $ --> <Maverick version="2.0" default-view-type="document" default-transform-type="document"><views><view id="loginRequired" path="loginRequired.jsp"><transform path="trimOutside.jsp"/></view></views><commands><command name="welcome"><view path="welcome.jsp"><transform path="trimOutside.jsp"/></view></command><command name="loginSubmit"><controller class="org.infohazard.friendbook.ctl.LoginSubmit" /><view name="success" type="redirect"/><view name="error" path="loginFailed.jsp"><transform path="trimOutside.jsp"/></view></command> ...... </commands> </Maverick> |
?
在上述配置文件中可發現有三個基本概念需要理解:command controller view 。
- command <command>是Maverick框架的基本單元,它定義了一個Maverick應用程序在運行時的基本特征,它包含<controller> <view>等子元素,其name屬性定義了一個command元素的名字,當來自HTTP請求的URL與之匹配時,command被執行:訪問controller定義的應用控制器,返回view定義的視圖。
- Controller子元素是可選擇的,當一個command的controller子元素未定義時,其請求直接返回view定義的視圖。 controller <controller>元素包含在command中,它定義了一個執行請求的用戶類(即應用控制器),該類一般繼承自ThrowawayBean2超類,集成了struts中Action和ActionForm的功能,通過perform()方法返回view定義的視圖。Maverick也支持struts類型的單獨控制器流程??赏ㄟ^繼承FormBeanUser超類靈活配置。
-
view <view>元素定義了表示層的視圖模型,在Maverick.xml文件中它一般定義在兩個位置,1、作為Maverick的子元素,它定義了一個全局變量式的全局視圖,如
<views><view id="loginRequired" path="loginRequired.jsp"><transform path="trimOutside.jsp"/></view></views>
視圖loginRequired可被其他定義在command中的view元素訪問。其id屬性是必須指定的。它可與其他view元素的name 和ref屬性相關聯。
2、作為command的子元素。它定義了一個與command相聯系的局部視圖,可通過ref屬性與全局視圖的id屬性相關聯,訪問全局視圖。如
<command name="editSubmit"><controller class="org.infohazard.friendbook.ctl.EditSubmit"/><view ref="loginRequired"/><view name="success" type="redirect" path="friends.m"/></command>
command中的<view>有一可選元素<transform>,它用" wrapped"關鍵子與包含它的視圖集成在一起。如trimOutside.jsp中的 <c:out value="${wrapped}" escapeXml="false"/> 在運行過程中"wrapped"被包含它的welcome.jsp替換。使welcome.jsp和trimOutside.jsp集成在一起。
?
|
應用控制器的配置
?
如前所述,Maverick框架具有高度可配置性,可以實現用戶自定義流程管理,其提供的主要超類有四種: ThrowawayBean2:ThrowawayBean2繼承了Controller接口,是標準的javabean組件,它采用controller-as-modle模式,把組件屬性和控制邏輯集成在一起,充當了struts中Action和FormAction兩個角色,如下例所示:
| public class LoginSubmit extends ThrowawayBean2 {public static final String DEFAULT_DEST = "friends.m";protected String name;public String getName() { return this.name; }public void setName(String value) { this.name = value; }protected String password;public String getPassword() { return this.password; }public void setPassword(String value) { this.password = value; }protected String dest;public String getDest() { return this.dest; }public void setDest(String value) { this.dest = value; }protected String perform() throws Exception{if (!this.login(form.getName(), form.getPassword(), ctx)){return ERROR;}else {if (this.dest == null || this.dest.trim().length() == 0)this.getCtx().setModel(DEFAULT_DEST);elsethis.getCtx().setModel(this.dest);return SUCCESS;}} } |
?
LoginSubmit類用get()和set()方法定義了三個受保護的屬性:name 、password、 dest,重寫了繼承自Throwawaybean2的perform()方法,調用ControllerContext類的setModel()方法建立視圖模型,并返回視圖名稱。LoginSubmit類集成了組件屬性和控制邏輯,并以關鍵詞"modle"放置在servlet的請求屬性中。在表示層的JSP文件中以modle.xxx的表達式暴露其屬性值。如
| <td><input value="<c:out value="${model.name}"/>" name="Password" > </td> <td class="Text"><c:out value="${model.password}"/> </td> |
?
FormBeanUser:FormBeanUser類繼承ControllerSingleton接口,是單獨的控制器類,它引用定義在外部的FormBeanl類,而不是把組件屬性定義在自身,它必須是線性安全的。如果你想把模型(modle)保存在session中或不喜歡Throwawarybean2的零亂結構,可采用此控制器流程,它和Struts結構的Actions非常相似。上例的LoginSubmit類可改寫如下:
| public class LoginSubmit2 extends FormBeanUser {public static final String DEFAULT_DEST = "friends.m";protected Object makeFormBean(ControllerContext cctx){return new Form();}protected String perform(Object formBean, ControllerContext ctx) throws Exception{Form form = (Form)formBean;if (!this.login(form.getName(), form.getPassword(), ctx)){return ERROR;}else // they are now logged in...{// Target of redirectif (form.getDest() == null || form.getDest().trim().length() == 0)ctx.setModel(DEFAULT_DEST);elsectx.setModel(form.getDest());return SUCCESS;}} } |
?
其引用的Form類定義如下:
| public class Form{protected String name;public String getName() { return this.name; }public void setName(String value) { this.name = value; }protected String password;public String getPassword() { return this.password; }public void setPassword(String value) { this.password = value; }protected String dest;public String getDest() { return this.dest; }public void setDest(String value) { this.dest = value; }} |
?
在JSP文件中可如下調用:
| <input value="<c:out value="${model.form.name}"/>" name="Password" >ThrowawayFormBeanUser:此類是ThrowawayBean2和 FormBeanUser類的混血兒,它即遵循ThrowawayBean2的流程又準許調用外部的FormBean類。ControllerWithParams:帶有參數訪問的控制類。如: <controller class="Login"> <param name="secure" value="true"> </controller> |
?
通過這四種控制器類型的擴展,Maverick框架提供了靈活的流程控制,最常用的是擴展ThrowawayBean2類的控制流程,但熟悉Struts框架的讀者可能對實現FormBeanUser的擴展更親切一些。Maverick下載包中包含了friendbook-jsp和friendbook-jsp-fbu兩個實例分別實現了擴展ThrowawayBean2和FormBeanUser的流程控制,讀者可根據源碼細心體會。
?
|
視圖表示
?
與Struts綁定與jsp視圖不同,Maverick支持多視圖表示,避免了控制層與表示層的緊耦合,使表示層的職責更加清晰明確。Maverick支持JSP Velocity XSLT等視圖模板。
JSP:
?
JSP是使用最廣的視圖模板,它具有強大的表示和控制功能,在Modle1的設計框架中承擔了關鍵角色。但在Maverick框架中它被限制在視圖表示的職責范圍內。Maverick支持JSP的標準標簽庫JSTL,不提供自身的特殊標簽庫,降低了學習難度,避免了框架對專有知識的依賴。
在Maverick中實現JSP是非常簡單的,在Maverick.xml配置文件中如下設置:
| <Maverick version="2.0" default-view-type="document" default-transform-type="document"><views><view id="loginRequired" path="loginRequired.jsp"><transform path="trimOutside.jsp"/></view></views> |
?
Maverick元素的default-view-type屬性設置為"document",以便訪問JSP文檔,JSP通過放置在servlet請求屬性中的modle關鍵字引用控制器類的屬性和方法。
Velocity:
?
Velocity是jakarta apach的開源項目,它是一個純粹的模板引擎,不依賴于servlet API,可用于除web程序之外的其他應用,并可在servlet容器外部測試。Velocity的核心是Velocity Template Language(VTL),該模板語言的屬性導航語法與JSP的JSTL差不多,易于學習和理解。
Velocity是一種簡單而高性能的模板語言,能有效暴露控制器類的屬性和方法,實現控制器邏輯和視圖模板的徹底分離。在Maverick中實現Velocity也很簡單,首先在web.xml配置文件中注冊VelocityViewServlet,如:
| <servlet><servlet-name>velocity</servlet-name><servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class><load-on-startup>10</load-on-startup></servlet><servlet-mapping><servlet-name>velocity</servlet-name><url-pattern>*.vm</url-pattern></servlet-mapping> |
?
其次,在Maverick.xml配置文件中,設置Maverick元素的default-view-type屬性設置為"document", 如JSP一樣通過放置在servlet請求屬性中的modle關鍵字暴露控制器類的屬性和方法。(Maverick下載包中不包括velocity,可另下載opt-velocity擴展包)。
XSLT
?
XSLT是XML轉換語言,純粹是為轉換數據而設計的,在web應用中常用于XML數據的轉換,但不能用來處理用戶請求。Maverick對XSLT的支持是通過opt-domify擴展包實現的,Domify利用java反射實現model模型到DOM的適配。實現JavaBean數據到XML的透明轉換,是Maverick的特點之一,現在Maverick的數據轉換庫是一個獨立的開源項目。另外,Maverick還提供一個可配置的轉換管道,可配合XSLT一起使用。(opt-domify擴展包有一friendbook實例,讀者可深入研究)。
?
|
可擴展的功能模塊:
?
強大的擴展功能是Maverick吸引人的特性之一,可插入式的擴展模塊,是實現此功能的關鍵。與eclipse的plug-in相似,Maverick核心層提供了可配置的模塊接口機制,可選的擴展模塊能根據客戶需求提供靈活的解決方案。在Maverick下載頁中提供的可擴展模塊主要包括:
opt-domify:Domify原是Maverick框架的一部分,提供JavaBean組件到 W3C DOM 表示層的適配,避免了生成XML文本的中間環節。現在Domify已從Maverick中獨立出來,成為另一開源項目。如果用Domify和XSLT作為視圖表示層,可選擇opt-odomify擴展包。
Opt-betwixt:Betwixt能從JavaBean組件中生成一系列SAX事件,可代替Domify成為XSLT表示層的另一選擇。
Opt-fop:提供Apache FOP服務,Apache FOP能把XSL-FO(XSL格式化對象)轉化成多種表現格式,如PDF和Postscript .用opt-fop擴展包你能用XSLT把模型轉化為XSL-FO,然后再轉化為PDF或其他格式表現出來。
Opt-Velocity:支持Velocity視圖模板的功能包,Velocity的使用如上文所述。
Opt-perl:提供了一個通過Perl運行的Maverick轉化類型。
Opt-Struts:提供一系列把Struts應用程序轉化到Maverick框架的工具。
?
|
總結:
?
與Struts相比,Maverick提供了一個更加靈活的輕量型web框架,它的簡潔易用和強大的擴展功能吸引了大批使用者??蚣艿倪x擇和使用是項目開發的重要部分,要根據客戶的需求和項目整體功能的要求選擇合適的框架,要記住最實用的才是最好的。
關于作者
| ? | 合易,中和開源工作室, jstanghz@163.com。 | |
總結
以上是生活随笔為你收集整理的细谈Web框架设计与实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 摄像机投射投影模型_综述及详解
- 下一篇: 各向异性扩散滤波_原理与算法