Tapestry4开发指南.doc_第1页
Tapestry4开发指南.doc_第2页
Tapestry4开发指南.doc_第3页
Tapestry4开发指南.doc_第4页
Tapestry4开发指南.doc_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Tapestry4开发指南 一, 简介使用“开发指南”这个名词,实在是惭愧。随着接触面的增广,随着各种技术的不断了解,才逐渐发现自己欠缺得更多。书读得越多,才发觉自己的知识越匮乏。半年前,非常自不量力地将自己对Tapestry3.0.x的实践总结出来,写了一个所谓的Tapestry开发指南,而现在Tapestry4发布,我觉得将这个所谓的“开发指南”更新到Tapestry4,对自己来说,更像是一种交代。有很多不足之处,希望朋友们能够不遗余力地指出,就是对我最大的支持。Tapestry4的雏形是Tapestry3.1,Tapestry的作者Howard,不光开发了Tapestry,还同时开发了一个轻量级框架Hivemind。所以Tapestry3.1的开发一开始就处于Hivemind框架之下。后来由于种种原因,Howard没有将Tapestry3.1从Hivemind中剥离出来,于是就成为了今天的Tapestry4.0。很多朋友都不是很认同Hivemind,认为Hivemind是与Spring类似的IoC框架。刚开始的时候,我也同样很不认同Hivemind,毕竟使用Spring很熟悉了。而且我们团队的整个技术架构已经日趋成熟。就如同我当初评价Tapestry4与Hivemind之间的融合:“除非有足够且必要的理由,不然别说让我去说服团队将Spring转型为Hivemind,就连我自己都说服不了自己。”随着对Tapestry4的深入,我开始理解为什么Howard没有将Tapestry从Hivemind中剥离。就团队而言,我依然不认为有必要说服团队转型。但是就我个人而言,仅仅在IoC和DI的使用上,我却觉得使用Hivemind比Spring简单。当然,简单并非最重要的理由,但是当我们处于某一个特殊条件下,或许使用Hivemind也不失一个值得参考的选择。另外,最重要的是,如果着眼于Tapestry本身,Hivemind就好比是一个良好的地基,Tapestry作为上层建筑,任何我们认为不合理,不适合自己特殊需要的Tapestry官方实现,都可以通过Hivemind的IoC及DI进行重构。于是,现在的Tapestry4变得非常有趣,首先,它本身是一个框架,可以使用Tapestry4来创建动态,灵活的web应用程序,另外,可以通过Hivemind对Tapestry4自身功能进行重构,以便实现任何我们希望达到的特殊功能。打个比方说:Tapestry4就好比一把起子,我们可以通过Hivemind对这把起子的起子头进行任意更换,这样我们就可以适应任何形状或者接口的螺丝。在后面,我们会看到令人兴奋的示例来介绍这种“换起子头”的思想。关于Tapestry4.0的理论知识,如果有兴趣,可以参看我以前写的,关于Tapestry3.0的开发指南。实际上,虽然版本升级了,使用方式也有了很大变化,但是Tapestry本质的思想和理论并没有变化。这就是为什么虽然Tapestry4.0才刚刚发布,我却可以比别人更快地熟悉Tapestry4.0的使用。对于理论的介绍,这里就不在累述了。记得我以前学习Tapestry3.0的时候,还是通过查询Tapestry2.4的理论资料来学习的。对于本文档,我希望定位在快速熟悉Tapestry4.0。凡是我在本文档中提到的组件,如果没有做特别解释,那么就表示其用法与T3中基本相同,而对于T3的组件,我在以前些的文档中已经介绍了绝大部分。所以如果你是新手,建议你先参看我以前写的文档(/update/Tapestry开发指南0.9.rar)。二, Quick Start现在Tapestry4已经发布beta-9版本,从其change log上,我们可以看到,Tapestry4的开发已经日趋成熟,基本上官方现在修改最多的都已经仅仅是文档。所以,我现在已经在使用Tapestry4来开发项目。为了配合这篇user guide,我写了一个quick start示例。我们可以一步一步从项目配置开始,逐步了解Tapestry4。1) 搭建环境我们需要如下东东:Eclipse3.1及其以上版本:/downloads/index.phpMyEclipse4.0及其以上版本:Java SE 5.0及其以上版本:/download/index.jspResin3.0.x:/download/index.xtpTapestry4.0包:/site/downloads/downloads_tapestry.cgiTapestry4.0支持包:/tapestry/dependencies.htmlOK,现在我们开始搭建Tapestry项目。对于Eclipse的配置,我们就略过了。使用MyEclipse新建一个Web Project:我们将项目名称命名为MyTapestry4:点击Finish,我们新建了一个Web Project:然后我们将下载好的Tapestry4及其支持包拷贝到WEB-INF/lib/目录中:然后将包文件载入项目:OK,基本的项目配置完成,现在我们在src下新建包:com.tapestry4: 然后在WEB-INF目录下新建一个XML文件,命名为hivemind.xml,内容如下:在这里,hivemind.xml中module的id是与java包名com.tapestry4对应的,这个id只是起标识的作用,因为Hivemind可以拥有很多的配置文件,所以一般都使用包名作为id以保证唯一性。接着,我们在WEB-INF/目录下再新建一个application文件MyTapestry4.application,其内容如下:在application文件中,我们做了两件事:第一:声明了项目名称:name=”MyTapestry4”;第二:我们定义了page文件与java文件相互对应的默认包路径,Tapestry4根据这个路径自动去寻找与Home.page同名的Home.java文件,如果找不到,那么就会默认使用BasePage类。然后我们进行web.xml配置:为了测试项目是否已经正常配置,我们可以做点小测试:首先在com.tapestry4下新建一个Home.java文件:在Tapestry4中,java文件可以不再是abstract的,这个差别相比于Tapestry3还是很突出的。因为一个很简单的理由,一旦Tapestry4的java文件不再是抽象类,那么就可以进行单元测试了。在后面,我们会看到如何进行单元测试。接着在WEB-INF/下建一个Home.page文件:最后,我们在web/目录下新建一个Home.html文件:2) 让我们的项目跑起来将resin解压到硬盘,当然,使用tomcat,jetty等,都可以用下面的方式来启动项目。首先,打开Eclipse的Window - Preference :在MyEclipse的Application Server选项下,我们找到Resin3,然后在右边进行Resin配置。首先指定Resin Server为Enable,然后指定Resin Home Directory地址。然后我们要确保JDK的版本是否正确,并且加载两条JVM参数:-Dorg.apache.tapestry.disable-caching=true-Dorg.apache.tapestry.enable-reset-service=true使用过Tapestry3的朋友对这两条参数都非常熟悉了,它们的作用是关闭Tapestry的页面缓存,这样就能够让我们在开发项目的时候,修改html和page之后,不需要频繁地重新启动项目。但是在加载这两条参数之后,内存消耗比较大,所以在项目发布的时候,我们就不再使用这两条参数了。一旦你正确地配置了Resin,我们就可以在MyEclipse中启动Resin了。首先点击MyEclipse的J2EE项目配置管理:然后在下拉菜单中选择我们的MyTapestry4项目,点击右边的Add按钮:选择我们已经配置好的Resin Server,最后点击Finish。OK,现在我们可以清楚地看到,我们的项目已经被部署到Resin的deploy目录下了。接着,我们启动Resin,就可以启动我们的项目了:在Eclipse的控制台,我们可以清楚地看到项目启动的整个过程:嘿嘿,OK了。我们的项目已经搭建成功,打开一个浏览器,在地址栏中输入::8080/MyTapestry4/app其实搭建Tapestry4项目,很简单吧?0J三, 更深入使用Tapestry4.0现在,我们还是和以前一样,做一个最熟悉的示例:购物车。只是这次我们手把手一步一步地完成这个示例。1)登陆OK,现在项目已经搭建完成了,对于购物车示例,第一个页面应该是一个登陆页面。登陆页面应该有一个表单,有一个用户名输入,一个密码输入,同时还需要对用户名和密码进行效验。修改Home.java文件如下:package com.tapestry4;import org.apache.tapestry.IRequestCycle;import org.apache.tapestry.html.BasePage;public abstract class Home extends BasePage /用户名public abstract String getUsername();/密码public abstract String getPassword();/登陆表单的监听方法public void loginSubmit(IRequestCycle cycle) System.out.println(this.getUsername();System.out.println(this.getPassword();在Home.page文件中,我们修改如下: 首先我们看到的是对username和password两个property的定义,与Tapestry3不同的是,现在Tapestry4.0不需要为property指定类型,也就是说,Tapestry4.0会根据程序实际运行时装载到property的数据来自动转换对应的类型。在java中,我们声明了两个property调用的抽象方法:/用户名public abstract String getUsername();/密码public abstract String getPassword();因此,即便不用在page中声明这两个property的类型,Tapestry4.0也知道它们是String。接着我们声明了三个组件: Form组件和TextField组件的基本定义和用法与Tapestry3.0差不多,所以对其原理这里就不再累述。对于Home.html我们修改如下: 登陆   用户名: 密码:   在Html中嵌入jwcid与Tapestry3.0一样,只是唯一不同的是,在Tapestry4.0中,“jwcid”这个名词可以修改为你任意指定的单词。现在,开启服务器,启动项目,我们会看见一个表单页面:然后我们输入用户名和密码,就可以看见eclipse的控制台打印出对应的值:其实仔细看看Home.java中的loginSubmit监听方法,其IRequestCycle参数我们并没有使用,所以,该监听方法可以简便为:/登陆表单的监听方法public void loginSubmit() System.out.println(this.getUsername();System.out.println(this.getPassword();现在,我们再增加一些表单效验,比如,我们要求进行客户端用户名和密码效验,它们都必须输入,而且密码必须大于6位字符,于是修改Home.page中的Form组件和TextField组件声明为: 运行项目之后,我们忽然发现如下页面:从Tapestry4的报错页面中,我们发现,原来一旦对TextField添加客户端效验,就必须让其运行在Body组件之中,那么我们在Home.html的标签中添加Body组件:再次访问Home页面,OK,一切正常:也许你觉得非常奇怪,我们并没有写任何JavaScript代码,那么又如何完成客户端的JavaScript效验呢?这就是Tapestry组件动态script的魅力了。在这里我们使用的Form组件,在Tapestry4.0中,Form组件自带了一些动态script代码,不论Form组件使用在任何情况下的任何项目中,只要开启就可以实现JavaScript效验。Tapestry的组件就好比一个黑盒子,动态script就好比这个盒子中一块我们不需要了解的JavaScript代码,只要我们按动这个“盒子”上的一个“开关”,动态Script就会通过Tapestry框架自动生成适应当前表单的JavaScript代码。因此,即便这段动态Script不是我自己写的,我同样可以毫无顾忌地使用。2)水果商店OK,现在登陆已经实现了,现在我们来为“购物车”添加一些商品,假设我们都是卖水果的:我们定义一个普通的水果VO:package com.tapestry4;public class Fruit private Integer id; private String name; / 名称private float price; / 单价private int mount; / 数量public int getMount() return mount;public void setMount(int mount) this.mount = mount;public String getName() return name;public void setName(String name) = name;public float getPrice() return price;public void setPrice(float price) this.price = price;public Integer getId() return id;public void setId(Integer id) this.id = id;然后定义一个商品业务逻辑类:package com.tapestry4;import java.util.ArrayList;import java.util.List;public class Products private static List productList;public static List getProductList() if(productList=null) productList = new ArrayList();productList.add(createFruit(1, 苹果, 1.00f, 20);productList.add(createFruit(2, 西瓜, 0.80f, 10);productList.add(createFruit(3, 桔子, 1.50f, 25);productList.add(createFruit(4, 梨子, 2.00f, 30);return productList;public static Fruit createFruit(Integer ig, String name, float price, int mount) Fruit fruit = new Fruit();fruit.setId(ig);fruit.setName(name);fruit.setPrice(price);fruit.setMount(mount);return fruit;public static Fruit findFruitById(Integer ig) if(productList = null) productList = getProductList();Fruit fruit = null;for(Fruit f : productList) if(f.getId().intValue() = Value() fruit = f;return fruit;现在,我们需要一个展示商品的页面,命名为FirstPage:Shop.javapackage com.tapestry4;import java.util.List;import org.apache.tapestry.html.BasePage;public class Shop extends BasePage public List getFruitList() return Products.getProductList();Shop.page Shop.html 水果名称 单价 名称 单价元 为了能够在登陆之后,跳转到商品目录页面FirstPage,我们需要对Home.java进行修改:public abstract class Home extends BasePage /用户名public abstract String getUsername();/密码public abstract String getPassword();InjectPage(Shop)public abstract FirstPage getShopPage();/登陆表单的监听方法public IPage loginSubmit(IRequestCycle cycle) System.out.println(this.getUsername();System.out.println(this.getPassword();return this. getShopPage ();注意监听方法loginSubmit的返回参数,在这里,直接返回FirstPage页面的实例即可跳转到FirstPage页面。InjectPage(Shop)是Tapestry4.0新提供的annotation包中的一个annotation。凡是该annotation所声明的抽象getter方法,均会获取到指定页面的实例。在这里就获取到FirstPage页面的实例。在输入用户名和密码之后,我们就可以跳转到新页面了:3) 购买水果为了购买水果,我们需要为Shop页面的每个水果名称添加一个链接,一旦用户点击该种水果,我们就跳转到一个水果购买页面,该页面显示了水果的详细信息并且可以让用户输入购买的数量。为Shop页面的每个水果名称添加链接:修改Shop.html:package com.tapestry4;import java.util.List;import org.apache.tapestry.IPage;import org.apache.tapestry.annotations.InjectPage;import org.apache.tapestry.html.BasePage;public abstract class Shop extends BasePage InjectPage(BuyFruit)public abstract BuyFruit getBuyFruitPage();public List getFruitList() return Products.getProductList();public IPage buyFruit(Integer ig) BuyFruit page = this.getBuyFruitPage();page.setFruitId(ig);return page;修改Shop.page: 修改Shop.html: 水果名称 单价 名称 单价元 从上面的修改可以看出,我们添加了一个DirectLink组件,该组件的监听方法是public IPage buyFruit(Integer ig),并传递参数。熟悉T3的朋友会发现,T4中监听方法的用法有很大区别,现在我们看到的是监听方法的另外一种用法。直接将DirectLink传递的输入参数作为其监听方法的参数。一旦DirectLink触发监听方法,我们直接就可以从监听方法的输入参数中获取到被传递过来的fruit.id。当然,监听方法的输入参数是与fruit.id类型相对应的。public IPage buyFruit(Integer ig) BuyFruit page = this.getBuyFruitPage();page.setFruitId(ig);return page;在这个监听方法中,我们获取到了DirectLink传递的参数,并且我们向下一个页面传递水果的ID值,在下一个页面,我们就可以根据这个ID值,查找到对应的水果详细信息。水果详细信息页面:BuyFruitPage.javapackage com.tapestry4;import java.util.ArrayList;import java.util.List;import org.apache.tapestry.html.BasePage;public class BuyFruit extends BasePage private Integer fruitId;private int buyMount;Overrideprotected void initialize() fruitId = null;buyMount = 0;/ 获取水果详细信息public Fruit getFruitDetail() return Products.findFruitById(this.getFruitId();/ 购买水果SuppressWarnings(deprecation)public String buyFruitSubmit() FruitCart fc = new FruitCart();Fruit f = Products.findFruitById(this.getFruitId();fc.setBuyFruit(f);fc.setBuyMount(this.getBuyMount();fc.setPayMoney(f.getPrice() * this.getBuyMount();MyVisit visit = (MyVisit)this.getVisit();List list = visit.getFruitCartList();if(list = null) list = new ArrayList();list.add(fc);visit.setFruitCartList(list);return Cart;/ 重新选择水果public String backShopSubmit() return Shop;public Integer getFruitId() return fruitId;public void setFruitId(Integer fruitId) this.fruitId = fruitId;public int getBuyMount() return buyMount;public void setBuyMount(int buyMount) this.buyMount = buyMount;BuyFruitPage.page BuyFruitPage.html 水果名称 名称 单价 1.00元 存货 20斤 购买数量 斤 当在Shop页面选择水果之后,我们通过DirectLink向这个页面传递了一个水果ID。然后,在下面的方法中,我们获得了详细的水果信息:/获取水果详细信息public Fruit getFruitDetail() return Products.findFruitById(this.getFruitId();这个方法返回的是一个Fruit对象,因此我们直接通过Insert组件,将水果信息输出到页面上。 接着,我们希望用户输入购买的水果数量,要么提交购买,要么就返回前一个页面Shop重新选择水果。因此,我们需要一个表单,并使用TextField组件: 这里TextField组件的用法和前面一样,只是我们发现了一个有趣的参数translator。作为

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论