Tapestry
目录
Tapestry是一个用java编写的基于组件的web应用开发框架。它不仅仅是一个模板系统,更是一个建立在Java Servlet API基础上的动态交互式网站的开发平台。不同于普通的模板系统,它是一个真正使用简单,可重用的组件开发复杂应用的框架。框架自身完成了把许多在创建web应用时容易出错并且极为乏味的工作,诸如分派请求,构造与解析URLs信息,处理国际化和本地化数据等。
Tapestry的“理念”就是“对象,方法,属性”。也就是说,Tapestry使开发者只需将注意力放在对象(包括Tapestry的页面和组件,也包括应用程序的领域对象),方法和JavaBeans属性上。而不是迫使开发者关注像requests, responses, sessions, attributes, parameters, URLs这样的Servlet API。在Tapestry应用程序里,所有用户动作(点击链接和提交表单)的结果是对象的属性被更新和用户方法被触发(包含业务逻辑的用户代码)。Tapestry会管理或添加必要的操作,使用户动作和对应的对象关联起来。
这就表明你不必在Tapestry程序里写servlets,你需要的是写监听方法(listerner methods)。你也不用为servlets构造URLs。通过使用现有的组件(像DirectLink)并为它注册一个监听函数,组件便会触发你的监听函数。那么监听函数又是什么呢?监听函数可以和其它后台系统交互(通常是stateless session EJBs)或做一些处理之后选择一个新的页面用于显示。通常,这些工作是某个servlet的核心代码。在Tapestry里,你不用写那些烦人而又机械化的代码(像构造URLs,分派请求,管理服务器端状态等),这些框架都会提你解决。
这并不是说Servlet API不重要;但是一般情况下Tapestry的使用者不用关心这些。
经过最近几年这段漫长的时间,Tapestry已经升级到4.0版本。虽然有许多对XHTML, WML和其它标示的支持,但是Tapestry关注的重点仍然是生成动态HTML页面。
几乎所有的Tapestry的API都用接口描述,并提供了默认实现。通过使用继承了正确接口的对象来替换默认对象,就可以使Tapestry的行为发生极大的改变。一个常用的例子是重写页面和组件存储位置的逻辑(比如说保存在数据库中)。
Tapestry将应用程序分为一系列页面,每个页面都有一系列组件组成。组件自身又可由一系列其它组件组成,而且对组件的没有递归深度的限制。
Tapestry的页面本身也是一种组件,只不过多了一些特殊的工作。
所有组件都能被其它组件包含。页面和大多数用户定义的组件都有一个模板。模板是一个特定的HTML文件,定义了组件的静态和动态部分,通过标记还可以确定嵌套的组件是否活跃。但是,组件并不必须拥有模板,大多数Tapestry提供的组件通过代码生成他们的HTML标签而不是使用模板。
组件可以拥有一个或多个拥有确定名称的参数。这些参数可以是被包含它的页面或组件使用(或者更确切的讲是绑定)。和Java函数的参数不同的是,组件的参数可以是双向的。一个组件可以在获取数据时读取某个参数,在更新数据时更新参数。
大多数组件只关心如何创建HTML标签。一部分的组件会处理与请求相关的事情;处理传入的请求。比如PageLink、DirectLink和ActionLink等Link类,在显示页面时会在页面创建一个链接标签,在用户点击链接时会处理部分与分派用户请求到指定用户代码的工作。
其它组件,如Form和由Form控制的组件(TextField,PropertySelection,Checkbox等),使HTML的表单使用变得简单。在这些组件显示的时候,他们会读取应用的领域对象的属性来构造默认数据。当表单提交的时候,表单中的组件会读取HTTP的请求参数,并将这些数据转化为合适的类型并更新到领域对象。
引擎,服务和友元
随着时间的推移,Tapestry有了属于它的术语。
引擎是核心对象,在Tapestry程序里它充当的角色就像HttpSession在Servlet API里做的一样。引擎最终会保存到HttpSession里。因此,保存应用程序中需要持久化的状态(需要在不同请求中保存的数据)最终会由引擎负责。本文将主要讨论默认的实现,并会提示一些在扩展或重写引擎时需要注意的事项。
引擎服务是连接servlets,URLs和其他框架逻辑的桥梁。引擎服务负责编码和解码URLs,为框架提供在链接被触发时(当用户点击链接或提交表单)能够唯一确认对应操作的参数。同时,服务也负责分派这些请求。用一个对象封装对URL的编码和解码功能是Tapestry的一个关键技术。这样组件能在不知道它们是如何被使用,包含在哪一个页面的情况下进行复杂的工作(在构造URLs的时候服务将会处理页面的具体位置)。
Visit对象是一个在应用程序中定义的对象,扮演者服务器端状态保存者的关键工作(并不是仅被某一个页面处理的数据)。不同的应用程序可以根据需要定义自己的Visit类。Visit对象会作为引擎的一个属性保存,所以最终会持久化的保存在httpSession中。
Global对象也是一个与应用程序相关的对象。它保存的是一个用于应用全局的数据,而不是对应于某一个特定用户或会话的数据。一个常用的例子是为使用JDNI查找session EJBs的方法提供一个统一的逻辑。
对象图导航语言(Object Graph Navigation Language)。
Tapestry和对象图导航语言(OGNL)是紧密联系的。OGNL是一个Java的表达式语言,它能深入一个对象读取或更新他们的数据。OGNL类似与包含在JSP2.0中的表达式语言,但是它具有更强的功能。OGNL不仅支持获取属性,它还能处理数学表达式和方法调用等,访问public class的静态属性,动态创建包括链表和map在类的对象。
最简单的OGNL表达式只包含属性的名称,比如foo对应于使用getFoo()方法(或者对应于表达式用于更新属性时的setFoo()方法)。导航的功能体现在当表达式是一串属性名时,比如foo.bar.baz对应于使用getFoo().getBar().gatBaz()。值得注意的是处于表达式中间的属性(这个例子中的foo和bar)不能为空的。
OGNL主要是用于让不同的对象(比如一个页面和同一个页面中的一个组件)共享数据。
虽然早在2000年就开始做宣传,但是Tapestry还是在社区反馈的推动下不断的进行着改进。在2003年Tapestry获得了很大的成功。在这段时间里Tapestry项目从SourceForge迁移到Jakarta。同时从2.3版升级到了3.0版(3.0版最终是在2004年4月发布)。
Tapestry 3.0的设计在根本上改变了Tapestry应用的创建方式。它提供了一种RAD(快速应用开发)方法。用一种JSP和PHP开发人员熟悉的方式在HTML模板中定义组件的类型和参数。
Tapestry 3.0 还提供了错误行精确定位的支持。当程序在运行时发生错误,HTML模板或定义文件中的相关错误行将会显示出来。更重要的是,3.0版提供了<property>属性并使用字节码生成技术在后台支持。
Tapestry 4.0 比3.0作了更大的修改。使用了建立在HiveMind基础上的一个新的,更成熟的基础设施。这个新的骨干技术为Tapestry日益壮大的社区提供了更多的必要支持。包括友好的URLs(允许使用文件夹,这样就可以使用J2EE的申明式安全机制),整合Tapestry和Java Portlet API,模块化应用程序等。另外,采用了更加成熟的参数连接技术和更灵活的持久化数据保存方式(使用HTTP请求参数保存数据)。对于JDK1.5的用户,更可以使用Java注释技术(annotations)代替XML技术来申明组件和页面。
Tapestry 5.0将会重新考虑组件对象模型。这样你编写的类就不必从Tapestry的类继承。页面和组件的类将都是POJOs(普通Java对象),Tapestry所需要的依赖关系则会被注入进去。
Tapestry在整个环境中的位置;应用程序由可复用组件构成的页组成。应用程序运行在应用服务器中。对应用服务器而言,Tapestry应用只不过是其他类型的servlet而已。
Web应用通常按照三个层面来实现,每一个层面都针对应用中不同的问题。
展现层的职责是负责接受请求和产生HTML的响应;
应用层的职责是负责所有的业务逻辑;这一层通常用EJB来实现;
数据库层的职责是负责持久地存储数据;
Tapestry仅仅是展现层的应用,或者说Tapestry仅仅是将处理好的信息展现给终端用户,如HTML,以及处理来自链接和HTML表单输入。Tapestry不知道或者不关心应用层、域逻辑层、或者信息的来源。一个Tapestry应用程序可以建立在平面文件数据库、可使用JDBC存取的关系数据库以及分布在世界上各个网络上的EJB之上。Tapestry对你的应用没有任何要求,它只是关注展现层是如何组织的。
Tapestry框架填充了web应用开发中隐藏的缝隙:它提供了一个与开发人员相关的一致的框架。通常,每个开发人员自行管理他或者她开发的部分取忽略了其他的工程纪律从而使得项目承担更大的风险。
可是,许多Web应用应用的开发仍然和上面描述的相似的混乱情况下被开发着。说明不完整;不同的开发人员以不同的方法处理类似的问题。一些开发人员不注意项目中的重要细节或者web开发中比较次要的细节。由于技术的不同,一些开发人员擅长些客户端的javascript,其他的则擅长于后台系统的交互开发-但是项目管理者常常认为这些人是完全可以互换的。最常见的是,项目的成功或失败担子在最后完全落在“全垒打团队“的肩膀上,他们不得不在剩余的时间里将所有的代码片断粘在一起。
继续以前边的比方为例。不管怎样,工人都是从管道和布线已经完成的空楼层开始工作。所有的事情都变成安装仅仅用于该层的固件的工作,项目的最后这些东西将会被正确的组装起来。把楼层看作页面,把固件看作组件,把安装看作配置,你就能理解了Tapestry给开发人员提供的东西了。
Tapestry在解决开发问题上不是一个万能药;然而,它提供了一个描述Web应用项目实现和由不同开发人员提供的元素之间交互的一致的方法。Web应用程序没有电梯轴线,但它们可以有,如统一的导航条,或嵌入的查询表格,或统一的登陆按钮。这些元素都能实现成Tapestry组件,单独地测试,并在每一个页面上重用,这样就能保证一致的外观和一致的交互行为。
Tapestry具有很高的代码复用性,在Tapestry中,任何对象都可看作可复用的组件。JSP开发者是真正面向对象,而不是URL解析。对于对页面要求灵活度相当高的系统,Tapestry是第一选择。精确地错误报告,可以将错误定位到源程序中的行,取代了JSP中那种编译后的提示。
因此,笔者一直对Tapestry情有独钟:如果技术允许,使用Tapestry会带给整个应用更加优雅的架构,更好的开发效率。
但是,在实际开发过程中,采用Tapestry也面临着一些问题必须考虑:
— Tapestry的学习曲线相对陡峭,国内开发群体不是非常活跃,文档不是十分丰富。官方的文档太过学院派,缺乏实际的示例程序。
— Tapestry的组件逻辑比较复杂,再加上OGNL表达式和属性指定机制,因而难以添加注释。
1、Tapestry是一个全面web application框架,是使用JAVA写的。
2、Tapestry不是一个application server,Tapestry是一个使用在application server中的框架。
3、Tapestry不是一个application,Tapestry是一个用来创建web application的框架。
4、Tapestry不是JSP的一种使用方式,Tapestry和JSP只能够选择一种。
5、Tapestry不是一个脚本环境,Tapestry使用一种组件对象模式(component object model),这并不是一种简单的脚本,而是用于生成高动态性高互交性的web页面。
Tapestry基于Java Servlet API version 2.2,兼容于JDK 1.2以上版本,Tapestry通过变换多样的组件模式,将一个web application分离为一个联合组件。每一个组件都拥有其特殊的责任用于显示web页面或者响应HTML请求。
附件列表
故事内容仅供参考,如果您需要解决具体问题
(尤其在法律、医学等领域),建议您咨询相关领域专业人士。
如果您认为本故事还有待完善,请 编辑
上一篇 中国计算机行业协会 下一篇 中国人民政治协商会议全国委员会民族和宗教委员会