一、TAPESTRY技术的综述。

tapestry是平行于struts/Spring MVC/webwork /jsf等开发工具的语言。tapestry是基于组件的开发工具。它具有组件的可重用性。因为大量重复使用的Tapestry组件,以及高度复用的表现层逻辑,使得工作效率大幅度提升。Tapestry组件是一个“黑盒子”,用于表现HTML响应,以及响应HTTP请求。

Tapestry组件通过其规范定义。规范是一个XML文档,其中定义了组件类型,参数,组件模板,包含的组件以及被包含组件之间的联系,还有所有的assets。

Tapestryde:优点:

1) 能够保证对HTML最少限度的干扰,Tapestry对HTML页面的介入可以仅仅是增加一个jwcid(Java Web Component ID)属性。这个明确地划分了美工和程序员之间的界限。

2) 页面的描述基于组件, Page规范描述了组件之间的联系,而java文件负责处理逻辑。

3) 由于表现层逻辑全部放在了java文件里面,相比JAVA SCRIPT描述更加灵活

 4) 随着我们项目的深入开展,可复用的组件逻辑越来越多,开发的效率大大提高

Tapestry框架是标准Servlet API的一种扩展。它需要J2SDK1.2或更高版本的J2SDK和一个与Servlet API2.2(或更高)兼容的应用服务器/Servlet容器。

一个Tapestry应用由许多拥有唯一名称的页面组成。一个页面由一个模板和一些可复用的控件构成。模板由标准的HTML标签和一些额外的属性和标签构成,这些额外的属性和标签是为了告诉Tapestry框架这个页面的那些部分是由Tapestry控件组成。

Tapestry应用拥有高度的可升级性,它利用缓存和对象池使每个请求的处理时间最小化。Tapestry应用拥有跟传统Servlet应用相仿的性能。

Tapestry的学习曲线会长一点,因为它与流行的Web应用框架不太相同。

注意我们需要三个文件:*.html/   *.page/  *.java,分别表示了HTML的模板页面属性逻辑属性

首先简介一下web.xml,这可以使我们了解TAPESTRY是怎么工作的。

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>test</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>

因为Tapestry框架是标准Servlet API的一种扩展,它实际上是建立在J2EE框架上的。这个从WEB.XML的描述中可以看出.j2ee从URL的请求中分离出/app=>tapestry这个servlet名=>servlet-class org.apache.tapestry.ApplicationServlet处理类.下面就与J2EE SERVLET处理的差不多了。

可以猜测org.apache.tapestry.ApplicationServlet做了以下工作:

1)拦截HTML文件,找到页面描述,创建类A,将其中的jwcid属性变换为对A的调用,从而获取属性值.进而获得页面实例.A可能在创建之后放入对象缓冲池,以备后来使用。

2)当提交表单时,处理listener,处理页面表单逻辑.

3)其他工作同Struts Servlet类似.

二、在Windows下如何使用Tapestry

1. 从官方网站:http://tapestry.apache.org/download.html下载tapestry-bin-5.1.0.5.zip并解压到:D:\tapestry\tapestry-project-5.1.0.5 ,需要指出的是D:\tapestry\tapestry-project-5.1.0.5\lib下包含了开发一个Tapestry应用的全部jar包

2. 安装myeclipse6.0。

3. 下面介绍如何创建一个简单的tapestry应用启动 myeclipse ,新建 java web project.展开工程(test)右键点击JRE System library 选择 build path >> configure build path. 新对话框中选择 libraries 选项卡,点击 add library>>user library>>user libraries>>new ,起一个名字本文中为T5-lib 然后点击 add JARs 将 D:\env\tapestry-project-5.1.0.5\lib 目录下的全部jar文件导入. 然后选中T5-lib 点击finish 。修改web-inf下web.xml文件,同前面例子。

4. 在WebRoot目录下(web-inf同级目录),创建Home.html。(Tapestry程序入口,名字在.appliaction文件中定义)代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body><span jwcid="@Insert" value="ognl:HelloWorld" />
</body>
</html>

5. 在web-inf目录下创建名为 Home.page 的xml文件。如下:

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE page-specification PUBLIC
"-//Apache Software Foundation//Tapestry Specification 4.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
<page-specification class="com.kevin.tapestry.Home">
</page-specification>

6. 最后在 mytapestry 包下写一个java

package com.kevin.tapestry;
import org.apache.tapestry.html.BasePage;public abstract class Home extends BasePage{public String getHelloWorld(){return "Hello World!";}
}

7. 启动tomcat 在浏览器输入 http://localhost:8080/test/app 应该看到如下页面

Hello World!

三.Tapestry框架的简介

一个基于Tapestry的web应用可能包含了以下几种文件:应用规范文件hivemind配置文件HTML模板文件页面规范文件页面类文件组件包规范文件组件规范文件组件类文件动态脚本文件。下面一个一个来详细讲述。

1. 三种配置文件(应用程序规范文件,hivemodule配置文件,组件包规范文件)

1.1 应用程序规范文件:是一个以应用程序servlet名称命名的,以“.application”为扩展名的xml文件。一个web应用只能有一个应用程序规范文件。他制定了应用程序的各种细节配置,页面和组件配置,组件包配置等等。如果我们不为应用程序配置应用程序规范文件,Tapestry会为我们提供一个默认的。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC"-//Apache Software Foundation//Tapestry Specification 4.0//EN""http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd"><application name="test"><meta key="org.apache.tapestry.page-class-packages" value="test_path"/><library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/><page name="Home" specification-path="Home.page"/></application>           

  <application>为根标签元素,name制定了serlvet名称。

  <meta>用于配置应用程序细节。在此我们为应用程序配置页面类的默认定义包路径。那么Tapestry将自动在test_path路径下寻找页面类。

  <library>导入了外部组件包.

1.2 hivemind配置文件:HiveMind框架是一个依赖注入微核心框架,Tapestry框架构建在HiveMind之上。如果你的程序业务层没有用到hivemind,不必配置hivemodule文件。下面给了一个为应用程序配置Friendly

URL的例子:

<?xml version="1.0" encoding="UTF-8"?><module id="test" version="1.0.0"><contribution configiration-id="tapestry.url.ServiceEncoders" /><direct-service-encoder id ="direct" stateless-extension="direct" stateful-extension="sdirect" /><direct-service-encoder id ="action" stateless-extension="action" stateful-extension="saction" /><page-service-encoder id="page" extension="page" service="page" /><page-service-encoder id="external" extension="external" service="external" /><asset-encoder id="asset" path="/assets" /><extension-encoder id="ext" id="ext" extension="svc" after="*"/></contribution>
</module>

1.3 组件包规范文件: 为了跨项目积累组件,我们可以将组件打成jar包,然后通过在应用程序规范文件中引入组件包的方式,调用组件包中的自定义组件。组件包规范文件的后缀为“.library”的XML文件,命名任意。

2. Tapestry页面的组成

2.1 HTML模板:HTML模板就是标准的静态HTML页面,在HTML模板中我们通过jwcid(Java Web Component ID)标签属性调用Tapestry组件。例如上例中的 <span jwcid="@Insert" value="ognl:HelloWorld" />

在上面的代码中,调用了Tapestry的官方组件Insert,value属性是Insert组件的参数之一。"@"符号用于区分jwcid是一个组件类型还是一个组件ID,如果是一个组件ID,tapestry将在HTML模板对应的页面规范中寻找对应该组件ID的组件调用配置。(亦可这样理解,"@"为官方组件无"@"为自定义组件,自定义组件需要在“.page”文件中详细配置该组件的用法。)

2.2 页面规范:是以页面名称命名且后缀是.page的XML文件,这个后缀为.page的XML文件必须声明Tapestry的页面规范DOCTYPE。

例如在上例中:

<span jwcid="@Insert" value="ognl:HelloWorld" />   

也可以这样来表示:

HTML模板:

 <span jwcid="@Insert" value="ognl:HelloWorld" />

页面规范:

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE page-specification PUBLIC"-//Apache Software Foundation//Tapestry Specification 4.0//EN""http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd"><page-specification class="com.kevin.tapestry.Home"><component id="test" type="Insert"><binding name="value" value="HelloWorld" /></component>
</page-specification>

2.3 页面类:必须继承org.apache.tapestry.html.BasePage类,如:

package com.kevin.tapestry;
import org.apache.tapestry.html.BasePage;   public abstract class Home extends BasePage{public String getHelloWorld(){return "Hello World!";}}   

3. Tapestry组件的组成

  在Tapestry中,一个组件通常由HTML模板组件规范组件类动态脚本文件4个文件组成,除了组件规范以外,其他三个文件都不是必须的。

4. ognl

  OGNL是 Object Graph Navigation Language 的简称,是一种绑定方式的表达式语言。

  OGNL是OpenSymphony的一个开源项目。OGNL最重要的也是最根本的作用是简化调用Java类中的getter/setter方法,同时,他也是一种功能单一且易于使用的表达式语言,OGNL表达式就式该语言的全部。对于OGNL如何与模板对象绑定,Tapestry已经实现,我们不需要关心。同时,虽然OGNL表达式带有运算功能,但是Tapestry框架将页面逻辑全部放到了页面类中,因此根本没必要使用OGNL表达式来处理页面逻辑。

Tapestry框架的整个调用过程Home.html -> Home.page -> Home.class

四、各种组件的使用(只列举了一些常用的,更多请参见TAPESTRY官方网站)

1、Foreach

 source:是对应的java类里的List 对象或者是个数组 需要抽象 或者提供set get方法

value:是循环这个source对象代表当前的一个 ,需要在page文件中设置问一个属性,可以不在对应的java类里有这个属性

index:是循环的索引值 同value一样 在page文件中设置一个属性即可 <property name="index"/>

在循环的时候 会自动为vlaue和index赋当前的值

<table cellspacing="6"><tr><td>ID</td><td> </td><td>Name</td><td> </td><td>Level</td></tr><tr><td colspan="5"><hr></td></tr><tr jwcid="@Foreach" source="ognl:customerList" value="ognl:customer" element="tr"><td><span jwcid="@Insert" value="ognl:customer.id"/></td><td> </td><td><span jwcid="@Insert" value="ognl:customer.fullName"/></td><td> </td><td><span jwcid="@Insert" value="ognl:customer.memberLevel"/></td></tr>
</table>

<property-specification name="customerList" type="java.util.List" persistent="yes"/><property-specification name="customer" type="Customer"/>

public abstract class SalesPage extends BasePage {public abstract List getCustomerList();public abstract List setCustomerList(List value);}public class Customer implements Serializable {private Integer id;private String fullName;private String memberLevel;public Customer(Integer id, String fullName, String memberLevel) {this.id = id;this.fullName = fullName;this.memberLevel = memberLevel;}public Integer getId() { return id; }public String getFullName() { return fullName; }public String getMemberLevel() { return memberLevel; }}

调用过程如下:source="ognl:customerList"==》getCustomerList()==》得到一LIST。

该LIST在FOREACH每次循环LIST中顺序取出一对象A(类型为ognl:customer),该对象A在FOREACH循环中它的属性被引用(调用:getId() ,getFullName(), getMemberLevel() )。

2、Hidden组件 总是多余的处理

 <input jwcid="@Hidden" type="hidden" value="ognl:blahblah" encode="false"/>

  用来存储一些页面的状态变量。

3、 Insert 组件

<input type="text" jwcid="name@Insert" value="ognl:user.name"/>

页面表现时,将会到页面类中寻找getUser().getName()方法获取初值并输出相当于在页面上显示数据.

4、 TextField 组件

<input type="text" jwcid="username@TextField" value="ognl:username"/>

  页面表现时,将会到页面类中寻找getUsername()方法获取初值。

*如果是修改信息页面,通常初始值要在页面表现之前由setUsername()手动设置从数据库中读取出来的值表单提交时,通过setUsername()写入新值(即用户输入值),在类中通过getUsername()获取新值相当于在修改个人信息时,首先读出用户名赋予文本框(用户名)初值,用户修改时填入新值,后台获取之后,*Hidden属性区分是普通文本输入框(默认false)和密码输入框(hidden="ognl:true")

  readonly属性设置只读 readonly="true"为只读(后台可读取)

  *disabled属性设置是否可写 diabled="true"为不可写(后台也不可读取)

6、 TextArea 组件

<textarea jwcid="content@TextArea" value="ognl:content" cols="40" rows="10"></textarea>

  页面表现时,将会到页面类中寻找getContent()方法获取初值,工作原理同TextField。

7、 RadioGroup/Radio 组件

 <span jwcid="headImage@RadioGroup" selected="ognl:headImage"><input jwcid="@Radio" type="radio" value="1"/>头像1<input jwcid="@Radio" type="radio" value="2"/>头像2<input jwcid="@Radio" type="radio" value="3"/>头像3<input jwcid="@Radio" type="radio" value="4"/>头像4<input jwcid="@Radio" type="radio" value="5"/>头像5<input jwcid="@Radio" type="radio" value="6"/>头像6</span>

RadioGroup为每一个Radio提供一个唯一的ID。RadioGroup跟踪当前被选中的属性值,并且只有一个Radio能够被选中。

页面提交时,RadioGroup组件就利用OGNL表达式向headImage字段写入被选中的Radio组件的value参数值。

页面表现时(修改页面),将会到页面类中寻找getHeadImage()方法获取初值,然后寻找@Radio组件中与其相同的组件并勾选上。

8、 PropertySelection 组件

  使用PropertySelection组件必须要构造一个类来实现IPropertySelectionModel接口,并且重写该接口的5个方法。

  public int getOptionCount() //提供下拉菜单的长度public Object getOption(int index) //提供select标签的optionpublic String getLabel(int index) //提供select标签的Label值,也就是下拉菜单显示的内容public String getValue(int index) //提供select标签的value值public Object translatue(String value) //selected后的返回值,value值未必就是我们需要的返回值,可以在这个方法里面对返回的value做对应的转换或修改.

8.1属性下拉框

<select jwcid="gender@ProPertySelection" name="genderSelect" value="ognl:gender" model="supportedGender"><option selected>先生</option><option>女士</option>
</select> 

代码:GenderSelectionModel.java

public class GenderSelectionModel implements IPropertySelectionModel {  public static final String male = "先生";  public static final String female = "女士";  public static final String[] genderOptions = { male, female };  public int getOptionCount() {  return genderOptions.length;  }  public Object getOption(int index) {  return this.translatue(genderOptions[index]);  }  public String getLabel(int index) {  return genderOptions[index].toString();  }  public String getValue(int index) {  return genderOptions[index];  }  public Object translatue(String value) {  if (value.equals("先生")) {  return "1";  } else {  return "0";  }  }
}

代码:ModUserInfo.java

public IPropertySelectionModel getSupportedGender() {  return new GenderSelectionModel();
}

  存入数据库中"1"代表先生,"0"代表女士,通过translatue(String value)方法转换页面表现时,通过model属性给出的IPropertySelectionModel获取下拉选项,即getSupportedGender()。

  然后通过getGender()方法获取初值,比如获取"0",则在页面显示时寻找value值为"0"的选项即为"女士",并选择之作为初始选择项。

8.2日志类型下拉框

<select jwcid="logType@PropertySelection" name="typeSelect" value="ognl:logType" model="supportedType"><option>心情日记</option><option>情感天地</option><option>生活感触</option>
</select>

代码:TypeSelectionModel.java

public class TypeSelectionModel implements IPropertySelectionModel {  private List typeList = new ArrayList();  public TypeSelectionModel(List typeList) {  this.typeList = typeList;  }  public int getOptionCount() {  return typeList.size();  }  public Object getOption(int index) {  return ((LogType)typeList.get(index)).getValue();  }  public String getLabel(int index) {  return ((LogType) typeList.get(index)).getName();  }  public String getValue(int index) {  return ((LogType) typeList.get(index)).getValue();  }  public Object translatue(String value) {  return value;  }
}

代码:ModLog.java

public IPropertySelectionModel getSupportedType() {  TypeSelectionModel typeSelectionModel = new TypeSelectionModel(loadType(getUser().getUserId()));  return typeSelectionModel;
}  private List loadType(int userid) {  ...//从数据库载入该用户的日志类型列表
}

  页面表现时,通过model属性给出的IPropertySelectionModel获取下拉选项,即getSupportedType(),然后通过value属性给出的初始值即,getLogType()方法获取初值,比如获取"2",则在页面显示时寻找value值为"2"的选项即为"生活感触",并选择之作为初始选择项。

9、 Form组件

 <form jwcid="logForm@Form">...</form>

Form的监听(listener)方法可以有两种方式:

9.1. 在Form组件中声明

 <form jwcid="logForm@Form" listener="ognl:listener:onLogin">...</form>

9.2. 在submit类型组件中声明

<input type="submit" jwcid="onLogin@Submit" listener="listener:onLogin" value="发表"/>

或者
<span jwcid="@ImageSubmit" image="..." listener="listener:onLogin"><img src="..." width="" height=""/></span>

  前一种方式当Form中只要有submit就会触发监听方法,后一种方式是Form中有多个submit,各自实现不同的监听方法。

10、 Conditional 组件

 <span jwcid="@Conditional" condition='ognl:item.sex.equals("1")'>先生</span><span jwcid="@Conditional" condition='ognl:item.sex.equals("0")'>女士</span>

conditional参数为true时运行Conditional组件中的HTML模板内容.

在Tapestry4.0以后就不支持该组件了, 可以使用其他组件来实现:

10.1. Contrib:Choose和Contrib

When (contrib:外围爱好者根据需要自行编译并贡献的软件)

<library id="contrib" specification-
path="classpath:/org/apache/tapestry/contrib/Contrib.library"/>(.application文件中引入Contrib类包)<span jwcid="@contrib:Choose"><span jwcid="@contrib:When" condition='ognl:user.gender.equals("1")'>先生</span><span jwcid="@contrib:When" condition='ognl:user.gender.equals("0")'>女士</span></span>

10.2. If组件

<span jwcid="@If" condition='ognl:item.sex.equals("1")'>先生</span><span jwcid="@If" condition='ognl:item.sex.equals("0")'>女士</span>

10.3. Else组件

  <span jwcid="@Else">man</span>

转载于:https://www.cnblogs.com/Kevin-ZhangCG/p/9453158.html

Tapestry3.0开发概论相关推荐

  1. ibm服务器的虚拟控制台,IBM Worklight 6.0 - 开发服务器/控制台问题

    在Worklight v5.0.6中预览Worklight Console的MBS中的混合应用程序非常简单,因为它的工作原理非常简单.IBM Worklight 6.0 - 开发服务器/控制台问题 W ...

  2. Struts 2创始人Patrick Lightbody看《精通Struts 2:Web 2.0开发实战 》

    <精通Struts 2:Web 2.0开发实战 > Apache Struts是目前最成功开源项目之一.除了一些基础性项目如Linux.MySQL以及若干编程语言外,很少有开源框架能像St ...

  3. From 《visual C++ 6.0开发工具与调试》

    From <visual C++ 6.0开发工具与调试> 1.          如何快速地规范代码缩进格式 选中所需要规范的代码,按shift+F8 2.          如何在Rel ...

  4. Windows Embedded CE 6.0开发初体验(二)CE开发环境 收藏

    上一篇<Windows Embedded CE 6.0开发初体验>之"嵌入式开发流程": http://blog.csdn.net/aawolf/archive/200 ...

  5. 用SignalR 2.0开发客服系统[系列3:实现点对点通讯]

    用SignalR 2.0开发客服系统[系列3:实现点对点通讯] 原文:用SignalR 2.0开发客服系统[系列3:实现点对点通讯] 前言 目录: 用SignalR 2.0开发客服系统[系列1:实现群 ...

  6. windows下qt5 kinect 2.0开发与环境配置

    上一次挑战杯我们用kinect1.8做了一个体感3d试衣系统,那时就想用qt来开发了,由于那时候很多东西都不懂,怎么也不知道怎样去配置环境,只能在vs2013中开发,结合qt开发界面.直到出了kine ...

  7. 实习小白::(转) Cocos2d-x 3.0开发(十三)使用CocoStudio编辑帧事件并关联到程序...

    1.概述 帧事件也是新加入的功能.这篇中我们将看到如何使用它.我们将上篇中制作的动画稍加修改.有图为证: 2.用途与原理 首先介绍一下帧事件.正如其名:一个与帧相关联的事件. 为什么要这么做呢?首先没 ...

  8. vc6.0开发环境两个辅助工具

    vc6.0开发环境两个辅助工具: 1)增加行号:http://download.csdn.net/detail/fjssharpsword/4162972 2)增加代码颜色和工具栏:http://do ...

  9. qt5.9.0调试如何查看变量的值_从0开发3D引擎(四):搭建测试环境

    大家好,本文介绍了3D引擎的测试方法,搭建了本地的测试环境. 上一篇博文 wonder-yyc:从0开发3D引擎(三):搭建开发环境​zhuanlan.zhihu.com 下一篇博文 wonder-y ...

最新文章

  1. python判断题题库大数据技术_智慧树知到_大数据分析的python基础_选择题答案
  2. springboot rabbitmq direct exchange和topic exchange 写法上关于路由键的区别
  3. python到底怎么学-学 Python 到底能帮你解决什么问题 ?
  4. python代码大全p-基于python实现计算两组数据P值
  5. error: mod_deflate has been requested but can not be built due to prerequisite failures
  6. Collections接口下的Comparetor类和Comparable接口排序
  7. java实现插入排序算法 附单元测试源码
  8. TCP/IP完整的基础介绍
  9. python问卷调查系统设计案例_从设计到施工,全面剖析超级玻璃屋面系统案例!...
  10. java inireader_用Java读取INI文件(带section的)
  11. SecureCRT无法使用root账户远程连接ubuntu
  12. 微弱光信号检测MATLAB,基于数字锁相放大器的微弱光电信号检测研究
  13. P3456 [POI2007]GRZ-Ridges and Valleys(bfs)
  14. error: server certificate verification failed 问题
  15. debian linux fcitx 小鹤双拼
  16. 单词迷阵游戏就是从一个10x10的字母矩阵中找出目标单词,查找方向可以从左往右、从右往左、从上往下或者从下往上。例如下面的迷阵中包含quot等单词。
  17. Cannot find reference 'dynamic_rnn' in '__init__.py'
  18. Python修改私有变量、统计访问次数、华摄氏度转换
  19. 大数据给保险业带来巨大商业价值
  20. Linux服务器+GPU配置总结(四)

热门文章

  1. 用Python来制作简单的爬虫,爬取到你想要的图片
  2. 在QGIS中导入Google、Bing、高德等地图和卫星影像
  3. 如何搭建个人简历网站
  4. 某宝滑块 x82y解决方法、x5sec
  5. mysql eav_mysql – 如何使此eav查询生成水平结果
  6. 利用TF_IDF算法计算两英文文章的文本相似度 C++实现
  7. Sun开发的JINI技术在网络中的应用
  8. mindspore 1.3.0版本GPU环境下源码编译的正式工作——完整的编译过程
  9. Django中filer和get的区别
  10. ppt关闭受保护视图