Introduction to Jakarta Tapestry(Tapestry入门)
by Rob Smith , Senior Software Engineer Object Computing, Inc. (OCI)
原作(original): http://www.ociweb.com/jnb/jnbMay2004.html
翻译:Hery Tang (hery1977@hotmail.com)
原文:http://www.javatx.cn/clubPage.jsp?ccStyle=0&tID=1396&ccID=9
简介
Jakarta Tapestry是一个开源的Java Web应用框架。你或许会说:"大同小异的东西罢了."多数
情况下,我同意你的观点,然而,只要花上些许时间研究一下,你会发现Tapestry跟别的框架大为不同,它是值得严肃对待的。
Tapestry是一个基于控件的框架以致于用它开发Web应用类似开发传统的GUI应用。你用Tapestry开发Web应用时你无需关注以操作为中心的(operation-centric) Servlet API.引用Tapestry网站上的一句话:"Tapestry用对象(objects),方法(methods),属性(properties)替代以往的URLs和查询参数, 重新诠释Web应用开发.Tapestry 3.0即将发布,它有大量的改进和新的特性。
Tapestry的目标
简单性
Tapestry应用与传统的Servlet应用相比代码量更少。大多数传统的Servlet应用包含如下厌烦和
重复的任务:解析查询参数,处理HttpSession对象,构建URLs。Tapestry消除了传统Servelt应用中许多无趣的"衔接"代码("plumbing" code)使开发者把精力集中到应用逻辑上来。
一致性
Tapestry为开发Web应用的页面提供了一致的方式。这样有助于消除传统Servlet应用开发中臆测。由于所有Tapestry应用中的页面都是用相同的可复用的控件组织而成,所以工作方式是相似的。
效率
Tapestr应用拥有高度的可升级性,它利用缓存和对象池使每个请求的处理时间最小化。Tapestry应用拥有跟传统Servlet应用相仿的性能。
错误反馈
任何开发过Servlet/JSP应用的人毫无质疑有类似经历:为了找出Web.xml文件有什么错误,不得不花费大量时间察看浏览器中的堆栈信息。Tapestry拥有优秀的错误报告方式,最值得一提的是它会指出哪个文件以及那一行导致了错误。
与Struts比较
既然Apache Struts可能是当今应用最广泛的Web应用框架,拿Tapestry与它比较是唯一公平的。以下是一些观察比较,它们来源于为这篇文章开发的几个简单的Tapestry应用和为几个Struts工程的工作经历。
Struts的优点
1 一个Servlet/JSP开发者熟悉Struts无需太久。然而Tapestry的学习曲线会长一点,因为它与流行的Web应用框架不太相同 。
2 Struts在Java社区里被广泛接受和使用。为你的项目找一个好的Struts开发人员并非难事,Tapestry近来在开发者社区里 赢得一些关注,然而仍有许多Java老手不知道Tapestry为何物。
3 既然Struts被如此广泛的使用,所以有很多Struts资源可供参考。相比大多数开源软件,Tapestry拥有非常可观的资源和文档,但跟Struts相比仍有差距。
Tapestry的优点
1 你开发一个Tapestry应用无需关注Servlet API,你也无须为你的Servlet应用写一些典型的"衔接"代码。虽然Struts简化了工作,然而Servlet API 仍是你需面对的。
2 Tapestry的页面模板除了几个特别属性和标识就是一个标准的HTML文件。 如果你是一个开发小组中的HTML设计高手,然而你不懂Java或JSP,这就给你带来很大方便。
3 因为Tapestry页面是标准的HTML,所以可以用HTML所见即所得(WYSIWYG)编辑器编辑和预览该页。当一个页需要修改它的外观并不需要通知服务器让它重新编译JSP.
4 Tapestry不需要一个至高的,整个应用范围的配置文件。Tapestry应用中的每一页是独立的,改变一页不会影响开发其他 页面的开发者,因为并没有一个配置文件把所有页面的浏览粘连在一起。
5 Tapestry拥有极好的错误报告。如果你在一个页的模板或页面规范犯了一个错误,Tapestry会指出导致错误的行号。
6 用Tapestry开发是种乐趣。这样说听上去似乎老调,然而用Tapestry开发一个Web应用相比应用其他流行的框架更为自然有趣。用Tapestry开发是应用了一种基于控件的架构,与开发传统的GUI应用非常相似。
Tapestry 架构
Tapestry框架是标准Servlet API的一种扩展。它需要J2SDK1.2或更高版本的J2SDK和一个与Servlet API 2.2(或更高)兼容的应用服务器/Servlet容器。
一个Tapestry应用由许多拥有唯一名称的页面组成。一个页面由一个模板和一些可复用的控件构成。模板由标准的HTML标签和一些额外的属性和标签构成,这些额外的属性和标签是为了告诉Tapestry框架这个页面的那些部分是由Tapestry控件组成。
简单的Tapestry应用
为了最好的描述构建一个Tapestry页面的方方面面,我们可以看看这个Pig Latin翻译器应用的代码。这个应用只有一个页面,在这页里输入一个text值把它翻译成Pig Latin,然后把翻译好的值显示给用户。
在Tapestry应用中每个页由3个部分组成:一个HTML模板,一个页面规范文件,一个Java类。
这里有这个页面屏幕抓图:
页面模板由标准的HTML标签和一些额外的属性和标签构成,这些额外的属性和标签是为了告诉Tapestry框架这个页面的那些部分是由Tapestry控件组成。页面模板存放在Web应用的根context目录下。通常,Tapestry在启动时会寻找和呈现一个名叫"Home"的页。虽然我们可以改变这种行为,但依照Tapestry的惯例会更简单。
Home.html
<html>
<head>
<title>Tapestry Pig Latin Translator</title>
</head>
<body>
<h1>Pig Latin Translator</h1>
<form jwcid="@Form"① listener="ognl:listeners.submit"②>
<table border="1">
<tr>
<td>Value to Translate:</td>
<td>
<input type="text" jwcid="@TextField"③ value="ognl:inputValue"/>
</td>
</tr>
<tr>
<td>Pig Latin:</td>
<td>
<jwcid="@Insert"④ value="ognl:pigLatinValue"/>
</td>
</tr>
</table>
<input type="submit" jwcid="@Submit"⑤ value="Translate"/>
</form>
</body>
</html>
页面模板的绝大部分是普通的HTML,只有少部分Tapestry特有的属性和标签。这种模板机制的优势就是Tapestry页面模板可以在一个可见即所得的编辑器里创建和预览。描述Tapestry控件部分的标识是有限的和突出的。
标识里的jwcid所指是被应用的Tapestry控件的Java Web Component ID.在上面代码断里,我们是隐式地使用控件。隐式的控件是指直接在页面模板里声明使用的控件,。jwcid的前缀 '@ '符号就是通知Tapestry这里声明使用了一个隐式控件。
在上面的Pig Latin Translator页面模板里用了四个控件:Form①, TextField③, Insert④ 和Submit⑤。它们只是Tapestry框架提供的包含超过40个控件的控件库里的四个。在后面的范例中,我们将会看到如何使用显式控件。显式控件是指控件在页面规范文件里声明后再使用的控件。
在前面的HTML模板里,使用控件的同时,也为控件指定了参数。例如控件Form①有一个listener②参数它指定了当表单提交时对应的页面类调用的方法名称。那个ognl:前缀的使用贯穿页面的HTML模板,指向的是Object Graph Navigation Language (OGNL)。OGNL是一个强大的开源的表达式语言,用于将页面内控件的属性绑定到页面类的属性。
现在我们看看页面规范文件。页面规范文件是一个扩展名为page的XML文件,这个文件有许多职责,在众多职责中最基本是指定页面对应的Java类。页面规范文件存放在webapp的WEB_INF目录。
Home.page
<?xml version="1.0"?>
<!DOCTYPE page-specification PUBLIC
"-//Apache Software Foundation//Tapestry Specification 3.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>;
<page-specification class="Home">
<property-specification name="inputValue" type="java.lang.String"/>
<property-specification name="pigLatinValue" type="java.lang.String"/>
</page-specification>
页面规范文件的根元素有一个class的属性,它指定了这个页对应的Java类。这个类必须要实现org.apache.tapestry.Ipage接口。页面规范同时页定义了两个属性(property)元素,以便Tapestry在页面类里创建新的属性。
Tapestry框架提供了org.apache.tapestry.html.BasePage class,它实现了Ipage接口。页面类被存放在Web-INF/classes目录下,跟你的Web应用的所需要的其他类放在一起。
Home.java
import org.apache.tapestry.html.BasePage;
import org.apache.tapestry.IRequestCycle;
public abstract class Home extends BasePage {
public abstract String getInputValue();
public abstract void setInputValue(String inputValue);
public abstract String getPigLatinValue();
public abstract void setPigLatinValue(String pigLatinValue);
public void submit(IRequestCycle cycle) {
String inputValue = getInputValue();
String pigLatinValue = new PigLatinTranslator().translate(inputValue);
setPigLatinValue(pigLatinValue);
}
}
你要提醒的第一件事或许是这个类为什么是抽象类。它还有几个抽象方法访问inputValue,pigLatinValue属性。这里利用了Tapestry会在运行时刻创建子类的功能,这个子类会创建你在页面规范里声明的属性和生成相应的访问方法。
在表单提交时页面类的submit方法会被调用。为什么会这样?因为我们在页面模板里将Form控件的listener属性指定为:ognl:listeners.submit。这就意味着一个名叫submit的listener会通过页面类的listeners被访问。
所有的页面类和控件类都从org.apache.tapestry.AbstractComponent这个类继承来一个叫listeners的属性。当submit方法完成后,页面会显示被翻译好的词。
最后讲讲Web.xml这个Web发布描述文件。Tapestry,像许多其他的流行的Web应用框架一样,由一个Servlet构成,但是还需要一个发布描述文件。那个发布描述文件应该被存放在WEB-INF目录。
web.xml
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd>;
<web-app>
<display-name>Tapestry Pig Latin Translator</display-name>
<servlet>
<servlet-name>tapestry</servlet-name>
<servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>tapestry</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>
</web-app>
虽然Pig Latin翻译应用非常简单,但是它会让你对在Tapestry应用中一个页面的3个组成部分有了基本的了解。它也展示了创建一个Tapestry应用的一个页面只需写多么少的代码。
表单输入验证
Tapestry 提供了一些控件以便校验用户的输入。校验子系统是ValidField控件的核心。在下面的登录应用中我们将使用ValidField控件。ValidField控件位于表单内,对用户在客户端的校验提供了有用的反馈和视觉上的错误提示。
区域化
在Tapestry中,区域化是相当简单的。Tapestry允许文字和图形的区域化。为了区域化页面的内容,你可以为每一个添加一个properties文件,或者提供一个区域化的模板。为每个页面提供一个资源文件的方式远比管理和维护一个巨大的全局的应用范围的资源文件简单。如果页面的区域化并不仅仅只是文字信息的区域化,例如页面的布局不同或者组成的控件不同,这样情况提供区域化的页面模板就能派上用场了。我们会在下面的登录应用的使用Tapestry区域化。
创建控件
Tapestry发布时提供了40多个自带的控件。如果你想知道更多的关于Tapestry自带控件的信息,请参考Tapestry Component Reference.想看看Tapestry的控件的应用范例可访问Tapestry Component Workbench.如果你发现你需要一个Tapestry本身没提供的控件,你可以自己创建一个。创建你自己的Tapestry控件跟创建一个页面是相似的。一个典型的Tapestry控件由一个控件规范文件(XML文档),一个HTML控件模板,一个实现了org.apache.tapestry.Icomponent接口的Java类。这个议题有点超出本文的范围,但是如果你有兴趣学习如何创建你自己的Tapestry控件,你可以参考Tapestry的原创人,Tapestry In Action 一书的作者--Howard Lewis Ship写的 Designing Tapestry Mega-Components 。