- 浏览: 1228323 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (353)
- java基础 (40)
- tapestry (16)
- gwt (14)
- ajax (7)
- linux (8)
- ubuntu (18)
- eclipse (6)
- dojo (2)
- javascript (7)
- maven (4)
- 日常生活 (29)
- web2.0 (2)
- jsonrpc (1)
- compass (1)
- lucene (0)
- spring (10)
- cluster (3)
- 数据结构 (2)
- sqlserver (1)
- tomcat (2)
- swing (1)
- servlet (1)
- hibernate (1)
- firefox (1)
- Java-Puzzlers (1)
- Wicket (2)
- mysql (10)
- windows (5)
- Webwork (1)
- struts2 (1)
- Seam (2)
- jboss (1)
- idea (6)
- 分布计算 (3)
- Python-Django (7)
- Hadoop (1)
- 工具 (3)
- Tokyo Tyrant (2)
- Comet (1)
- android (115)
- 音乐 (6)
- cxf (1)
- mqtt (1)
最新评论
-
hesai_vip:
学习了,感谢
gradlew wrapper使用下载到本地的gradle.zip文件安装。 -
imknown:
姚瑶大坏蛋 写道我也遇到了这个,用你这个方法,导致下拉刷新不起 ...
解决android-Ultra-Pull-To-Refresh下拉刷新组件中嵌套ViewPager的一个bug -
姚瑶大坏蛋:
我也遇到了这个,用你这个方法,导致下拉刷新不起作用了,你遇到过 ...
解决android-Ultra-Pull-To-Refresh下拉刷新组件中嵌套ViewPager的一个bug -
寐语者:
LeaderElection(String zookeeper ...
使用Zookeeper来为你的程序加上Leader Election的功能。 -
fyc0109:
博主, 安装了一部分还是报这个错误!FAILURE: Buil ...
gradlew wrapper使用下载到本地的gradle.zip文件安装。
有许多页面的一部分或者这个页面是很少更新的,他们通常是由外部文件来生成这个部分。所以我们可以把这部分内容cache住,当有新的请求时,我们就response cache,这样可以减少服务器的负担,还可以提高性能。其中oscache已经可以实现页面的cache和页面部分cache。oscache使用jsp tags来实现局部cache的。拿到Tapestry中肯定是行不通的。在同事的提醒下,想到写这个Tapestry的cache组件来达到重用的目的。
说干就干,先在头脑中想好要怎样使用cache(页面上的布局)。ok。 我想好了。
这里有2个参数,updateCondition 当为true时,我们就绕过cache, cacheProvider 我把他定义为一个接口,这样用户可以把cache存在任何地方。而且提供这样的一个接口,用户可以更好的操作cache。先看看jwc对cache组件的定义。
下面的是ICacheProvider接口:
ok。 再来看看Cache组件的代码。
在使用中你可以把CacheProvider放到Global或者Visit对象中。注意要使用同一个CacheProvider。
本来我是打算用oscache来实现了。 其实oscache自己带了filter来处理cache。 我想尽量把他做简单点。 容易理解。 其实你可以看到 我的这个组件需要提供个CacheProvider。 这个是个接口。 所以这样的话, 你想使用任何cache都是可以的。 只要用你现在用的cache实现CacheProvider就行了。 这样岂不是更灵活???
这里说说我的想法, 这个Cache主要是cache页面的,你想到的比较多,可能你忘了Cache组件中有个updateCondition 属性, 其实我是不太赞成ICacheProvider的removeCache这个方法的,这也是我开始想到使用idpath作为cacheKey的原因,用户不需要知道太多的东西。他仅仅需要知道什么时候我需要让tapestry重新生成一下Body的内容就行。 他也就需要实现updateConditon这个component方法。争对你说的这种场景, 我在updateCondition这个方法里面去判断数据库里面的最新帖子的时间和你生成cache时最新帖子的时间来比较(你可以保存在一个singtlon对象里面),如果时间更新了,return true就ok了。 其实我现在这个项目中也是这种情况,首页内容部分是由管理员upload的一个文件(owl file)生成的内容。这时候我在MiscUtils类里面有个checkOWLFileUpdated()方法去判断owl时候发生了变化, 也是使用file的lastmodfy time来判断的。 我在Cache组件中仅仅是非常方便的委派MiscUtils的那个方法而已。
你在上面也提到了主动的方式,就是在发表玩帖子的时候去设置updateCondition为true。其实你只要把这个值set到一个singlton类属性里面就ok了。 updateCondition方法就去check那个值吧。 我不是很赞成这种做法,因为他把一些非业务相关的逻辑加了进来,可能你会说我可以用aop方便的搞定这个。 但是我还是觉得判断cache是否要更新就让Cache组件来作罢(updateCondition)。
开始时我觉得这个cacheKey其实可以对用户不见的,用户不用关心cache的内容。其实这里的cache的内容也就是cache组件的body render之后的html source。但是ICacheProvider提供了removeCache这个方法。假如用idPath的对用户来说确实是不友好的。 指定cacheKey值的话,可读性也很高。这个想法不错。我会加入这个功能,多加个cacheKey属性,假如用户关心的话就指定, 不指定的话默认就是idpath。
<span cacheProvider="ognl:cacheProvider" cacheKey="literal:Home:news" updateCondition="ognl:needUpdate">
//body ....
</span>
@InjectCache("Home:news")
public CacheContent getHomeNewsCache();
你这个annotation的意思是获得cache的内容么? 我这里可能有多个cacheProvider, 而且我想用户可以方便的通过cacheProvider去拿到cache content。 再者我想用户肯定不会想去自己updateCache的内容,因为这个body是tapestry解析后的内容,我想用户关系的只是现在cache中的内容是不是stale的。我现在需不需要更新这个cache。 获得cache的内容交给tapestry来处理。 其实这个组件的目的也是主要是想cache页面的html source而已。
现在想要更新cache中的内容的话, 你只需要让updateCondition为true, 或者让对应的cache 内容为null 即可。
非常谢谢tapestry提供的建议,欢迎一起研究。
说干就干,先在头脑中想好要怎样使用cache(页面上的布局)。ok。 我想好了。
xml 代码
- <span jwcid="@Cache" cacheProvider="ognl:cacheProvider" updateCondition="ognl:needUpdate">
- //Cache body, which is the content you want to cache.
- <!---->span>
这里有2个参数,updateCondition 当为true时,我们就绕过cache, cacheProvider 我把他定义为一个接口,这样用户可以把cache存在任何地方。而且提供这样的一个接口,用户可以更好的操作cache。先看看jwc对cache组件的定义。
xml 代码
- xml version="1.0" encoding="UTF-8"?>
- "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
- "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
- <component-specification allow-body="yes" allow-informal-parameters="no" class="com.live.spaces.dengyin2000.tapestry.tfancomponents.components.Cache">
- <description>
- Cache component, this component can inclue any content as its body, and cache its body.
- This is useful in rarely updated content.
- <!---->description>
- <parameter name="updateCondition" required="no" default-value="false">
- <description>
- The flag that need to refresh cache, it would casue tapestry render not use the cache.
- <!---->description>
- <!---->parameter>
- <parameter name="cacheProvider" required="yes">
- <description>
- You need to provider an cache provider to store its body content. for some simply use.
- Please see @com.live.spaces.dengyin2000.tapestry.tfancomponents.components.SimpleHtmlSourceCacheProvider
- <!---->description>
- <!---->parameter>
- <!---->component-specification>
下面的是ICacheProvider接口:
java 代码
- package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;
- /**
- * @author Denny - deng.yin@gmail.com
- * @since 2006-12-21
- */
- public interface ICacheProvider {
- /**
- *
- * @param cacheKey
- * @param cacheContent
- */
- public void storeCache(String cacheKey, String cacheContent);
- /**
- *
- * @param cacheKey
- * @return
- */
- public String getCacheContent(String cacheKey);
- /**
- * This method provider to user, so that user can controll cache manaully.
- * @param cacheKey
- */
- public void removeCache(String cacheKey);
- /**
- * This method provider to user, so that user can controll cache manaully.
- * Clear all caches
- *
- */
- public void reset();
- }
ok。 再来看看Cache组件的代码。
java 代码
- package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;
- import java.io.PrintWriter;
- import java.io.StringWriter;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.tapestry.AbstractComponent;
- import org.apache.tapestry.IMarkupWriter;
- import org.apache.tapestry.IRequestCycle;
- import org.apache.tapestry.util.ContentType;
- /**
- * @author Denny deng
- *
- */
- public abstract class Cache extends AbstractComponent {
- protected static final Log logger = LogFactory.getLog(Cache.class);
- public abstract boolean getUpdateCondition();
- public abstract ICacheProvider getCacheProvider();
- @Override
- protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
- if (getUpdateCondition()){
- renderComponentWithCache(writer, cycle);
- }else{
- if (getCacheProvider().getCacheContent(this.getIdPath()) != null){
- //response cache html content.
- writer.printRaw(getCacheProvider().getCacheContent(this.getIdPath()));
- }else{
- renderComponentWithCache(writer, cycle);
- }
- }
- }
- private void renderComponentWithCache(IMarkupWriter writer, IRequestCycle cycle) {
- logger.debug("We need to refresh cache now.");
- CacheWriterWrapper cacheWrapper = new CacheWriterWrapper();
- super.renderBody(buildCacheMarkupWriter(cacheWrapper.getPrintWriter(), writer), cycle);
- String cacheContent = cacheWrapper.getCacheContent();
- logger.debug("fetched cache content, ready to put it into cache.");
- getCacheProvider().storeCache(this.getIdPath(), cacheContent);
- // response html content.
- writer.printRaw(cacheContent);
- }
- private IMarkupWriter buildCacheMarkupWriter(PrintWriter writer, IMarkupWriter sourceWriter){
- return this.getPage().getRequestCycle().getInfrastructure().getMarkupWriterSource().newMarkupWriter(writer, new ContentType(sourceWriter.getContentType()));
- }
- class CacheWriterWrapper{
- private StringWriter sw;
- private PrintWriter pw;
- public CacheWriterWrapper() {
- sw = new StringWriter();
- pw = new PrintWriter(sw);
- }
- public String getCacheContent(){
- return sw.getBuffer().toString();
- }
- public PrintWriter getPrintWriter(){
- return pw;
- }
- }
- }
主要是得到cache组件body的内容,然后把body的内容cache住,下次的话就response Cache的内容。 其实也是满简单的。
我自己还写了一个简单CacheProvider。
java 代码
- package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;
- import java.util.HashMap;
- import java.util.Map;
- /**
- * @author Denny - deng.yin@gmail.com
- * @since 2006-12-21
- */
- public class SimpleHtmlSourceCacheProvider implements ICacheProvider {
- private Mapnew HashMap
- public String getCacheContent(String cacheKey) {
- return cache.get(cacheKey);
- }
- public void storeCache(String cacheKey, String cacheContent) {
- cache.put(cacheKey, cacheContent);
- }
- public void removeCache(String cacheKey) {
- cache.remove(cacheKey);
- }
- public void reset() {
- cache.clear();
- }
- }
我在google code host上面建了一个probject地址是http://code.google.com/p/tfancomponents/ 有兴趣的同学可以看看, 这是一个maven项目。
评论
7 楼
dengyin2000
2007-08-10
koda 写道
不错!我想知道你为什么不直接使用oschache呢?
本来我是打算用oscache来实现了。 其实oscache自己带了filter来处理cache。 我想尽量把他做简单点。 容易理解。 其实你可以看到 我的这个组件需要提供个CacheProvider。 这个是个接口。 所以这样的话, 你想使用任何cache都是可以的。 只要用你现在用的cache实现CacheProvider就行了。 这样岂不是更灵活???
6 楼
koda
2007-08-10
不错!我想知道你为什么不直接使用oschache呢?
5 楼
dengyin2000
2006-12-22
tapestry 写道
我的CacheContent意思是封装一个对象,里边有个开关变量,设定是否需要update,当然还有cache的内容(这个才是你的cacheContent的意思),里边有个update方法,因为总感觉update应该是cache自己的事情,但实验了一下概念还是比较乱,先暂时放放。
使用起来应该有两种情况,一种是设置页面的update开关,一种是cacheProvider的removeCache。试想这样一个场景,ShowBlogs页面,你cache住了,然后用户添加了blog,除非他添加完后直接需要到ShowBlogs页面,可以调用ShowBlogs.setNeedUpdate(true),然后显示ShowBlogs页面来刷cache,但一般情况很可能不是跳到ShowBlogs页面,可能是用户自己的ManageBlogs页面,这个时候更新的唯一方法就是调用cacheProvider.removeCache了。
cacheProvider里加个updateCache方法吧,方法里调用removeCache,这样api清楚点。
使用起来应该有两种情况,一种是设置页面的update开关,一种是cacheProvider的removeCache。试想这样一个场景,ShowBlogs页面,你cache住了,然后用户添加了blog,除非他添加完后直接需要到ShowBlogs页面,可以调用ShowBlogs.setNeedUpdate(true),然后显示ShowBlogs页面来刷cache,但一般情况很可能不是跳到ShowBlogs页面,可能是用户自己的ManageBlogs页面,这个时候更新的唯一方法就是调用cacheProvider.removeCache了。
cacheProvider里加个updateCache方法吧,方法里调用removeCache,这样api清楚点。
这里说说我的想法, 这个Cache主要是cache页面的,你想到的比较多,可能你忘了Cache组件中有个updateCondition 属性, 其实我是不太赞成ICacheProvider的removeCache这个方法的,这也是我开始想到使用idpath作为cacheKey的原因,用户不需要知道太多的东西。他仅仅需要知道什么时候我需要让tapestry重新生成一下Body的内容就行。 他也就需要实现updateConditon这个component方法。争对你说的这种场景, 我在updateCondition这个方法里面去判断数据库里面的最新帖子的时间和你生成cache时最新帖子的时间来比较(你可以保存在一个singtlon对象里面),如果时间更新了,return true就ok了。 其实我现在这个项目中也是这种情况,首页内容部分是由管理员upload的一个文件(owl file)生成的内容。这时候我在MiscUtils类里面有个checkOWLFileUpdated()方法去判断owl时候发生了变化, 也是使用file的lastmodfy time来判断的。 我在Cache组件中仅仅是非常方便的委派MiscUtils的那个方法而已。
你在上面也提到了主动的方式,就是在发表玩帖子的时候去设置updateCondition为true。其实你只要把这个值set到一个singlton类属性里面就ok了。 updateCondition方法就去check那个值吧。 我不是很赞成这种做法,因为他把一些非业务相关的逻辑加了进来,可能你会说我可以用aop方便的搞定这个。 但是我还是觉得判断cache是否要更新就让Cache组件来作罢(updateCondition)。
4 楼
tapestry
2006-12-22
还有几点疑问,一个是tapestry本身就cache住了静态的模版文档,只需要动态内容添加进去然后生成页面,这个cache应该说是想将静态和动态内容cache住,不需要再生成了,既然是动态的必须是可被更新的,所以要给出个key来,好让人更新,老是调用页面去设置开关然后再显示好像不大方便,现在设置key的话就存在key的管理问题了,今天设定为news了,明天改了成newses了,好多地方就会更新不到了,设为enum或者常量都可以,一个数据字典的概念了,比如Home页面有3个cache了,分别是news,tags,links,后台更新数据的时候来看看哪里用了news了,更新下。这个扯远了,不过老是感觉还有改进的可能,但又暂时想不到。
3 楼
tapestry
2006-12-22
我的CacheContent意思是封装一个对象,里边有个开关变量,设定是否需要update,当然还有cache的内容(这个才是你的cacheContent的意思),里边有个update方法,因为总感觉update应该是cache自己的事情,但实验了一下概念还是比较乱,先暂时放放。
使用起来应该有两种情况,一种是设置页面的update开关,一种是cacheProvider的removeCache。试想这样一个场景,ShowBlogs页面,你cache住了,然后用户添加了blog,除非他添加完后直接需要到ShowBlogs页面,可以调用ShowBlogs.setNeedUpdate(true),然后显示ShowBlogs页面来刷cache,但一般情况很可能不是跳到ShowBlogs页面,可能是用户自己的ManageBlogs页面,这个时候更新的唯一方法就是调用cacheProvider.removeCache了。
cacheProvider里加个updateCache方法吧,方法里调用removeCache,这样api清楚点。
使用起来应该有两种情况,一种是设置页面的update开关,一种是cacheProvider的removeCache。试想这样一个场景,ShowBlogs页面,你cache住了,然后用户添加了blog,除非他添加完后直接需要到ShowBlogs页面,可以调用ShowBlogs.setNeedUpdate(true),然后显示ShowBlogs页面来刷cache,但一般情况很可能不是跳到ShowBlogs页面,可能是用户自己的ManageBlogs页面,这个时候更新的唯一方法就是调用cacheProvider.removeCache了。
cacheProvider里加个updateCache方法吧,方法里调用removeCache,这样api清楚点。
2 楼
dengyin2000
2006-12-22
tapestry 写道
这个idea不错,还有扩展的余地,保存的key最好不要用idPath,自己可以定义,例如定义一个cache名字为news,key应该为Home:news,这样我可以使用cacheProvider.update("Home:news")来更新,还可以写个annotation,例如我新建了个news,
@InjectCache("Home:news")
public CacheContent getHomeNewsCache();
public void save(){
getNewsService().save(getNews());
getHomeNewsCache().update();
}
这样可用性比较好,有兴趣的话,一起研究一下。
@InjectCache("Home:news")
public CacheContent getHomeNewsCache();
public void save(){
getNewsService().save(getNews());
getHomeNewsCache().update();
}
这样可用性比较好,有兴趣的话,一起研究一下。
开始时我觉得这个cacheKey其实可以对用户不见的,用户不用关心cache的内容。其实这里的cache的内容也就是cache组件的body render之后的html source。但是ICacheProvider提供了removeCache这个方法。假如用idPath的对用户来说确实是不友好的。 指定cacheKey值的话,可读性也很高。这个想法不错。我会加入这个功能,多加个cacheKey属性,假如用户关心的话就指定, 不指定的话默认就是idpath。
<span cacheProvider="ognl:cacheProvider" cacheKey="literal:Home:news" updateCondition="ognl:needUpdate">
//body ....
</span>
@InjectCache("Home:news")
public CacheContent getHomeNewsCache();
你这个annotation的意思是获得cache的内容么? 我这里可能有多个cacheProvider, 而且我想用户可以方便的通过cacheProvider去拿到cache content。 再者我想用户肯定不会想去自己updateCache的内容,因为这个body是tapestry解析后的内容,我想用户关系的只是现在cache中的内容是不是stale的。我现在需不需要更新这个cache。 获得cache的内容交给tapestry来处理。 其实这个组件的目的也是主要是想cache页面的html source而已。
现在想要更新cache中的内容的话, 你只需要让updateCondition为true, 或者让对应的cache 内容为null 即可。
非常谢谢tapestry提供的建议,欢迎一起研究。
1 楼
tapestry
2006-12-22
这个idea不错,还有扩展的余地,保存的key最好不要用idPath,自己可以定义,例如定义一个cache名字为news,key应该为Home:news,这样我可以使用cacheProvider.update("Home:news")来更新,还可以写个annotation,例如我新建了个news,
@InjectCache("Home:news")
public CacheContent getHomeNewsCache();
public void save(){
getNewsService().save(getNews());
getHomeNewsCache().update();
}
这样可用性比较好,有兴趣的话,一起研究一下。
@InjectCache("Home:news")
public CacheContent getHomeNewsCache();
public void save(){
getNewsService().save(getNews());
getHomeNewsCache().update();
}
这样可用性比较好,有兴趣的话,一起研究一下。
发表评论
-
解决用run-jetty-run锁住css,js文件的问题。
2008-09-25 17:46 6658开发中用run-jetty-run插件启动jetty调式tap ... -
打造Tapestry5中的智能的错误页面。
2008-09-18 15:59 1815我们一般需要为生产和开发环境准备两套error page。 t ... -
T5这么多的Page Lifecycle method, 应该怎样使用?
2008-09-04 18:18 2405Tapestry5种大概有以下Page ... -
扔掉T5复杂的Grid组件,打造自己灵活的支持分页排序组件。
2008-01-03 13:12 2884Grid算是比较T5中较复杂的一个组件,我也有篇介绍Grid怎 ... -
对Tapestry的一点思考。
2007-12-27 23:33 4104Tapestry5已经开发了蛮久了。 听说最近要发布T5.0. ... -
Tapestry 5.0.5 bug, TAPESTRY-1648
2007-08-26 12:20 2637有一个domian object, 其中有个property的 ... -
T5 技巧 3:使用“t::body”进行布局。
2007-08-25 00:08 2952现在正在使用T5开发一个小项目。 因为现在T5还正处于发展中。 ... -
T5 技巧 2:为Grid组件的每一行增加“删除/修改”链接。
2007-08-21 12:35 9047现在正在使用T5开发一个小项目。 因为现在T5还正处于发展中。 ... -
T5 技巧 1:解决Form的提交乱码问题。
2007-08-21 10:58 8387现在正在使用T5开发一个小项目。 因为现在T5还正处于发展中。 ... -
T5 developing with WTP and TOMCAT
2007-08-16 09:50 2751以下是我发给tapestry右键列表的问题。 现在还没有人回复 ... -
Wicket Vs Tapestry
2007-05-11 14:41 7490我是一个tapestry的老用户。从学校毕业就开始使用tape ... -
Tapestry5中 page template不能reload。
2007-05-09 13:50 5895上午看了下tapestry5的文档,然后自己写了个简单的页面。 ... -
Tapestry Table 组件的强大(分页查询时只fetch当前页的数据)。
2006-03-01 16:00 4376导入的blog格式乱了,大 ... -
Tapestry 显示图片
2006-03-06 16:00 2785导入的blog格式乱了,请看我的msn spaces blog ... -
@Persist 解释
2006-03-08 16:00 3160a) @Persist("client") ...
相关推荐
在 Tapestry 5 框架中,自定义组件是扩展其功能的关键方式,它允许开发者根据特定需求创建个性化和可重用的 UI 元素。Tapestry 5 是一个强大的 Java Web 应用程序开发框架,它强调组件化、模块化以及声明式编程模型...
介绍Tapestry组件的使用和功能。内容还行,使用初学者入门。
在本篇文章中,我们将深入探讨Tapestry的页面编辑组件,以及如何利用这些组件创建交互式的用户界面,包括文本框、单选框、多选框和下拉框。 首先,让我们理解什么是Tapestry页面编辑组件。在Tapestry中,组件是可...
tapestry部分组件绑定参数的列表!
本文将深入探讨Tapestry 4.02版本中对ExtJS的GridPanel组件进行封装的相关知识点。 首先,Tapestry是一个基于Java的开源Web应用框架,它提供了组件化开发的方式,使得开发者可以构建出结构清晰、可维护性强的大型...
Tapestry是一款强大的Java Web应用程序框架,由Apache软件基金会维护,它提供了一种基于组件的模型来构建动态、数据驱动的Web应用。本教程将帮助初学者了解Tapestry的基本概念,带你逐步入门并掌握其核心组件的使用...
Tapestry的组件化设计使得开发人员可以快速构建动态、响应式的用户界面,如在描述中提到的`form`组件和`table`组件。`form`组件用于处理用户输入,创建表单并进行验证,而`table`组件则用于展示数据,支持分页和排序...
Tapestry是一款强大的Java Web应用程序框架,由Apache软件基金会维护,它强调了组件化、模块化和可重用性,使得开发复杂的Web应用变得更加简单。本文将深入介绍Tapestry 4的相关知识点。 1. **组件化编程**: ...
Tapestry是一个基于Java的全栈Web应用程序框架,它的设计目的是为了简化Web应用开发,提供组件化和高度交互性的页面。Tapestry并不是一个应用服务器,而是一个可以在应用服务器中运行的框架,用于构建动态、复杂的...
2. **组件实例化**:根据页面和组件定义,Tapestry 创建必要的组件实例。 3. **状态管理**:Tapestry 自动处理组件状态的保存和恢复,确保在多个请求间保持一致性。 4. **渲染**:Tapestry 将组件渲染成HTML响应,...
Tapestry 是一个基于 Java 的开源Web 应用程序框架,它强调组件化开发,提供了一种强大的方式来构建动态、高性能的Web 应用。在"tapestry-project-4.1.5"这个压缩包中,我们有机会深入探索 Tapestry 4.1.5 版本的...
Tapestry 是一个开源的基于 servlet 的应用程序框架,它使用组件对象模型来创建动态的、交互的 web 应用。 Tapestry 使得 Java 代码与 HTML 完全分离,利用这个框架开发大型应用变得轻而易举。并且开发的应用很容易...
Tapestry是一个基于Java的Web应用框架,它采用了面向组件的开发方式,这使得它与其他如Structs、WebWork、SpringMVC等采用传统面向元素开发方式的框架有所不同。面向组件的开发模式旨在克服面向元素开发中的局限性,...
Tapestry的组件系统非常强大,允许开发者定义自己的可复用组件,每个组件都可以有自己的属性、事件和行为。这些组件可以通过简单的XML标记(如`<span jwcid="@Insert" ...>`)在页面模板中使用。ognl(Object-Graph ...
- **组件状态管理**:探讨了Tapestry中组件状态的生命周期及其管理方法,包括如何在不同的请求之间保持组件的状态。 #### 第5章:表单输入验证 - **内置验证器**:详细列出了Tapestry提供的内置验证器类型,如长度...
2. **组件化开发**:Tapestry采用了组件化的开发模式,每个页面或页面的一部分都可以被视为一个组件,这些组件可以被重用,并且易于维护。 3. **强大的模板系统**:Tapestry提供了一套丰富的模板语言,开发者可以...
1. **页面和组件的生命周期**:每个Tapestry 3应用由一系列页面组成,页面又包含多个组件。Tapestry管理这些页面和组件的创建、初始化、渲染和销毁过程。 2. **模板和元数据**:Tapestry使用HTML模板定义页面布局,...
在学习过程中,开发者会了解到如何使用Tapestry的组件进行页面布局、如何通过tapestry组件实现数据的增删改查操作、如何通过tapestry的LinkSubmit组件实现表单提交、如何进行表单验证以及如何使用tapestry的上传组件...
1. **Tapestry Core**: 这是Tapestry框架的基础部分,包含了核心组件、服务容器(Tapestry IoC)和页面生命周期管理。通过源码分析,我们可以理解其如何实现页面组件的渲染、事件处理和依赖注入。 2. **Tapestry ...
Tapestry API提供了`Component`接口和相关的实现类,例如`Page`和`ComponentTemplate`,用于构建这些组件。 2. **MVC架构** 在Tapestry中,模型、视图和控制器的概念得到了清晰的体现。`Model`代表数据和业务逻辑...