Web框架设计与实现(一):Maverick

原创 2004年08月30日 15:54:00
 
Web框架设计与实现(一):Maverick
   

合易 (jstanghz@163.com)
中和开源工作室
2003 年 9 月

在j2ee项目工程中合理的使用web框架能有效提高工作效率,增强程序的可维护型和可扩展性。目前比较流行的是基于mvc模式的struts结构,但在开源项目的宝库中,除了struts外,还有其他许多独具匠心、性能优异的框架结构,如Maverick WebWork Spring Tapestry Turbine 等,存在自有存在的理由和价值,只有了解了其他框架的设计思想和性能特色,才能在项目实践中根据客户需求灵活选择更合适的设计框架,本文主要介绍maverick框架的设计与实现。

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、 多平台的实现。可扩展到.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的视图模板。或用模型对象生成XML,通过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);
			else
				this.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 redirect
			if (form.getDest() == null || form.getDest().trim().length() == 0)
				ctx.setModel(DEFAULT_DEST);
			else
				ctx.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框架,它的简洁易用和强大的扩展功能吸引了大批使用者。框架的选择和使用是项目开发的重要部分,要根据客户的需求和项目整体功能的要求选择合适的框架,要记住最实用的才是最好的。

关于作者

合易,中和开源工作室,jstanghz@163.com

《Redis设计与实现》读书笔记

花了几天时间把《Redis设计与实现》读完了,把一些心得记下来给大家分享。     第2章 简单动态字符串     redis里面的字符串对象都采用SDS结构实现。SDS有别于C风格的字符数组和jav...
  • bruce128
  • bruce128
  • 2015年08月08日 22:56
  • 1226

Redis设计与实现(一~五整合版)

前言 项目中用到了redis,但用到的都是最最基本的功能,比如简单的slave机制,数据结构只使用了字符串。但是一直听说redis是一个很牛的开源项目,很多公司都在用。于是我就比较奇怪,这玩意不...
  • wsliangjian
  • wsliangjian
  • 2015年05月24日 22:36
  • 2698

读《Linux内核设计与实现》我想到了这些书

从题目中可以看到,这篇文章是以我读《Linux内核设计与实现》而想到的其他我读过的书,所以,这篇文章的主要支撑点是《Linux内核》。      开始读这本书已经是很久以前的事了,不过,由于时间和精力...
  • DLUTBruceZhang
  • DLUTBruceZhang
  • 2013年08月19日 08:59
  • 9915

Android Binder设计与实现 - 实现篇

http://www.cnblogs.com/albert1017/p/3849585.html 前言       在学习Android的Binder机制时,看了http:...
  • laviolette
  • laviolette
  • 2014年07月31日 09:42
  • 1477

cache 的设计与实现

本文整理自一下两篇博客:http://my.oschina.net/ScottYang/blog/298727http://my.oschina.net/u/866190/blog/188712 C...
  • zhushuai1221
  • zhushuai1221
  • 2016年07月14日 13:58
  • 552

Redis设计与实现(黄健宏)pdf

下载地址:网盘下载 内容简介 编辑 本书[1]  主要分为四大部分。第一部分“数据结构与对象”介绍了Redis中的各种对象及其数据结构,并说明这些数据结构...
  • cf406061841
  • cf406061841
  • 2017年06月03日 23:37
  • 836

消息系统设计与实现

消息系统设计与实现 文/JC_Huang(简书作者) 原文链接:http://www.jianshu.com/p/f4d7827821f1 著作权归作者所有,转载请联系作者获...
  • moshenglv
  • moshenglv
  • 2016年07月18日 17:05
  • 5944

如何设计一个秒杀系统

什么是秒杀秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商品的特殊性,会吸引大量用...
  • suifeng3051
  • suifeng3051
  • 2016年09月21日 14:23
  • 14981

Linux内核设计与实现 原书第3版中文版pdf

下载地址:网盘下载 内容简介 编辑 《Linux内核设计与实现(原书第3版)》基于Linux 2.6.34内核详细介绍了Linux内核系统,覆盖了从核心内核系统的应用...
  • cf406061841
  • cf406061841
  • 2017年05月29日 10:00
  • 1869

搜索引擎的设计与实现(一)从零开始?

毕业狗一枚,即将步入职场。仅以此系列,记录毕业设计中遇到的问题和解决的具体思路,重点不是完整的代码,而是得到完整代码的思考过程。所以只会贴出部分代码,勿怪。专业是电子商务,除了万恶的经管大类课程,技术...
  • u010386006
  • u010386006
  • 2015年06月19日 16:26
  • 1418
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Web框架设计与实现(一):Maverick
举报原因:
原因补充:

(最多只允许输入30个字)