blogjava-凯发k8网页登录http://www.blogjava.net/usherlight/category/38735.html天平山上白云泉,云自无心水自闲。何必奔冲山下去,更添波浪向人间!zh-cntue, 29 mar 2011 08:15:20 gmttue, 29 mar 2011 08:15:20 gmt60tapestry5 in action(manning)的第一章免费阅读http://www.blogjava.net/usherlight/archive/2011/03/29/347159.html云自无心水自闲云自无心水自闲mon, 28 mar 2011 21:53:00 gmthttp://www.blogjava.net/usherlight/archive/2011/03/29/347159.htmlhttp://www.blogjava.net/usherlight/comments/347159.htmlhttp://www.blogjava.net/usherlight/archive/2011/03/29/347159.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/347159.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/347159.html
tapestry5 in action现在还只是提供meap形式的订购,meap-manning early access program, 也就是提前试阅的意思,如果读者订购了此版本,那么manning会在作者每完成一章后,将该章节发给订购者,订购者可以提交自己的反馈,manning会根据情况发布相应的错误修改信息。
目前此书的第一章可以免费下载:

http://www.blogjava.net/files/usherlight/tapestry5 in action meap ch01.zip


云自无心水自闲 2011-03-29 05:53
]]>
tapestry的一些最新动态http://www.blogjava.net/usherlight/archive/2010/11/24/338872.html云自无心水自闲云自无心水自闲tue, 23 nov 2010 22:08:00 gmthttp://www.blogjava.net/usherlight/archive/2010/11/24/338872.htmlhttp://www.blogjava.net/usherlight/comments/338872.htmlhttp://www.blogjava.net/usherlight/archive/2010/11/24/338872.html#feedback3http://www.blogjava.net/usherlight/comments/commentrss/338872.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/338872.html 1、tapestry5.2.4的发布,tapestry5.2.3版本在内部投票中被否决(主要是因为使用maven快速创建的原型有问题),所以在被否决的3天后便发布了5.2.4,相对5.2.2来说,变动并不大,只有8个错误修复和5个功能改进。但是至少说明tapestry的项目还在顺利的进行中。
2、tapestry凯发k8网页登录主页的全新改版。主要是完善了文档。这一点是非常重要的,tapestry项目组的成员也承认tapestry在推销自己或者是在市场推广方面做得非常失败(very bad in marketing),所以最近也采取了一些措施来进行改变,比如,预计明年会发行tapestry5 in action一书等等。
3、还有一件事需要提及的是:appfuse的作者最近对web框架进行了一番对比http://raibledesigns.com/rd/entry/my_comparing_jvm_web_frameworks,tapestry在13个框架中名列第7,刚好是中间的位置。tapestry项目的成员颇有不满,认为作者matt raible对tapestry不够了解,有误导观众之嫌。tapestry项目成员igor e. poteryaev认为matt在 认识度,开发效率,项目健康度,测试友好性,scalability等方面严重低估了tapestry的能力。


云自无心水自闲 2010-11-24 06:08
]]>
tapestry5.2.2(beta release)发布了http://www.blogjava.net/usherlight/archive/2010/11/02/336747.html云自无心水自闲云自无心水自闲mon, 01 nov 2010 23:58:00 gmthttp://www.blogjava.net/usherlight/archive/2010/11/02/336747.htmlhttp://www.blogjava.net/usherlight/comments/336747.htmlhttp://www.blogjava.net/usherlight/archive/2010/11/02/336747.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/336747.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/336747.html 这主要是便于ajax的使用。

bug

    *  element.forceattribute uses the element's namespace to match the attribute.
    *  element.attribute(string name, string value) adds elements that already exist
    *  element#addclassname can create an additional new 'class' attribute
    *  properties defined in an interface are not exposed by propertyaccess for abstract classes that do not directly implement the methods
    *  some services require a notification that they have been reloaded, so they can clean up external dependencies
    *  whitespaces in symbolconstants.supported_locales cause that locales are not persised
    *  validation macros do not work when used in @validate annotation
    *  client-side validation of @pattern is broken
    *  linking a form to a zone will no longer work unless the form contains validated fields
    *  when using propertyshadowbuilder to build a service, if the property is null, an immediate exception is needed (rather than a nullpointerexception)
    *  when using a multizoneupdate, tapestry will clear the referenced zone

improvement

    *  add the facility to optionally disable on-focus-change triggered validation while retaining the on-form-submit validation
    *  form component should be able to render a secure url even on an insecure page
    *  new annotations @decorate and @advise to identify methods that decorate or annotate services
    *  extend link with new methods for producing absolute urls (that include scheme, hostname, etc.)
    *  simplify connecting a link or form to an (enclosing) zone
    *  beanblockcontribution should be split into two sub-classes: editblockcontribution and displayblockcontribution
    *  define a special css class to prevent a client-side form from submitting normally (for ajax use cases)
    *  additional method for link: addparametervalue(string,object) that uses contextpathencoder to encode object value to a string
    *  seleniumtestcase should expose the underlying commandprocessor, to allow execution of commands not defined by the selenium interface
    *  allow individual seleniumtestcases to run w/o configuring seleniumlauncher



云自无心水自闲 2010-11-02 07:58
]]>
tapestry5.2.1 beta已经发布http://www.blogjava.net/usherlight/archive/2010/10/20/335644.html云自无心水自闲云自无心水自闲tue, 19 oct 2010 23:38:00 gmthttp://www.blogjava.net/usherlight/archive/2010/10/20/335644.htmlhttp://www.blogjava.net/usherlight/comments/335644.htmlhttp://www.blogjava.net/usherlight/archive/2010/10/20/335644.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/335644.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/335644.html今天在网上转了转,发现tapestry又有了新动作。
1、从5.2.0alpha版8月11日发布到现在,终于发布5.2.1beta版了。这个版本主要是修改alpha版本中的bug.
5.2相对于5.1进行了许多重大的改进,详细内容可见:
2、据称在5.3版中将引入大量的新功能,具体内容不详。
3、以往最令人诟病的文档问题,目前开发小组也在努力解决。
     首先,建立了新的文档网页:http://people.apache.org/~uli/tapestry-site/,不过目前这个网站还没有完全完成,只能算是预览版,但是这毕竟是在正确的道路上前进。
     其次,tapestry 5 in action一书正在写作中,已经完成20%,预计明年一季度能够出版。
我相信,随着功能的不断完善和补充,再加上文档的逐渐充实,tapestry完全有理由能吸引更多的开发者来关注和使用。

云自无心水自闲 2010-10-20 07:38
]]>
tapestry5.2的新变化http://www.blogjava.net/usherlight/archive/2010/08/18/329170.html云自无心水自闲云自无心水自闲tue, 17 aug 2010 23:13:00 gmthttp://www.blogjava.net/usherlight/archive/2010/08/18/329170.htmlhttp://www.blogjava.net/usherlight/comments/329170.htmlhttp://www.blogjava.net/usherlight/archive/2010/08/18/329170.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/329170.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/329170.html 1、增强了class reload的功能(我个人也认为这一点是5.2版本最令人激动的改进),以前tapestry和其他的web框架类似,修改页面不需要重新启动application server, 但是修改了类之后,必须重新启动应用服务器才行。但是在tapestry5.2中,对这一点进行了修改,如果只改变了接口的实现类,而不改变接口的方法签名,就不需要重新启动应用服务器
2、新增了若干个组件,比如:error和trigger。
error和原有的errors类似,但是error用于给指定的组件显示验证错误信息。
trigger提供了在泻染页面过程中触发任务事件的功能,常常用于通过rendersupport来给页面添加javascript代码
3、新的插件(mixin),包括renderclientid, rendernotification
4、集成了jsr-303 bean的验证,现在可以在页面中使用jsr-303标准的注解来给字段指定需要的验证
5、新的注解,包括@contribute,@requestparameter, @activationrequestparameter, 使用后两个注解能很容易地获取request中的参数
6、新的页面生命周期事件:pagereset
7、链接修饰过程中的新事件: decoratepagerenderlink, decoreatecomponenteventlink
8、页面解析器的更换,原来使用stax,造成了对google app engine和对osgi的不兼容,5.2版本中使用了标准的sax解析器
9、页面缓冲池的废除(我认为这是5.2版本的一个相当大而且也是非常重要的一个变化,我认为页面缓冲池技术是tapestry学习曲线陡峭的一个重要原因),5.2版本中所有页面将只有一个实例(也就是lewis howard说的单例化),页面属性的值将会在每个线程中使用一个map来保存。这样一个页面实例可以在多个线程中使用,而不会有同步问题。
但是,由于这是一个新的尝试,所以lewis也不确定这样做的效果是否很好(详见:http://tapestryjava.blogspot.com/2010/07/everyone-out-of-pool-tapestry-goes.html)所以,在5.2中可以通过配置恢复页面缓冲池的使用。

云自无心水自闲 2010-08-18 07:13
]]>
prototype版的table filterhttp://www.blogjava.net/usherlight/archive/2010/07/28/327294.html云自无心水自闲云自无心水自闲wed, 28 jul 2010 03:02:00 gmthttp://www.blogjava.net/usherlight/archive/2010/07/28/327294.htmlhttp://www.blogjava.net/usherlight/comments/327294.htmlhttp://www.blogjava.net/usherlight/archive/2010/07/28/327294.html#feedback1http://www.blogjava.net/usherlight/comments/commentrss/327294.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/327294.htmljquery有一个很方便的插件ui table filter可以根据输入的内容隐藏显示表格中相应的数据行。
因为目前使用的tapestry捆绑的是prototype,所以就自己写了一个类似的插件。







 
  filter: case-sensitive
  
   
    
     
     
     
     
     
     
     
    
   
   
    
    
    
    
    
    
    
   
   
    
    
    
    
    
    
    
   
   
    
    
    
    
    
    
    
   
   
    
    
    
    
    
    
    
   
   
    
    
    
    
    
    
    
   
  
namecolumn1column2column3column4column5column6
test00150002331238156075001172.16.14.201-1-05
test-200150002332238157075002172.16.14.211-1-05
test00150002333238158075003172.16.14.231-1-05
test00150002341238159075004172.16.14.241-1-05
test00150002339238186075006172.16.14.261-1-06

 
  

如果页面中多个表格,而只需要对其中的一个表格的数据进行过滤的话,简单地把其中:$$('tr').each(function(ele, index) 改成 $$('#tableid, tr').each(function(ele, index) 就行了,其中的tableid就是表格的id

云自无心水自闲 2010-07-28 11:02
]]>
tapestry5.2的alpha版本已经发布http://www.blogjava.net/usherlight/archive/2010/07/15/326156.html云自无心水自闲云自无心水自闲thu, 15 jul 2010 00:20:00 gmthttp://www.blogjava.net/usherlight/archive/2010/07/15/326156.htmlhttp://www.blogjava.net/usherlight/comments/326156.htmlhttp://www.blogjava.net/usherlight/archive/2010/07/15/326156.html#feedback2http://www.blogjava.net/usherlight/comments/commentrss/326156.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/326156.html 在5.2中还是新增了不少令人激动的功能
1、queryparametermapped注解,使用这个注解可以很方便地把request中的参数映射到bean里的属性
2、(这是最让我期待的功能)服务终于能够动态加载了!
3、在事件处理方法中可以使用queryparameter来注解参数
4、submit组件现在可以cancel表单里的数据了
5、不再使用stax作为tml的解析器了,而是采用标准的sax解析器,这样减少外界引用,而且兼容性更好
6、组件中也可以使用sessionattribute来获得session中的数据了,以前好像只有在page中才能用
7、引入了jsr-303 bean validation integration library.

云自无心水自闲 2010-07-15 08:20
]]>
tapestry5.2 beta版已经完成http://www.blogjava.net/usherlight/archive/2010/06/03/322593.html云自无心水自闲云自无心水自闲thu, 03 jun 2010 02:31:00 gmthttp://www.blogjava.net/usherlight/archive/2010/06/03/322593.htmlhttp://www.blogjava.net/usherlight/comments/322593.htmlhttp://www.blogjava.net/usherlight/archive/2010/06/03/322593.html#feedback1http://www.blogjava.net/usherlight/comments/commentrss/322593.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/322593.html 作者相信ga版本将会在不久的未来发布。
所作者透露,在新版本中会增加一个新的组件:dynamic.

这个组件的用途是更换皮肤。在旧版本的tapestry中,由于tapestry的模板是一致的,所以要实现换肤相当困难。
但在新版本中的这个组件比较完美地解决了这个问题。
作者自我评价这个组件是令人激动的一个新事物。




云自无心水自闲 2010-06-03 10:31
]]>
完美是优秀的敌人the perfect is the enemy of the goodhttp://www.blogjava.net/usherlight/archive/2010/03/19/315858.html云自无心水自闲云自无心水自闲thu, 18 mar 2010 23:40:00 gmthttp://www.blogjava.net/usherlight/archive/2010/03/19/315858.htmlhttp://www.blogjava.net/usherlight/comments/315858.htmlhttp://www.blogjava.net/usherlight/archive/2010/03/19/315858.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/315858.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/315858.html出自伏尔泰的名句。在许多优秀的程序员的编程习惯中,寻找凯发天生赢家一触即发官网的解决方案就如同是寻找女友一般,总是力求完美,如果一个凯发天生赢家一触即发官网的解决方案不够完美的话,那么宁可舍弃也不会降低标准而采用。但是这样的结果很有可能会是一叶障目,不见森林。
举个实际的例子来说,tapestry5的服务动态加载就是一个典型。
大家知道,在tapestry中,页面模板的动态加载一直是其的一个宣传点。也就是说,页面模板如果修改了,不需要重新启动应用服务器,修改即时生效。但是,tapestry却一直没有实现服务的动态加载,也就是说服务的类修改了,就必须重新启动服务器。为什么呢,因为追求完美。
其实很久以前在tapestry的作者的头脑中,包括许多的用户都想在tapestry中加入服务动态加载的功能,但是最后作者却放弃了。原因是因为,在tapestry的架构中,服务比页面要复杂的多,服务不是单独存在的,他会被inject到许多其他的服务,而这些服务又会被inject到其他的服务中,最后导致你很难界定哪些类需要被重新加载。
但是最近有一个人提出一个建议,为什么要实现完整的动态加载呢。其实只实现服务的实现类的动态加载就已经很好了。
确实,如果保持接口不变,只在接口具体实现修改的时候加载,确实大大简化了问题,因为这样变化范围就被限定在单个类之内了。虽然这样并不完美,因为如果改变了对外接口,比如,添加了一个新的方法,或者改变了方法的签名,还是需要重新启动服务器。可是这样也已经在很大程度上提升了用户的使用满意度。
正如有句古语所说:退一步海阔天空。也在此提醒自己在以后的开发过程中,尽量拓展自己的思维,不要一下子钻到牛角尖里。


云自无心水自闲 2010-03-19 07:40
]]>
tapestry 最新版5.1.0.5教程(十二):自定义前缀prefixhttp://www.blogjava.net/usherlight/archive/2010/03/06/314700.html云自无心水自闲云自无心水自闲sat, 06 mar 2010 07:54:00 gmthttp://www.blogjava.net/usherlight/archive/2010/03/06/314700.htmlhttp://www.blogjava.net/usherlight/comments/314700.htmlhttp://www.blogjava.net/usherlight/archive/2010/03/06/314700.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/314700.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/314700.html在教程的第四部分(http://www.blogjava.net/usherlight/archive/2009/06/20/283396.html)我们已经粗略地介绍了tapestry的前缀,其中提及最常用的两种literal和prop。这里顺便再介绍一下其他的几个前缀.
1、context,这个经常在引用图片的时候用到。比如: 这样就能够在页面上显示在web-inf/images/icon.png
2、message,这个是需要i18n的应用必用的前缀。${message:some-key}
3、var,用于定义生成一个临时变量。比如:
  • ${var:index}
  • 。如果没有加这个前缀var:的话,就需要在页面类中添加一个property: index以及相应的getter和setter。
    我们这次介绍自定义一个cycle前缀,这个可以用于在表格中显示不同背景的行(也就是斑马条)。
    比如:

    ...

    或者

    aaaa

    自定义prefix一般来说是3个步骤,
    1、定义一个bindingfactory,这个需要实现bindingfactory接口
    2、定义一个binding继承abstractbinding
    3、注册这个binding

    看一下具体的prefix的类:

     1import java.util.arraylist;
     2import java.util.list;
     3
     4import org.apache.tapestry5.binding;
     5import org.apache.tapestry5.bindingconstants;
     6import org.apache.tapestry5.componentresources;
     7import org.apache.tapestry5.ioc.location;
     8import org.apache.tapestry5.services.bindingfactory;
     9import org.apache.tapestry5.services.bindingsource;
    10
    11/**
    12 * implementation of the cycle: binding prefix -- we parse list of bindings
    13 * and generate delegate bindings for each element

    14 * default binding is literal, other bindings can be used by specifying prefix.

    15 * example: "cycle:prop:name,prop:lastname,sth,sth else"
    16 */

    17public class cyclebindingfactory implements bindingfactory {
    18    private final bindingsource _bindingsource;
    19
    20    public cyclebindingfactory(bindingsource source){
    21        this._bindingsource = source;
    22    }

    23    
    24    public binding newbinding(string description, componentresources container, componentresources component,
    25            string expression, location location)
    26    {
    27        list<binding> delegates = new arraylist<binding>();
    28        string[] bindingnames = expression.split(",");
    29
    30        for (string bindingname : bindingnames){
    31            string defaultbinding = bindingconstants.literal;
    32
    33            binding binding = _bindingsource.newbinding(description, container, component, defaultbinding, bindingname, location);
    34            delegates.add(binding);
    35        }

    36        
    37        cyclebinding cyclebinding = new cyclebinding(delegates);
    38        container.addpagelifecyclelistener(cyclebinding);
    39            
    40        return cyclebinding;
    41    }

    42}

     1import java.util.list;
     2
     3import org.apache.tapestry5.binding;
     4import org.apache.tapestry5.internal.bindings.abstractbinding;
     5import org.apache.tapestry5.runtime.pagelifecyclelistener;
     6
     7
     8public class cyclebinding extends abstractbinding implements pagelifecyclelistener{
     9    private final list<binding> delegates;
    10    private int index = 0;
    11
    12    public cyclebinding(list<binding> delegates) {
    13        this.delegates = delegates;
    14    }

    15
    16    public object get() {
    17        object ret = delegates.get(index).get();
    18        index 
    19        if(index>=delegates.size()) index = 0;
    20        return ret;
    21    }

    22    
    23    @override
    24    public boolean isinvariant() {
    25        return false;
    26    }

    27    
    28    @override
    29    public class<object> getbindingtype() {
    30        return object.class;
    31    }

    32
    33
    34    public void containingpagediddetach() {
    35        index=0;
    36    }

    37
    38    public void containingpagedidattach() {/*not interested*/}
    39    
    40    public void containingpagedidload() {/*not interested*/}
    41}

    binding和bindingfactory写好了,注册后就可以使用了,注册的过程是在appmodel中添加以下一段代码:
    1    public static void contributebindingsource(
    2            mappedconfiguration<string, bindingfactory> configuration,
    3            bindingsource bindingsource
    4            )
    5    {
    6        configuration.add("cycle",new cyclebindingfactory(bindingsource));
    7    }
     




    云自无心水自闲 2010-03-06 15:54
    ]]>
    tapestry 最新版5.1.0.5教程(十一):自定义组件checkboxgrouphttp://www.blogjava.net/usherlight/archive/2010/02/12/312607.html云自无心水自闲云自无心水自闲thu, 11 feb 2010 23:26:00 gmthttp://www.blogjava.net/usherlight/archive/2010/02/12/312607.htmlhttp://www.blogjava.net/usherlight/comments/312607.htmlhttp://www.blogjava.net/usherlight/archive/2010/02/12/312607.html#feedback3http://www.blogjava.net/usherlight/comments/commentrss/312607.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/312607.html 本文就用一个实例来看一下tapestry中是如何添加一个自定义组件的。
    tapestry的内置组件只提供了checkbox,而且只能返回一个boolean,用于表明是否被选中。
    比如,要进行一个群众喜爱的水果调查,选项有: 苹果,葡萄,桃子,香蕉...,就需要对应每个选项设置一个布尔型变量,显得比较繁琐。
    这里我们将添加一个组件用于将一组checkbox集中起来返回一个逗号分隔的字符串值。
    通过查看tapestry中的checkbox的源码(已经附在文章的后面)可以知道,tapestry可以很容易地通过request来获取form中的变量的值。
    遇到的问题:
    tapestry的checkbox组件不允许设置相同的name,如果name相同,tapestry会自动在name后面添加后缀来使之不同。
    if a component renders multiple times, a suffix will be appended to the to id to ensure uniqueness(http://tapestry.apache.org/tapestry5.1/tapestry-core/ref/org/apache/tapestry5/corelib/components/checkbox.html)。如果各checkbox的name不同,我们无法通过request来获得一组checkbox的值。
    思路:
    在页面模板中不使用tapestry的checkbox组件,而使用html的checkbox,这样可以避免tapestry自动修改checkbox的name。
    添加一个新的tapestry组件,来映射接受所有同名的checkbox的值,并把值返回给tapestry页面中对应的变量。这个组件需要有一个属性,这个属性的值就是所有同组checkbox的name,这样,这个组件就可以通过request来获取所有相同name的checkbox的值。
    代码:
     1 public class checkboxgroup extends abstractfield {
     2 
     3     @suppresswarnings("unused")
     4     @parameter(required = true, autoconnect = true)
     5     private string value;
     6 
     7     @parameter(required = true, autoconnect = true)
     8     private string groupname;
     9 
    10     @inject
    11     private request request;
    12 
    13     @suppresswarnings("unused")
    14     @mixin
    15     private renderdisabled renderdisabled;
    16 
    17     @inject
    18     private componentresources resources;
    19 
    20     @beginrender
    21     void begin(markupwriter writer)
    22     {
    23         writer.element("input""type""checkbox",
    24                        "name", groupname,
    25                        "id", getclientid(),
    26                        "style""display:none");
    27 
    28         resources.renderinformalparameters(writer);
    29 
    30         decorateinsidefield();
    31     }
    32 
    33     @afterrender
    34     void after(markupwriter writer)
    35     {
    36         writer.end(); // input
    37     }
    38 
    39     @override
    40     protected void processsubmission(string elementname)
    41     {
    42         string elementvalue = "";
    43         string[] valuearray = request.getparameters(groupname);
    44         if ( valuearray != null && valuearray.length > 0 ) {
    45             elementvalue = valuearray[0];
    46             for ( int i = 1; i < valuearray.length; i  ) {
    47                 elementvalue  = ","  valuearray[i];
    48             }
    49         }
    50         value = elementvalue;
    51     }
    52 }

    组件的使用:
    -----tml------


       
    ${book.name}


    注意checkboxgroup的groupname和其他checkbox的name必须一致,checkboxgroup的value的值就是页面中的变量名

    -----java-----
        @suppresswarnings("unused")
        @property
        private final valueencoder encoder = new valueencoder() {
            public string toclient(book value) {
                return string.valueof(value.getid());
            }
            public book tovalue(string clientvalue) {
                return bookdao.getbook(integer.parseint(clientvalue));
            }
        };
       
        public list getbooklist() {
            return bookdao.getbooks();
        }
       
        @suppresswarnings("unused")
        @property
        private book book;
       
        @suppresswarnings("unused")
        @property
        private string selectedbooks;







    云自无心水自闲 2010-02-12 07:26
    ]]>
    tapestry 最新版5.1.0.5教程(十):页面间传递多个参数http://www.blogjava.net/usherlight/archive/2010/02/06/312181.html云自无心水自闲云自无心水自闲sat, 06 feb 2010 04:36:00 gmthttp://www.blogjava.net/usherlight/archive/2010/02/06/312181.htmlhttp://www.blogjava.net/usherlight/comments/312181.htmlhttp://www.blogjava.net/usherlight/archive/2010/02/06/312181.html#feedback4http://www.blogjava.net/usherlight/comments/commentrss/312181.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/312181.html在tapestry5中,在页面之间传递基本有3种方法
    1、存放在session中
    2、使用@persist进行持久化
    3、使用页面context来传递参数。
    其中1和2都需要将数据存放在session中,相对来说系统的开销比较大。尤其是多用户高并发情况下,对于性能可能会有一定的影响。
    使用页面context来传递则需要在开发时写一些代码,增加了一些开发量,显得没有前两种方法方便。
    第3种方法的实现是需要在页面中添加onactivate和onpassivate方法来完成页面参数的传递。
    我们先来看一下其背后的故事。
    举个例子,比如说我们有两个页面,第一个是查询条件输入页面input,另一个是查询结果输出页面output。input页面中有两个查询条件,起始时间datefrom和终止时间dateto
    在input.java中,我们可以很直观地这样写:
    @injectpage
    private output output;

    @property
    private string datefrom;

    @property
    private string dateto;

    object onformsubmit() {
            output.setdatefrom(datefrom);
            output.setdateto(dateto);
            return output;
    }
    首先使用注解注入output页面,然后在表单的提交事件中,返回output,这样就在程序中定义了返回页面,而不是使用配置文件的方式。
    但是这样的实现却不能正确运行,原因是因为tapestry5的使用了页面池技术,页面在每次渲染前都是从页面池中随机获取一个页面,而从页面池中取得的页面,所有的属性都是被清空了的。
    也就是说在上例中,虽然我们注入了output页面,但是此页面马上就被放入了页面池,而且其中的属性值马上就被清空了。这就是引入onactivate和onpassivate这丙个方法的原因。tapestry5在清空属性前会首先查看是否包含onpassivate方法,如果有,就把其返回值保存起来,然后从页面池中取得页面后,再把刚才保存的值作为参数传递给onactivate方法。
    这就是方法3的基本原理,但是无论是在官方的文档或是示例或者网上其他的应用中,可以发现大部分都是使用单个参数的,比如说id。这也很容易理解,因为onpassivate的方法的返回值只能有一个。
    在tapestry5的官方文档中,只有一句非常简要的话介绍了如果传递多个文档的方法: the activation context may consist of a series of values, in which case the return value of the method should be an array or a list. (参见:http://tapestry.apache.org/tapestry5.1/guide/pagenav.html)。
    但是这并不是说只要在onpassivate中把参数的值加入到list中,返回一个list,而在onactivate中接受一个list参数,然后就可以得到其中的参数了,因为tapestry5把参数传给onactivate的方法其实是通过将参数作为httprequest中的参数的。如果试图使用上述方法就是得到一个“无法将list转换成string的错误”
    所以方法应该是这样的,在output中:

    private list paramlist;
    public void setparamlist(list paramlist) {
            this.paramlist = paramlist;
    }
    public list getparamlist() {
            return paramlist;
    }
    list onpassivate() {
            return paramlist;
    }
    void onactivate(string datefrom, string dateto) {
            this.datefrom = datefrom;
            this.dateto = dateto;
    }
    private string datefrom;
    private string dateto;

    在input页面中,需要把onformsubmit改一下:
    object onformsubmit() {
            list list = new arraylist();
            output.setparamlist(list);
            return output;
    }

    其中,需要注意的是output中的onactivate方法,基参数的顺序必须和list中放入的参数顺序一致。


     



    云自无心水自闲 2010-02-06 12:36
    ]]>
    tapestry最新版5.1.0.5教程(九):权限控制框架的实现-进阶篇http://www.blogjava.net/usherlight/archive/2010/02/04/312016.html云自无心水自闲云自无心水自闲thu, 04 feb 2010 11:17:00 gmthttp://www.blogjava.net/usherlight/archive/2010/02/04/312016.htmlhttp://www.blogjava.net/usherlight/comments/312016.htmlhttp://www.blogjava.net/usherlight/archive/2010/02/04/312016.html#feedback1http://www.blogjava.net/usherlight/comments/commentrss/312016.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/312016.html在上一篇中我们研究了如何实现springsecurity中jsp tag的的功能。这一次我们一起研究一下如何实现在tapestry5.1中添加一个filter来对所有的操作进行权限的过滤控制。
    在springsecurity中,我们一般是在application-context.xml中,添加一个springsecurity的filter,然后在另外一个xml中详细配置如何根据url的规则进行权限的控制。而tapestry的哲学是尽量减少xml中的配置(其ioc容器也基本上是借鉴guice而不spring的),所以我们也是在代码中实现权限规则的控制。
    总体上来看,可以用两种方式来实现url规则,一种是request级别的filter,一种是页面组件级别的filter,如果是request级别的话,可以从request对象中获取url路径,这样就与springsecurity基本一样了。本文主要介绍页面组件级别的filter,从中我们也可以体会到tapestry5.1中的ioc容器的强大和便利。

    这就是filter的代码,这个filter必须实现componentrequestfilter接口。值得注意的是其构造函数所需要用到的4个参数,这4个参数都是tapestry5本身自有的服务,所以我们什么也不用做,tapestry5自动会将服务的实例注入进来,这就是tapestry-ioc的威力。
    componentrequestfilter接口一共有4个方法需要实现,具体代码如下:

     1 public class requiresloginfilter implements componentrequestfilter {
     2 
     3     private final pagerenderlinksource renderlinksource;
     4 
     5     private final componentsource componentsource;
     6 
     7     private final response response;
     8    
     9     private final applicationstatemanager appstatemanager;
    10    
    11     public requiresloginfilter(pagerenderlinksource renderlinksource,
    12             componentsource componentsource, response response,
    13             applicationstatemanager appstatemanager
    14             ) {
    15         this.renderlinksource = renderlinksource;
    16         this.componentsource = componentsource;
    17         this.response = response;
    18         this.appstatemanager = appstatemanager;
    19     }
    20 
    21     public void handlecomponentevent(
    22             componenteventrequestparameters parameters,
    23             componentrequesthandler handler) throws ioexception {
    24 
    25         if (dispatchedtologinpage(parameters.getactivepagename())) {
    26             return;
    27         }
    28 
    29         handler.handlecomponentevent(parameters);
    30 
    31     }
    32 
    33     public void handlepagerender(pagerenderrequestparameters parameters,
    34             componentrequesthandler handler) throws ioexception {
    35         if (dispatchedtologinpage(parameters.getlogicalpagename())) {
    36             return;
    37         }
    38         handler.handlepagerender(parameters);
    39 
    40     }
    41 
    42     private boolean dispatchedtologinpage(string pagename) {
    43         component page = componentsource.getpage(pagename);
    44        
    45         if (page.getclass().isannotationpresent(requireslogin.class)) {
    46             if ( ! appstatemanager.exists(authentication.class)) {
    47                 redirect();
    48                 return true;
    49             }
    50             authentication auth = appstatemanager.get(authentication.class);
    51             if ( auth == null ) {
    52                 redirect();
    53                 return true;
    54             }
    55            
    56              if ( ! auth.isloggedin()) {
    57                  redirect();
    58                  return true;
    59              }
    60 
    61             requireslogin requirelogin = page.getclass().getannotation(
    62                     requireslogin.class);
    63             string ifnotgranted = requirelogin.ifnotgranted();
    64             string ifallgranted = requirelogin.ifallgranted();
    65             string ifanygranted = requirelogin.ifanygranted();
    66             boolean permitted = auth.checkpermission(ifnotgranted, ifallgranted, ifanygranted);
    67             if ( ! permitted ) {
    68                 return true;
    69             }
    70         }
    71 
    72         return false;
    73     }
    74    
    75     private void redirect() {
    76          link link = renderlinksource.createpagerenderlink("logout");
    77        
    78          try {
    79              response.sendredirect(link);
    80          } catch (exception e) {
    81          }
    82     }
    83 
    84 }

    在componentrequestfilter中,我们无法使用@sessionstate注解来直接注入session中的变量,但是我们可以通过applicationstatemanager来取得。

    现在我们需要把刚定义的filter注册到系统中,很简单,只要在appmodule中添加以下函数就行了:

    1 public static void contributecomponentrequesthandler(
    2                 orderedconfiguration<componentrequestfilter> configuration) {
    3         configuration.addinstance("requireslogin", requiresloginfilter.class);
    4 }
    5 
    从本例子中我们可以看到tapesty ioc容器使用的便利性,也认识到了ioc容器在tapestry体系中的重要性

    云自无心水自闲 2010-02-04 19:17
    ]]>
    tapestry5.1中java.lang.classformaterror: invalid length nnn in localvariabletable in class file 错误的解决http://www.blogjava.net/usherlight/archive/2010/01/21/310302.html云自无心水自闲云自无心水自闲wed, 20 jan 2010 23:28:00 gmthttp://www.blogjava.net/usherlight/archive/2010/01/21/310302.htmlhttp://www.blogjava.net/usherlight/comments/310302.htmlhttp://www.blogjava.net/usherlight/archive/2010/01/21/310302.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/310302.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/310302.html exception in thread "main" java.lang.classformaterror: invalid length 561 in localvariabletable in class file

    在网上搜索后,发现有人也有同样的错误,解决方法有两种:
    http://mail-archives.apache.org/mod_mbox/tapestry-users/200909.mbox/
    其中一个人的错误原因是在其类路径中有不同版本的javassists的jar文件。
    另一个的解决方法是使用eclipse自带的jdk来编译java类。
    而我自己仔细检查了类路径中的文件,并没有重复的javassists,不过我觉得问题应该就在javassists上,
    因为这显然是javassists在操作class文件时报的错误,
    我去网上搜索这方面的信息,发现有好几个人都和我一样在使用javassists3.11.0ga版本的时候,会出现这个错误。
    后来,我改用tapestry5中自带的javassists3.9.0ga后,问题消失了。
    这次经验教训是并不是所有最新的东西都是最好的。合适的才是最好的。


    云自无心水自闲 2010-01-21 07:28
    ]]>
    tapestry最新版5.1.0.5教程(八):权限控制框架的实现-基础篇http://www.blogjava.net/usherlight/archive/2010/01/12/309226.html云自无心水自闲云自无心水自闲tue, 12 jan 2010 12:17:00 gmthttp://www.blogjava.net/usherlight/archive/2010/01/12/309226.htmlhttp://www.blogjava.net/usherlight/comments/309226.htmlhttp://www.blogjava.net/usherlight/archive/2010/01/12/309226.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/309226.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/309226.html 本文主要介绍如何实现类似于springsecurity的jsp tag的功能。在tapestry中,利用components实现这一点非常容易。
    其基本原理是tapestry5中一个页面或者组件的渲染生成过程是基于一个状态机和队列完成的。这样,渲染生成过程就被细分成了很多个小模块,我们可以非常容易地覆写这些小模块。具体内容详见官方文档:http://tapestry.apache.org/tapestry5.1/guide/rendering.html。如果权限校验不通过,我们就可以控制不显示组件的内容。
    我们这里就是主要依赖这个过程来实现在页面这一层面对权限进行校验和控制。
    代码主要包含两大部分,一个组件和一个用于权限控制的服务。
    参考了tapestry-spring-security的实现,我也将组件命名为ifrole(当然,我们也可以和tapestry-spring-security一样,也再生成一个ifloggedin组件)。权限控制的服务我命名为:authenticationservice。
    主要的实现思路:
    将authenticationservice申明为sessionstate变量。这样这个变量就可以在所有的页面和组件之间很方便地共享了。一般情况下,是在登录页面对authenticationservice进行赋值,而在退出页面清空authenticationservice这个变量。
    代码(这部分代码完全根据应用的需求进自行更改):
    authenticationservice的代码:
    public class authenticationservice {
        
    private list<string> privilegelist;
        
    // privilegelist 的getter and setter

        
    public boolean checkpermission(string ifnotgranted, string ifallgranted,
                string ifanygranted) 
    {
            
    if (((null == ifallgranted) || "".equals(ifallgranted))
                    
    && ((null == ifanygranted) || "".equals(ifanygranted))
                    
    && ((null == ifnotgranted) || "".equals(ifnotgranted))) {
                
    return false;
            }


            
    if ((null != ifnotgranted) && !"".equals(ifnotgranted)) {
                stringtokenizer st 
    = new stringtokenizer(ifnotgranted, ",");
                
    while (st.hasmoretokens()) {
                    string value 
    = st.nexttoken();
                    
    if (privilegelist.contains(value)) {
                        
    return false;
                    }

                }

            }


            
    if ((null != ifallgranted) && !"".equals(ifallgranted)) {
                stringtokenizer st 
    = new stringtokenizer(ifallgranted, ",");
                
    while (st.hasmoretokens()) {
                    string value 
    = st.nexttoken();
                    
    if (!privilegelist.contains(value)) {
                        
    return false;
                    }

                }

            }


            
    if ((null != ifanygranted) && !"".equals(ifanygranted)) {
                stringtokenizer st 
    = new stringtokenizer(ifanygranted, ",");
                
    while (st.hasmoretokens()) {
                    string value 
    = st.nexttoken();
                    
    if (privilegelist.contains(value)) {
                        
    return true;
                    }

                }

                
    return false;
            }


            
    return true;
        }

    }

    ifrole的代码(这个类需要放在components目录下):
    public class ifrole {
        
    /**
         * a comma-separated list of roles is supplied to one or more of the
         * following parameters. if none are supplied, the default behavior is to
         * forbid access. behavior should be self-explanatory.
         
    */

        @parameter(required 
    = false, defaultprefix = "literal")
        
    private string ifallgranted;

        @parameter(required 
    = false, defaultprefix = "literal")
        
    private string ifanygranted;

        @parameter(required 
    = false, defaultprefix = "literal")
        
    private string ifnotgranted;

        
    /**
         * an alternate {
    @link block} to render if the test parameter is false. the default, null, means
         * render nothing in that situation.
         
    */

        @parameter(name 
    = "else")
        
    private block elseblock;

        
    private boolean test;
       
        @sessionstate
        
    private authenticationservice auth;

        
    private boolean checkpermission() {
            
    return auth.checkpermission(ifnotgranted, ifallgranted, ifanygranted);
        }

       
        
    void setuprender() {
            test 
    = checkpermission();
        }


        
    /**
         * returns null if the test method returns true, which allows normal
         * rendering (of the body). if the test parameter is false, returns the else
         * parameter (this may also be null).
         
    */

        object beginrender() 
    {
            
    return test ? null : elseblock;
        }


        
    /**
         * if the test method returns true, then the body is rendered, otherwise not. the component does
         * not have a template or do any other rendering besides its body.
         
    */

        
    boolean beforerenderbody() {
            
    return test;
        }

       
    }


    示例:
    1. 在登录页面:
    @sessionstate
    private authentication auth;

    ......

    // if user name and password is valid:
    auth.setprivliegelist(.....);


    2. 在需要权限控制的页面模板中:

            administrator can see this block



    云自无心水自闲 2010-01-12 20:17
    ]]>
    tapestry最新版5.1.0.5教程(七):与ibatis3的整合http://www.blogjava.net/usherlight/archive/2010/01/06/308415.html云自无心水自闲云自无心水自闲wed, 06 jan 2010 04:20:00 gmthttp://www.blogjava.net/usherlight/archive/2010/01/06/308415.htmlhttp://www.blogjava.net/usherlight/comments/308415.htmlhttp://www.blogjava.net/usherlight/archive/2010/01/06/308415.html#feedback2http://www.blogjava.net/usherlight/comments/commentrss/308415.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/308415.html 本文主要介绍如何将tapestry5.1和ibatis3进行整合。
    简要步骤:
    1. 准备工作
    2. 数据库的建立
    3. pojo的建立
    4. ibatis相关配置文件的创建
    5. tapestry相关代码的完成
    概要说明:
    1、准备工作。这一部分是比较简单的,eclipse之类的开发环境是必需的。tapestry5.1、ibatis3(目前还是beta7)、数据库(我使用的是mysql)的下载安装。
    2、数据库的建立,由于是示例,所以数据库的建立也非常简单,只有一张user表,3个字段,id,name,password
    3、com.sample.user类,对应数据库表的3个字段,生成user类
    4、ibatis配置文件:configuration.xml,usermapper.xml,jdbc.properties的生成, 前两个必需,最后一个可选.
    5、在appmodule里,使用build方法, 添加服务生成ibatis3的sqlsessionfactory, 在需要使用sqlsessionfactory的地方,使用@injectservice注入即可
    详细说明:
    1、大家到各自的网站上下载相应的包好了。我只罗列一下我所用到的lib:
        antlr-runtime-3.1.1.jar
        commons-codec-1.3.jar
        commons-lang-2.4.jar
        ibatis-3-core-3.0.0.216.jar
        javassist.jar
        log4j-1.2.14.jar
        mysql-connector-java-5.0.5.jar
        slf4j-api-1.5.10.jar
        slf4j-log4j12-1.5.10.jar
        stax2-api-3.0.1.jar
        tapestry-core-5.1.0.5.jar
        tapestry-ioc-5.1.0.5.jar
        tapestry5-annotations-5.1.0.5.jar
        woodstox-core-lgpl-4.0.7.jar
    2、create table
    drop table if exists `test`.`user`;
    create table  `test`.`user` (
      `id` int(10) unsigned not null auto_increment,
      `name` varchar(45) not null,
      `password` varchar(45) not null,
      primary key (`id`)
    ) engine=innodb;

    3、
    package com.sample.model;
    public class user {
        private long id;
        private string name;
        private string password;
        // getter and setter    ....
    }

    4、我把configuration.xml和usermapper.xml都放在src目录下,这样在部署的时候,就是生成在classes,也就是类路径的根目录下。
    configuration.xml:

      public "-//ibatis.apache.org//dtd config 3.0//en"
      "http://ibatis.apache.org/dtd/ibatis-3-config.dtd"> 

       
       

       
           
               
               
                   
                   
                   
                   
                               
                               
                               
               

           

       

       
           
       




    usermapper.xml:
     
        public "-//ibatis.apache.org//dtd mapper 3.0//en" 
        "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
       

       




    jdbc.properties:
    jdbc.driver=com.mysql.jdbc.driver
    jdbc.url=jdbc:mysql://localhost/test?autoreconnect=true
    jdbc.username=root
    jdbc.password=root
    pingenable=true
    pingquery=select 1
    pingoldertime=0
    pingnotusetime=3600000

    5、
    package com.sample.web.services;
    public class appmodule {
        public static sqlsessionfactory buildsqlsessionfactory() {
            try {
                string resource = "configuration.xml";
                reader reader = resources.getresourceasreader(resource);
                return new sqlsessionfactorybuilder().build(reader);
            } catch (exception e) {
                logger.warn("failed to build sqlsessionfactory: ", e);
                return null;
            }
        }

        private static logger logger = loggerfactory.getlogger(appmodule.class);
    }


    package com.sample.model;
    public interface usermapper {
        public user selectuser(int id);
    }


    package com.pc.sample.web.pages;
    public class layout {
        @injectservice("sqlsessionfactory")
        private sqlsessionfactory sqlmapper;
        public string getusername() {
            if ( sqlmapper == null ) {
                return "null-mapper";
            }
            sqlsession session = sqlmapper.opensession();
            try {
                usermapper usermapper = session.getmapper(usermapper.class);
                if ( usermapper == null ) {
                    return "null-usermapper";
                }
                user user = usermapper.selectuser(1);
                if ( user == null ) {
                    return "null-user";
                }
                return user.getname();
            } catch (exception e) {
                return "exception-" e.getmessage();
            } finally {
                session.close();
            }
        }
    }

    几个注意事项:
    1, 因为我的ibatis的配置文件configuration.xml是放在类路径的根目录下,所以在初始化sqlsessionfactory的时候,直 接用string resource = "configuration.xml";就行了,否则需要添加相应的路径,比如:把configuration.xml与user类放在一起,也就是在 com.sample.model这个package中,那么就要写成:string resource = "com/sample/model/configuration.xml";
    同样,在configuration.xml中,指定usermapper.xml的规则也是这样的。
    2,usermapper的使用。mapper的使用是ibatis3中才有的新功能,也是ibatis用户指南中推荐使用的方式。因为这样使用的话,就完全避免了类型的强制转换,实现了类型安全。
    需要注意的是usermapper只是一个接口。我们不需要提供这个接口的具体实现。ibatis3会自动生成一个具体的实例。

    其中的方法名必须与usermapper.xml中的select语句的id一样。在我的例子中是selectuser.
    另外,此方法的返回值的类型必须与usermapper.xml中配置的returntype一致。
    最后要提醒的是usermapper.xml中的namespace必须是usermapper的全类名,在本例中就是com.sample.model.usermapper


    云自无心水自闲 2010-01-06 12:20
    ]]>
    tapestry最新版5.1.0.5教程(六):核心利器-ioc容器介绍http://www.blogjava.net/usherlight/archive/2009/09/12/294895.html云自无心水自闲云自无心水自闲sat, 12 sep 2009 14:07:00 gmthttp://www.blogjava.net/usherlight/archive/2009/09/12/294895.htmlhttp://www.blogjava.net/usherlight/comments/294895.htmlhttp://www.blogjava.net/usherlight/archive/2009/09/12/294895.html#feedback1http://www.blogjava.net/usherlight/comments/commentrss/294895.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/294895.html其核心思想就是使用java代码自身来解决依赖注入而不是由xml之类的配置文件来完成,这和guice的思想是非常相似的,lewis也承认从guice那里借鉴了不少。
    另外需要说明一下的是,tapesty还从中国的一个非常古老但又充满哲理的游戏--围棋中借鉴了一些术语和思想。大意是围棋中经常要把棋子走的轻盈(lightness),让每个棋子都能尽量地高效。编程也一样要轻量(lightness)。  

    云自无心水自闲 2009-09-12 22:07
    ]]>
    tapestry最新版5.1.0.5教程(五):hello示例程序的剖析http://www.blogjava.net/usherlight/archive/2009/07/10/286315.html云自无心水自闲云自无心水自闲fri, 10 jul 2009 12:15:00 gmthttp://www.blogjava.net/usherlight/archive/2009/07/10/286315.htmlhttp://www.blogjava.net/usherlight/comments/286315.htmlhttp://www.blogjava.net/usherlight/archive/2009/07/10/286315.html#feedback5http://www.blogjava.net/usherlight/comments/commentrss/286315.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/286315.html
    根据前面的4部分内容,我们已经了解了tapestry的基本概念,掌握了配置、组件等内容。现在我们通过剖析tapestry的入门示例来对tapestry进行一个总体上认识。
    1、web.xml

        app tapestry 5 application
       
           
            tapestry.app-package
            t5demo
       

       
            app
            org.apache.tapestry.tapestryfilter
       

       
            app
            /*
       

    这就是一个最简单的tapestry应用所需要配置的内容了。
    a.context-param中的tapestry.app-package配置,这在第一部分说过:这是tapestry要求配置的java package的名称,tapestry相关内容都需要在这个package下面的pages, services, componets子package下。这里的配置是t5demo
    b.tapestryfileter的配置。这个非常容易理解,几乎所有现在流行的web框架都需要一个类似的定义。

    2、start.tml以及相应的java class,例子中就是t5demo.pages.start.java
    start.java非常简单,只定义了一个get方法:
    public class start
    {
            public date getcurrenttime()
            {
                    return new date();
            }
    }
    相应的页面start.tml

       
            app start page
       
       
           

    blogjava-凯发k8网页登录

           

    this is the start page for this application, a good place to start your modifications.
                just to prove this is live:

           

    the current time is: ${currenttime}.


           


                [refresh]
           


       

    首先要注意在html的tag中加入了tapestry的命名空间。
    第二、${currenttime}就是tapestry的tag了,这里就会调用对应class的getcurrenttime方法在页面上显示对应的值。
    第三、定义一个到自己本身页面的链接,来完成刷新的任务。t:pagelink在本系列的第4部分介绍过。

    3、需要的library:
    commons-codec.jar
    javassist.jar
    log4j.jar
    slf4j-api.jar
    slf4j-log4j.jar
    tapestry5-annotations-5.1.0.5.jar
    tapestry-core-5.1.0.5.jar
    tapestry-ioc-5.1.0.5.jar

    4、再加上一个log4j.properties,这就是一个最简单的tapestry应用所需要的全部东西了。
    怎么样,感觉还是挺简单的吧。



    云自无心水自闲 2009-07-10 20:15
    ]]>
    tapestry最新版5.1.0.5教程(四)http://www.blogjava.net/usherlight/archive/2009/06/20/283396.html云自无心水自闲云自无心水自闲sat, 20 jun 2009 11:57:00 gmthttp://www.blogjava.net/usherlight/archive/2009/06/20/283396.htmlhttp://www.blogjava.net/usherlight/comments/283396.htmlhttp://www.blogjava.net/usherlight/archive/2009/06/20/283396.html#feedback3http://www.blogjava.net/usherlight/comments/commentrss/283396.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/283396.html阅读全文

    云自无心水自闲 2009-06-20 19:57
    ]]>
    tapestry最新版5.1.0.5教程(三)http://www.blogjava.net/usherlight/archive/2009/06/05/280207.html云自无心水自闲云自无心水自闲fri, 05 jun 2009 06:24:00 gmthttp://www.blogjava.net/usherlight/archive/2009/06/05/280207.htmlhttp://www.blogjava.net/usherlight/comments/280207.htmlhttp://www.blogjava.net/usherlight/archive/2009/06/05/280207.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/280207.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/280207.html阅读全文

    云自无心水自闲 2009-06-05 14:24
    ]]>
    tapestry最新版5.1.0.5教程(二)续http://www.blogjava.net/usherlight/archive/2009/06/03/279852.html云自无心水自闲云自无心水自闲wed, 03 jun 2009 09:17:00 gmthttp://www.blogjava.net/usherlight/archive/2009/06/03/279852.htmlhttp://www.blogjava.net/usherlight/comments/279852.htmlhttp://www.blogjava.net/usherlight/archive/2009/06/03/279852.html#feedback2http://www.blogjava.net/usherlight/comments/commentrss/279852.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/279852.html阅读全文

    云自无心水自闲 2009-06-03 17:17
    ]]>
    tapestry最新版5.1.0.5教程(二)http://www.blogjava.net/usherlight/archive/2009/05/31/279277.html云自无心水自闲云自无心水自闲sun, 31 may 2009 12:31:00 gmthttp://www.blogjava.net/usherlight/archive/2009/05/31/279277.htmlhttp://www.blogjava.net/usherlight/comments/279277.htmlhttp://www.blogjava.net/usherlight/archive/2009/05/31/279277.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/279277.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/279277.html阅读全文

    云自无心水自闲 2009-05-31 20:31
    ]]>
    tapestry最新版5.1.0.5教程(一)http://www.blogjava.net/usherlight/archive/2009/05/30/279014.html云自无心水自闲云自无心水自闲sat, 30 may 2009 05:55:00 gmthttp://www.blogjava.net/usherlight/archive/2009/05/30/279014.htmlhttp://www.blogjava.net/usherlight/comments/279014.htmlhttp://www.blogjava.net/usherlight/archive/2009/05/30/279014.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/279014.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/279014.html阅读全文

    云自无心水自闲 2009-05-30 13:55
    ]]>
    tapestry5.1.0.5的性能测试http://www.blogjava.net/usherlight/archive/2009/05/16/271028.html云自无心水自闲云自无心水自闲sat, 16 may 2009 11:38:00 gmthttp://www.blogjava.net/usherlight/archive/2009/05/16/271028.htmlhttp://www.blogjava.net/usherlight/comments/271028.htmlhttp://www.blogjava.net/usherlight/archive/2009/05/16/271028.html#feedback1http://www.blogjava.net/usherlight/comments/commentrss/271028.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/271028.htmlben gidley进行了一个关于tapestry5.1.0.5的性能测试。原文见:http://blog.gidley.co.uk/2009/05/tapestry-load-testing-round-up.html
    最后,他得出的结论是:
    1、tapestry的速度是比较快的。即使在一定的压力下tapestry的反应时间也相当短。tapestry并不总是最快的凯发天生赢家一触即发官网的解决方案,但它对于我(译注:gidley)已经足够快了。
    2、tapestry没有内存泄漏。我以前曾经听说过tapestry会占用大量的内存,实际上,正好相反。它使用的内存比struts/jsp还要少。内存使用曲线相当的平坦。
    3、tapestry在表单应用中比struts要快。tapestry在应用变得非常复杂的时候有一定的优势。这可能利益于其模块池技术。
    4、tapestry不轻易崩溃,即使崩溃,也会恢复。tapestry在极大压力的情况下确实会相应变慢,但是它会暂停或者遇到瓶颈(译注:我怀疑是作者这里有笔误,从语气和上下文来看,感觉应该不是暂停和没有瓶颈),这的确是一个好事情。另外在压力减轻之后,tapestry能够自动恢复。
    5、更多的cpu并一定会提升性能。在一系列的测试中,性能与cpu的数量并不是线性增长。2个cpu确实比一个cpu的性能翻倍了,但是4个cpu并不比2个cpu的性能翻倍。因此,建议在多个双核cpu的虚拟机上运行,而不是少数的4核cpu上运行。
    6、64位比32位要快。这一点很让我惊奇。不管在solaris还是linux上,运行在64位jvm中要比在32位jvm要快。
    7、linux要比open solaris x86要快。这一点同样让我惊奇。我本来以为性能应该是相似的。
    最终的结论是:tapestry即使是对于一个大并发量的web应用来说也已经足够快了。如果你的应用有性能问题的话,那么问题应该出在你自己本身的代码上。

    上述是原文的翻译。下面是一些评论:
    howard(应该是tapestry的作者):taptestry5和struts相比,我认为差别应该是在反射的使用上(包括在java.bean.introspector中大量的synchronization)。因此在struts将查询参数的名称映射成javabean属性的时候,会比较耗时。而tapestry5是不使用反射的,tapestry在查询参数和javabean的属性之间使用一种“预编程”向量组件,也许这就是两者(tapestry和struts)的差别。当然,这只是猜想,如果要证实的话,是需要花费很多时间的。我认为ognl的教训不是说反射很慢,而是在于一个关键代码上的序列存取对于性能的影响是相当大的。
    最后一个小提示:我觉得在tapestry5应用中如果把beanmodel从beanmodelsource中只提取一次,然后给grid,beaneditform等等提供一个可以存取的方法,将会获得相当的性能提升。这样就不是需要每次都重建beanmodel,将减少操作的消耗。
    jeverest:我也进行了tapestry的性能测试,并且同意tapestry5的性能比较以前版本的要快。



    云自无心水自闲 2009-05-16 19:38
    ]]>
    tapestry5.1正式发布http://www.blogjava.net/usherlight/archive/2009/05/07/269484.html云自无心水自闲云自无心水自闲thu, 07 may 2009 13:08:00 gmthttp://www.blogjava.net/usherlight/archive/2009/05/07/269484.htmlhttp://www.blogjava.net/usherlight/comments/269484.htmlhttp://www.blogjava.net/usherlight/archive/2009/05/07/269484.html#feedback0http://www.blogjava.net/usherlight/comments/commentrss/269484.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/269484.htmltapestry5.1经过数个alpha,beta版的非正式发布,今天终于在凯发k8网页登录主页看到最终正式版5.1.0.5的发布。

    这次的版本算得上是比较迅速了,从官方凯发k8网页登录主页中可以看到,第一版5.1.0.1是2月24日发布了,短短3个月不到的时间,发了4个版本,动作不可谓不迅速。

    5.1中具有以下几个新特性
    1、tapestry现在开始采用blackbird作为javascript的调试工具
    2、一个ajax的事件请求现在可以返回一个multizoneupdate实例来更新浏览器中的多个区
    3、客户端数字的检验实现了国际化
    4、相对于5.0.18有显著的性能提升,主要是页面的加载时间和页面的渲染时间大大缩短
    5、tapestry的ioc服务现在既可以是advised也可以是decorated
    6、tapestry的服务现在可以注入到spring的bean中
    7、对于支持gzip的客户端,tapestry现在可以压缩返回包
    8、有序的和mapped的配置信息现在可以被重新赋值
    9、属性表达式得到加强,现在可以调用有参数的方法,或者创建一个列表
    10、ioc的贡献既可以是类(自动生成实例)也可以是具体的实例
    11、现在提供了一个简单的可以重写内建服务的方法

    这里面最让我感兴趣的还是性能的提升,不知道在展示大数据量的时候性能的提升到底有多少,有机会一定要测试一下。



    云自无心水自闲 2009-05-07 21:08
    ]]>
    tapestry和jsf比较http://www.blogjava.net/usherlight/archive/2009/04/21/266866.html云自无心水自闲云自无心水自闲tue, 21 apr 2009 15:09:00 gmthttp://www.blogjava.net/usherlight/archive/2009/04/21/266866.htmlhttp://www.blogjava.net/usherlight/comments/266866.htmlhttp://www.blogjava.net/usherlight/archive/2009/04/21/266866.html#feedback3http://www.blogjava.net/usherlight/comments/commentrss/266866.htmlhttp://www.blogjava.net/usherlight/services/trackbacks/266866.html 最主要的原因还是从性能上的考虑。
    tapestry的5.1版的最主要改动就是想提升性能,而jsf似乎还没有这方面的行动。
    而且从tapestry5.1的版本发布情况来看,动作相当的迅速。预计final版马上就要出来了。
    据lewis的说法,tapestry5.0在页面内容比较少的时候,速度几乎和纯jsp页面一样快。只是在展示大量数据的会有一定的性能瓶颈。
    所以,他推出5.1来解决这个问题。

    而jsf的实现和组件库呈现一种百花齐放的状态,难免会有一些良莠不齐。
    当然大家需要选择其中比较好的,但是选型本身就是一件非常头疼的事情。
    我选择的是myfaces+richfaces,但是我查看了richfaces的在线demo后,对其展示速度不是很满意。
    不知道是演示网站的问题还是richfaces本身的问题。
    也欢迎大家进行讨论。

    不过tapestry相对jsf而言的一个缺点就是文档不够丰富。毕竟jsf是标准啊。

    云自无心水自闲 2009-04-21 23:09
    ]]>
    网站地图