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