Tapestry学习笔记.docx
- 文档编号:6439656
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:18
- 大小:30.22KB
Tapestry学习笔记.docx
《Tapestry学习笔记.docx》由会员分享,可在线阅读,更多相关《Tapestry学习笔记.docx(18页珍藏版)》请在冰豆网上搜索。
Tapestry学习笔记
Tapestry学习笔记
(1)
1. 什么是面向组件开发方式
Tapestry最大的特点是其颠覆性的开发方式。
所谓颠覆,是指Tapestry的开发方式不光与传统的开发方式截然不同,而且还是在逐渐取代传统的开发方式。
在web表现层框架中有两大开发方式,一种是传统的面向元素开发方式,这种开发方式也是最早出现的开发方式。
绝大多数框架都是使用面向元素开发方式,比如Structs,WebWork,SpringMVC等。
在面向组件开发方式出现的原因正是为了弥补面向元素开发方式中种种不足之处。
因此,我们可以认为面向组件的开发方式比面向元素的开发方式更加先进。
目前,面向组件的Web表现层框架有三种:
Tapestry,JSF,Wicket。
2.传统的面向元素开发方式
在Java语言中,我们都是使用JavaServlet API来创建Web应用程序。
JavaServletAPI是SUN公司制定的标准。
Servlet是一个Java类,它的作用是接收客户端发送过来的请求,然后返回一个响应,最后通过客户端浏览器显示出一个HTML页面。
JavaServletAPI为Servlet定义了一些基础类,例如HttpServletRequest,该对象装载了客户端发送过来的请求,并允许Servlet获取URL中携带的质询参数。
Servlet在Servlet容器中运行,Servlet容器是HTTP协议与JavaServletAPI之间的桥梁。
Servlet容器负责创建Servlet实例并对其进行初始化。
很多软件都提供了Servlet容器,其中有些软件的全部功能只是为了提供Servlet容器,例如,ApacheTomcat,Resin,Jetty等,而在有些软件中,Servlet容器可能只是一个庞大应用程序服务器中的一部分,例如,BEAWebLogic,IBMWebSphere或开源的JBoss应用程序服务器。
Servlet容器根据URL来选择合适的Servlet响应请求,一个简单的Web应用程序可能包含许多Servlet。
那么在Web应用程序的部署描述文件(应用程序中的一个XML文件通常命名为web.xml,放置在应用程序中的WEB/WEB-INF/目录下)中,我们就必须对每一个Servlet的名称和Java类全路经进行配置,并且配置URL和Servlet的映射关系。
例如:
那么当客户端请求URL中包含“/servlet/MyServlet”字符串的时候,Servlet容器将会查找名称为“myServlet”的Servlet,然后根据名称为“myServlet”的Servlet的Java类群路径“com.wanjin.MyServlet”创建Servlet实例,并对其进行初始化。
MyServlet类在接受到客户端返回相应。
相应的结果以一个HTML,页面的形式在客户端浏览器出现,该叶面向是勒我们希望客户端得到的应用程序业务信息。
整个过程是很简单的。
但是当我们面对一个庞大Web应用程序的时候,该用程序就可能包含大量的Servlet。
这就意味着我们必须定义大量的URL与Servlet映射关系。
那么,应用程序的URL结构将变得越来越复杂,也越来越容易发生混淆。
于是,在应用程序开发阶段,我们不得不将绝大部分精力用于处理数量众多且易于混淆的URL。
在传统的开放方式中,例如,JavaServerPage(JSP),SpringMVC,Struts,WebWork中,我们必须关注叶面中每一个元素的href属性,以及form元素的action属性,因为这些属性装载了向服务器发送请求的URL.大多数情况下,我们对这些HTML元素属性的关注甚至超过了我们对应用程序业务逻辑的关注。
我们将这种开发方式称为面向元素(标签)开发方式。
Tapestry学习笔记
(2)
3. Tapestry的面向组件开发方式
Tapestry面向组件的开发方式是传统开发方式的变革。
什么是面向组件呢?
这就像搭积木一样。
Tapestry将一个应用程序分成很多个页面,而一个页面又是由若干组件组成的,我们不需要去关心任何Servlet细节,也不需要关心如何生成URL和URL的结构,Tapestry会为我们自动生成合适的URL跳转叶面或者传递参数。
在Tapestry框架中,页面有HTML模板,页面规范和页面类组成,而组件由HTML模板,组件规范和组件类组成。
叶面的HTML模板和组件的HTML模板都是在原始的HTML静态页面中嵌入少量的jwcid属性标签构成,页面类和组件类都是抽象或非抽象的Java类,并最终继承于Tapestry的org..apache.tapestry.AbstractComponent类。
因此,页面对于Tapestry来说,是一种特殊的组件。
那么一个使用Tapestry框架的Web应用程序,实际上就是一堆Tapestry组件的集合。
页面的所有业务逻辑都放在页面类中,页面与页面的关系是Java对象之间的关系。
叶面类的逻辑不会影响到组件类的逻辑,页面与组件通过组件参数联系在一起,组件参数是页面向组件或者组件向页面传递数据的媒介。
组件的所有逻辑都放在组件类中。
因此,组件的逻辑实现完全脱离页面的束缚。
Tapestry组件是一个“黑盒子”,用于相应HTTP请求,并表现响应。
在调用Tapestry组件的时候,我们根本就不需要去关心这个组件是如何实现的。
我们面对的是组件的参数,只要向组件传递合适的数据,那么组件就会实现我们预期的功能。
页面类和组件类都是Java类,实现页面逻辑或者组件逻辑的过程不会影响到页面或组件的HTML模板。
因此,Java程序员能够和美工人员实现完全独立的分工。
使用Tapestry框架来开发应用程序,就如同我们组装一台电脑。
我们只是关心CPU的性能如何,内存多大。
却不会关心CPU是怎样制造的,内存芯片之间如何通信等。
如果我们嫌这台电脑运算内存不够,加根内存条就可以了,并不会影响CPU硬盘等已有硬件的工作。
同样,从小型的应用程序到各种大型团队开发的几百个页面的大型应用程序,对于Tapestry来说,只不过是页面和组件使用多少的差别。
使用Tapestry来开发各种大小应用程序,都能够保持一个协调一致的结构。
这种结构一致的特性使得不同开发者在类似的问题上会找到类似的解决办法。
我们创建的Tapestry组件能够跨项目使用,那么随着我们开发的应用程序的增多,积累的Tapesty组件就会越多,开发应用程序的效率就会越快。
Tapestry框架带来了真正的JavaWeb应用程序OOP编程。
4. 面向元素VS面向组件——思维方式的变革
在面向元素的开发方式中,我们的思维是线性的。
我们无法将精力集中在应用程序的整体功能实现上。
当一个超链接或者一个表单按钮没有达到我们预期目的的时候,我们首先考虑的不是应用程序业务逻辑是否正确实现,而是超链接或表单发送的URL的结构是否正确,并成功映射到指定的Servlet。
特别当我们在页面中大量使用JavaScript脚本语言构造URL,或者修改页面中form表单的action属性的时候,分析和维护这样的页面是一场非常可怕的噩梦。
在面向元素的应用程序中,我们关心URL传递参数所携带的数据,关心Servlet的任何细节,甚至在高并发状态下,我们还必须担心Servlet是否正确地接收URL中传递的数据。
由于国内Struts框架使用相当广泛,而JSP又是我们学习Web应用程序开发的起步技术。
因此,面向元素的开发方式是我们最习惯和最容易实现的开发方式。
虽然面向元素开发方式实现起来最容易,但这并不意味着这种开发方式效率最高。
由于我们不等不关心很多Servlet底层实现,于是我们不得不重复地编写这些底层代码,当一个页面中有多个action或者Servlet涉及高并发的时候,我们还得非常仔细地分析这些易让人混淆的底层代码。
Tapestry框架的面向组件思维颠覆了我们的习惯性思维。
在面向组件的开发方式中我们不再关注Servlet底层实现,也不再过问URL的结构。
我们通过创建页面来构成应用程序,通过在页面中调用组件来实现页面功能。
我们不关心页面如何通过URL跳转到另外一个页面,也不关心form表单如何通过URL将数据包装在请求中提交到服务器端。
在面向组件的开发方式中,我们的思维是块状的,面向对象的思维方式。
我们关心如何将用户在登录时输入的用户名和密码。
我们关心在用户登录失败时向客户端返回什么样的错误提示信息,却不关心如何将这些错误信息打印到客户端浏览器。
面向组件的开发方式使我们将注意力集中在页面逻辑实现上,这样就提高了工作效率。
对于那些重复而又容易发生错误的底层Servlet代码,Tapestry框架能够很好地进行处理,使我们得以解脱。
Tapestry学习笔记(3)
Tapestry属性生命周期
Tapestry属性可能拥有持久化状态,在各个请求周期之间保存用户指定的Tapestry属性。
当应用程序的某一部分请求一个页面时候,将会获得一个页面实例和用户先前存入持久化页面属性中的值。
如果这个页面中调用的组件包含有持久化的组件属性,那么请求也将获得持久化组件属性的值。
页面实例不是session持久化。
他们仅仅在第一次创建的时候存在于JavaVM的内存中。
页面和组件不需要实现java.io.serializable接口,他们永远不会被序列化。
而应用程序引擎对象总是不停地创建页面的新实例,并重新对页面赋予其先前被记录的状态。
页面的状态也就是指页面所拥有的Tapestry属性(页面属性,以及页面调用组件的组件属性)的值。
在Tapestry中,属性的声明周期和重要。
它拥有以下3种声明周期。
持久-----在各个请求周期之间,属性被记录并持久化。
当属性被重载的时候,持久化页面属性被恢复。
持久化Tapestry属性根据其声明的持久化策略已不同的方式被不同的用户共享。
瞬时----在页面表现之前,属性被设定,并且在当前请求结束的时候,重置为默认值。
动态----属性的值根据页面的表现而改变,但是在当前请求结束的时候,被重置。
持久化Tapestry属性就好像用户名,又像在商业应用程序中所显示的产品名称;而瞬时持久Tapestry属性通常只被使用一次,比如错误信息;而动态Tapestry属性与表现进程联系紧密,比如以某种排序显示一组条款,就可能需要动态Tapestry属性来为每一条款在循环中赋值。
1.持久化页面状态
Tapestry框架有责任在请求周期内跟踪页面状态的改变,并且在请求周期之间储存状态。
实际上,这是应用程序的引擎对象的职责,通过页面记录器对象来完成。
页面记录器是实现org.apache.tapestry.engine.IPageRecorder接口的对象,用于获取页面及其组件中属性的变化,并在请求周期内储存页面的状态。
当一个页面的持久化状态被改变时,引擎对象通知页面记录器,并提供属性的名称以及新的值。
这个“通知”作为一条信息被持久化地储存下来,当下一个请求周期到达的时候,页面记录器将根据这个信息将页面退回到先前的状态。
声明Tapestry属性持久化的工作由开发人员来完成,属性的值必须被序列化(非原始类型通过实现serializable接口来实现)。
Tapestry属性的持久化有两种形式。
Session持久化当页面被第一次访问的时候,页面属性的值被储存到HttpSession对象中,当页面需要操作页面属性的时候,从HttpSession中获取页面属性的值,当session会话的生命周期结束,页面属性的值即被清空。
声明方法:
代码
1.
客户端持久化当页面被第一次访问的时候,Tapestry框架自动向客户端浏览器中所偶表单添加hidden域以保存客户端持久化属性的值。
并且页面上所有用于跳转的URL都将会被添加客户端持久化属性进行操作的时候,Tapestry框架自动从客户端浏览器的hidden域中,或者从URL里包含的客户端持久化属性相关信息中获取到客户端持久化属性的值,并重新赋给对应的Tapestry属性。
客户端持久化分为客户端应用程序持久化和客户端页面持久化。
客户端应用程序持久化:
Tapestry属性的客户端持久化范围为整个应用程序,使用方法是在页面规范或组件规范中声明
app”,例如:
代码
1. app”/> 客户端页面持久化: Tapestry属性的持久化范围是属性所在页面,使用方法是在页面规范或组件规范中声明 page”例如: 代码 1. page”/> 2. 2.瞬时页面状态 我们使用的大多数Tapestry属性都是瞬时的页面状态,瞬时的页面状态就如同我们在页面类中定义成员变量,同时创建该成员变量的标准JavaBean方法,并在initialize()方法中对其进行初始化。 当页面表现的时候,瞬时的Tapestry属性被赋值,当页面表现结束时,瞬时的属性被还原为初始值。 声明方法为: 代码 1. 3.动态页面状态 页面属性在页面表现的时候动态地改变。 最典型的例子就是Foreach组件,例如: 代码 1. 2. 3. 4. 5. 在这里,组件ID为fruitListLoop的Foreach组件的value参数绑定了页面属性fruit,Foreach组件每遍历到其source参数所绑定fruitList集合中的每一个元素,就将这个元素赋予value参数绑定的页面属性fruit。 于是该页面属性fruit的值在Foreach组件的整个循环遍历中,是不断被改变的。 当Foreach组件调用结束,整个页面表现完毕之后,value参数所绑定的fruit页面属性又会被还原为初始值。 因此,动态页面状态实际上也是瞬时页面状态。 Tapestry学习笔记(4) 在Tapestry框架运行时,通过反射机制生成一个继承于我们页面类的子类,根据页面规范或组件规范中声明的属性,向这个反射生成的子类中添加标准的JavaBean属性,这就是属性指定的运作过程。 在页面规范中声明的数据称为页面属性;在组件规范中声明的属性成为组件属性。 其实,不论页面属性还是组件属性,他们都以完全一样的方式进行声明和使用。 将Tapestry属性分为页面属性和组件属性,只不过为了方便称呼。 例如,在登录页面Home,为了拥有一个用户名和密码的输入值载体,我们在页面规范Home.page中声明两个页面属性。 代码 1. 2. 为了在页面类Home.java中能够获取到这两个页面属性,我们需要定义两个对应于页面属性的JavaBean抽象getter方法。 代码 1.Public abstract string getUsername();//用户名 2.Public abstract string getPassword();//密码 在页面规范或组件规范中声明属性的时候,我们并不需要声明其类型。 Tapestry框架根据我们在页面类或组件类中声明的JavaBean抽象的getter/setter方法类型来决定属性的类型。 从反射机制的角度,由于Tapestry框架运行时会生成一个集成于页面类的子类,根据Java的多态性,我们很容易理解,既然子类生成的是标准JavaBean属性,那么当我们在父类(页面类或组件类)中调用JavaBean属性的抽象getter方法,即可以获得子类JavaBean中装载的值。 同样,如果我们需要在页面类中设置属性值,那么可以在页面类中添加对应的JavaBean属性抽象的setter方法。 如: 代码 1.Public abstract void setUsername(String username);//设置用户名 2.Public abstract voif setPassword(String password);//设置密码 3. 现在我们已经理解了页面属性(或组件属性)的概念,因此我们可以通过在页面类中添加JavaBean属性的方式来达到页面属性相同的效果。 在Home.java中: 代码 1.Private string password; 2.Protected void initialize(){ 3. This.password = null; 4.} 5.Public String getPassword(){ 6. Return password; 7.} 8.Public void setPassword(String password){ 9. This.password = password; 10.} 除了标准的JavaBean属性,我们需要注意的是protectedvoidinitialize()方法。 所有的页面类都继承于org.apache.tapestry.html.BasePage类,而BasePage类继承于AbstractPage类,protectedvoidinitialize()方法是org.apache.tapestry.AbstractPage类中的方法。 实际上,页面属性在运作的时候,Tapestry框架不光为其添加标准的JavaBean属性还在页面表现之前和表现之后,两次对页面属性进行初始化。 而protectedvoidinitialized()方法具有同样的初始化作用,在页面表现之前和表现之后,两次对页面类中的成员变量进行初始化。 需要注意的是,org.apache.tapestry.AbstractComponent类中并没有protectedvoidinitialize()方法,而所有的组件类都继承于AbstractComponent类。 因此我们不能用这样方式对组件类中的成员变量进行初始化。 Tapestry框架对页面属性或组件属性的默认初始化值是Java各种类型对象的默认值,如int型为0,String型为NULL等。 我们需要对页面属性(或组件属性)进行自定义的初始化事例如下: 代码 1. 我爱Tapestry”/> 如这里对页面属性username的声明所示,我们为该页面属性提供一个初始化值: 字符串“我爱Tapestry”。 它的作用等同于在页面类中对成员变量username进行以下声明。 代码 1.Private String username; 2.Protected void initialize(){ 3. This.username=” 我爱Tapestry”; 4.} 5.Public String getUsername(){ 6. Return username; 7.} 8.Public void setUsername(String username){ 9. This.username=username; 10.} Tapestry学习笔记(5) 监听方法 Tapestry框架属于事件触发机制,监听方法是我们在客户端触发服务器端Tapestry框架的主要方式。 监听方法有多种形式,当表单form被触发提交的时候,或者当一个链接被单击的时候,就会触发监听方法。 监听方法存在于我们的页面类或组件类中,例如,DirctLink组件和Form组件都拥有一个监听参数,我们可以使用一个”listener”字符串将我们页面类中的监听方法绑定在组件的监听参数上。 监听方法其实就是一个普通的功用非抽象方法,它可能携带有参数,也可能返回某种类型的值。 Tapestry框架并不强制要求监听方法必须携带参数或必须拥有返回值,一个普通的功用方法一旦与某个组件的监听参数通过“listener”字符串绑定,那么这个普通的功用方法就变成了监听方法。 1.监听方法的返回类型 监听方法可以使void方法,也可以返回一个String字符串,或者可能是一个实现了IPage接口的页面对象实例。 返回一个字符串或返回一个页面对象实例是为了激活并跳转页面以便响应请求。 如果返回NULL,则跳转到当前页面。 Void: 监听方法跳转到当前页面; String: 监听方法根据返回的页面名称来激活页面并表现响应,返回NULL,则跳转到当前页面; IPage: 监听方法根据返回的页面类实例来激活页面对象。 页面对象可以通过requestcycle来获取,也可以通过页面属性注入页面实例来获得,返回NULL则跳转到当前页面; ILink: 监听方法根据返回的实现ILink接口的对象对客户端URL进行重定向。 2.监听方法的参数 当使用DirectLink组件,ActionLink组件,Submit组件等带有parameters参数的组件时,你甚至可以定制该组件的监听方法参数。 DirectLink组件的parameters参数所携带的值将会被编码到URL中,以便我们可以通过监听方法的参数
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Tapestry 学习 笔记