﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Open-Open-随笔分类-Tapestry</title><link>http://www.blogjava.net/realzar/category/7332.html</link><description>皇家撒拉哥萨</description><language>zh-cn</language><lastBuildDate>Thu, 01 Mar 2007 18:25:50 GMT</lastBuildDate><pubDate>Thu, 01 Mar 2007 18:25:50 GMT</pubDate><ttl>60</ttl><item><title>[转贴]Tapestry 心得</title><link>http://www.blogjava.net/realzar/archive/2006/03/26/37418.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Sat, 25 Mar 2006 16:29:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/03/26/37418.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/37418.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/03/26/37418.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/37418.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/37418.html</trackback:ping><description><![CDATA[对于整个tapestry的设计和实现其实最核心的部分就是对于页面和配置页以及逻辑类的配合。在学习和使用tapestry的时候，我们可以完全不用理会jsp的概念，因为他们从设计思想上就完全不同。<br />  传统的jsp设计，或者说servlet设计是一种根据jsp和servlet不同的优点设计的mvc模式。对于jsp，显示更加便捷，更加灵活，所以更多地用于页面显示，而servlet则更多的突现了它对于后台的强大控制力，所以更多地被用于控制器，也就是controller。mvc的设计模式是，无论什么样的请求，都需要通过对于url的模糊匹配被定位到第一级或者顶级控制器，再通过控制器对于所传递的请求进行解析分析后，重定向到正确的处理类中，也就是说，我们对于整个应用需要些大于总页面个数的java类来完成所规定功能。这在一定程度上浪费了资源和开发时间。当然，在软件工程学中，本就提出了几种不同的解决方法，mvc模式可以使我们应用更加清晰化，更加可维护化。<br />  当然，抽象地说，tapestry在设计中完全没有了控制器的概念。当然这也是个人的观点。开发过程中，我只是设计，在用户使用我所写的页面的时候会出现多少种状况，然后设计相应的页面。这样就更加类似我们在c中的开发，瀑布式开发模式。还是做个例子比较好，对不对？<br />暂时不给大家.htm和.page文件了，不然大家会越来越晕的，只给大家讲解一下.java文件<br />public abstract void SubjectList extends GbsBasePage<br />{<br />     public abstract Subject getSubject();<br />     public abstract void setSubject();<br /><br />     public abstract Subject getParentSubject();<br />     public abstract void setSubject();<br /><br />     public IsubjectService getIsubjectService()<br />     {return (IsubjectService)getService("subjectService");}<br /><br />     public List getSubjectList()<br />     {<br />           List list=new ArrayList(getSubject().getSubjects());<br />           return list;<br />     }<br />     <br />      public void addSubject(IRequestCycle cycle)<br />      {<br />           AddSubject addSubject=(AddSubject)cycle.getPage("add_subject");<br />           <br />           addSubject.setParentSubject(getSubject().getParentSubject());<br />           forward(cycle,"add_subject");<br />      }<br /><br />      public void defineSubSubject(IRequestCycle cycle)<br />      {<br />          SubjectList subjectList=(SubjectList)cycle.getPage("subject_list");<br />          subjectList.setParentSubject(getSubject);<br />          forward(cycle,"subject_list");<br />      }<br />}<br />     朋友们可能会看得很迷糊，对吧？其实这就是tapestry的优点了。如果你希望把一些东西绑定在页面上的话，那么我根本就不需要在java类中处理他们，只需要将实体类在.page中声明一下，例如，<br />&lt;property-specification name="subject" type="com.tapestry.Subject"/&gt;<br />     然后在java类中抽象的声明他们，tapestry就会自动将你所需要绑定的属性绑定在实体上，处理的时候只需要调用就可以了。<br />   那么，这个IService又是怎么回事儿呢？其实我们在页面之间进行数据或者实体传递的时候，为了提高速度，或者提高效率，或者提高安全性，我们都可以通过传递id的方式进行，那么通过spring的service方法，我们就可以快速的找到这个实体，例如：<br />Subject subject=getSubjectService().Load(getSubject().getID());<br />     同时，我们这个页面所需要的控件也需要我们传递相应的参数来显示我们所需要的效果，这就是为什么要有getSubjectList()这个方法了。在我们使用foreach控件或者actionTable控件的时候，都需要我们传递一个list用来显示，那么这个list就来自这个方法。<br />    我们可以添加subject这个实体，那么tapestry就会自动调用addSubject()这个方法来使得页面进入添加页面。上一次曾经说过，tapestry中所有的页面都是一个java类，所以，相应的负值也就变得理所当然了。addSubject.setParentSubject(getSubject().getParentSubject());<br />     最后，我们要把所有的请求和相应一起发给正确的页面forward(cycle,"add_subject");<br />同时，我们还可以在自己和自己中不停的跳转。这时我们就可以无限的定义我们的树型结构了，因为我们只需要给自己传递不同的参数就可以了。<br /><img src ="http://www.blogjava.net/realzar/aggbug/37418.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-03-26 00:29 <a href="http://www.blogjava.net/realzar/archive/2006/03/26/37418.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>表现层框架Struts/Tapestry/JSF比较</title><link>http://www.blogjava.net/realzar/archive/2006/02/28/32798.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Tue, 28 Feb 2006 01:42:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/02/28/32798.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/32798.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/02/28/32798.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/32798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/32798.html</trackback:ping><description><![CDATA[Struts/Tapestry/JSF是目前J2EE表现层新老组合的框架技术。从诞生时间上看，Struts应该比较早，使用得非常广泛，Tapestry 3.0逐渐引起广泛的重视，正当Tapestry即将大显身手时期，SUN推出JSF标准技术，虽然JSF一开始推出尚不成熟，留出了一段空白期，但是随着JSF1.1标准推出，JSF开始正面出击，粉面隆重登场了。 
<P align=left>　　其实，JSF和Tapestry也并不是那种头碰头的相同竞争性技术，两者还是各有侧重点的，不过比较细微，但是这种细微点在实现一个大工程时可能带来不同的感受和变化。</P>
<P align=left>　　首先，我们从一个高度来抽象一下表现层框架应有的技术架构，下图可以说所有表现层框架技术都必须实现的功能架构图：</P>
<P align=center><IMG height=236 alt=ti7m48370n10.jpg src="http://www.blogjava.net/images/blogjava_net/realzar/ti7m48370n10.jpg" width=219 border=0></P>
<P align=left>　　当然，我们不必废话罗嗦MVC模式，MVC模式是基准模式，现在框架技术已经不必再拼是否是MVC模式了。 在上图MVC模式基础上，一个表现层框架无外乎要实现图中的三个功能：</P>
<P align=left>　　1.在当前页面能够显示一个组件对象的内容；而不是象纯JSP那样，需要在Jsp页面写入“调用对象方法”的Java代码。</P>
<P align=left>　　2.当用户按下页面的提交按扭或链接后，事件发生，这时应该触发服务器端并将当前页面的参数提交给服务器。这种机制表现在Form表单提交和有参数的链接&lt;a href=""&gt;&lt;/a&gt;</P>
<P align=left>　　3.从一个页面视图直接跳转到另外一个页面视图，单纯的导航作用。</P>
<P align=left>　　我们通过下表来比较这 三种框架在实现上图各个功能时技术细节，从而得出他们的异同点和偏重点。</P>
<TABLE cellSpacing=1 cellPadding=1 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#cccccc>
<TABLE width="100%" border=0>
<TBODY>
<TR>
<TD width="16%">&nbsp;</TD>
<TD width="29%">Struts</TD>
<TD width="33%">Tapestry3.0</TD>
<TD width="22%">JSF</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>在View显示的组件要求</TD>
<TD>
<P>组件必须继承ActionForm</P></TD>
<TD>分显式调用和隐式调用<BR>组件必须继承BaseComponent</TD>
<TD>普通POJO<BR>无需继承<BR>Managed Bean</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>组件在View显示粒度</TD>
<TD>View页面只能显示与表单对应的ActionForm，配置中Action ActionForm 页面一般只能1:1:1关系。</TD>
<TD>可将组件嵌入页面任何一行，对使用组件数量无限制。</TD>
<TD>同Tapestry</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>页面分区tiles</TD>
<TD>使用Tiles标签库实现，需要另外tiles-def.xml配置文件</TD>
<TD>组件有自己的视图页面，通过调用组件即直接实现多个页面组合。强大自然的页面组合是其特点。</TD>
<TD>通过组件+标签库实现Subview,但如需重用Layout,还要结合Tiles.</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>页面跳转</TD>
<TD>使用标签库html:link中写明目标URL，URL名称需要对照配置文件的path命名,与组件Action耦合。</TD>
<TD>URL名称是目标的组件名称，不涉及URL和路径等操作，方便稳固。</TD>
<TD>类似Struts，也需要在配置文件中查找,与组件分离。</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>参数传递</TD>
<TD>使用html:link时传递参数超过一个以上处理麻烦。</TD>
<TD>直接调用组件，直接赋予参数，没有参数个数限制</TD>
<TD>参数分离传递给组件</TD></TR>
<TR bgColor=#ffffff>
<TD bgColor=#999999>事件触发</TD>
<TD>通过表单提交submit激活，不能细化到表单里字段。</TD>
<TD>能够给于表单每个字段贴一个事件，事件组件必须实现PageListener接口</TD>
<TD><SPAN id=intelliTxt><CODE>同Tapestry，事件组件必须实习ActionListener 接口</CODE></SPAN></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P><STRONG>　　Struts组件编程模型</STRONG></P>
<P>　　Struts实现组件编程时有一些复杂：经常为一个页面中需要引入多个组件而头疼，因为Struts中无法直接引入多个组件，必须绕一些圈子:</P>
<P>　　一般分两种情况：如果同一个Action就可以对付这些组件，那么在这种情况下有两个办法：</P>
<P>　　1.将这多个组件装入一个ActionForm中，如使用<SPAN class=unnamed3>MapForm</SPAN>等机制；</P>
<P>　　2.手工将多个组件装入request/session等scope中，然后根据其名称在jsp中获得。</P>
<P>　　这两个方法都有缺点： 第一种办法经常一个ActionForm弄得面目全非，变成一个大杂烩，违反了OO分派封装的原则；第2种办法其实又回到jsp编程；</P>
<P>　　第二种情况，如果这些组件必须有预先由不同的Action来处理，每个组件必须经过Action --&gt;ActionForm流程，在这种情况下有两种办法：</P>
<P>　　1.使用Tiles, 不同流程输出到同一个页面的不同区域。是一种并行处理方式。</P>
<P>　　2. 对多个流程首尾相连，第一Action forward结果是第二个Action，最后输出一个Jsp，在这个jsp中就可以使用前面多个流程的多个ActionForm了，这属于串行方式。</P>
<P><STRONG>　　Struts组件模型缺点</STRONG></P>
<P>　　Struts组件编程必须限定在Action/ActionForm/JSP这三个框框中做文章，难度相对比较大，而Tapestry/JSF则没有太多这些技术框框限制，两者在组件编程方面更让编程者自由一些，方便一些，这也是组件型框架的优势吧。</P>
<P><STRONG>　　Struts标签库</STRONG></P>
<P>　　在Struts中，经常需要使用标签库来显示组件ActionForm中内容，这就涉及到一个结合的问题，标签库是别人写的，参考Struts的标签库用法，而组件是自己的，难度和麻烦就体现在这个结合点上。</P>
<P>　　JSF基本思路和Struts差不多，只不过换了不同标签库，也需要标签库+组件的结合思考，不过因为组件这里是通用组件，没有什么限制，所以这样比Struts要轻松一些。</P>
<P>　　Tapestry使用了组件库概念替代了标签库，没有标签库概念，这样就没有标签库和自己的组件需要结合的问题，都是组件的使用，组件中分Tapestry标准组件和自己定义的组件，这也是接触了Jsp体系的人学习Tapestry面临的一个思路转换。</P>
<P>　　具体以页面跳转为例子，页面跳转是靠链接&lt;a href="目标"&gt;&lt;/a&gt; 实现，链接是页面经常使用的元素。</P>
<P>　　Struts提供的html:link在频繁使用就特别不方便，尤其在传递多个参数时：其中html:link的page值，是跳转对方页面或Action的path，这个path一般需要到struts-config.xml查找Action的相应path,一旦配置文件path值修改，涉及到这个所有相关页面都要修改。</P>
<P>　　JSF将链接概念划分两个方面：导航性质和事件激活，在导航方面还是需要到配置faces-config查询Navigation的from-outcome的值。</P>
<P>　　由于Tapestry没有标签库概念，只有组件或页面两个概念，因此，链接跳转目标要么是组件，要么是页面，简洁简单，它没有多余的path概念，就是组件名，也就是对象名称，组件名称和path名称合二为一。</P>
<P><STRONG>　　总结</STRONG></P>
<P>　　JSF在很大程度上类似Struts，而不是类似Tapestry，可以说是一种Struts 2.0，都是采取标签库+组件的形式，只是JSF的组件概念没有象Struts那样必须继承ActionForm的限制；JSF在事件粒度上要细腻，不象Struts那样，一个表单一个事件，JSF可以细化到表单中的每个字段上。</P>
<P>　　JSF只有在组件和事件机制这个概念上类似Tapestry，但是不似Tapestry那样是一个完全组件的框架，所以，如果你做一个对页面要求灵活度相当高的系统，选用Tapestry是第一考虑。</P>
<P>　　Struts/JSF则适合在一般的数据页面录入的系统中，对于Struts和JSF的选用，我目前个人观点是：如果你是一个新的系统，可以直接从JSF开始；如果你已经使用Struts，不必转换，如果需要切换，可以将JSF和Tapestry一起考虑。</P>
<P>　　另外，JSF/Tapestry不只是支持Html，也支持多种客户端语言如WML或XUI等。</P>
<P>　　这三者之间关系：如果说Struts是左派；那Tapestry则是右派；而JSF则是中间派，中庸主义是SUN联盟的一贯策略。</P>
<P>　　当然，你也可以发表你在实践中这三者任何一个的使用感受，以使得后来者有一个比较</P><img src ="http://www.blogjava.net/realzar/aggbug/32798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-02-28 09:42 <a href="http://www.blogjava.net/realzar/archive/2006/02/28/32798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tapestry 4.0 新特性(9月8日修订) </title><link>http://www.blogjava.net/realzar/archive/2006/02/10/30075.html</link><dc:creator>开源爱好者</dc:creator><author>开源爱好者</author><pubDate>Thu, 09 Feb 2006 17:11:00 GMT</pubDate><guid>http://www.blogjava.net/realzar/archive/2006/02/10/30075.html</guid><wfw:comment>http://www.blogjava.net/realzar/comments/30075.html</wfw:comment><comments>http://www.blogjava.net/realzar/archive/2006/02/10/30075.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/realzar/comments/commentRss/30075.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/realzar/services/trackbacks/30075.html</trackback:ping><description><![CDATA[<SPAN class=postbody>参考：<A class=postlink href="http://jakarta.apache.org/tapestry/current/UsersGuide" target=_blank>http://jakarta.apache.org/tapestry/current/UsersGuide</A> <BR>基本上是理解性翻译，英文好的可以直接去看此guide，我只是做了笔记，然后放到这里希望能对大家有所帮助。 <BR>新特性我也只是了解，没有具体应用(很想用<IMG alt="Very Happy" src="http://forum.hibernate.org.cn/images/smiles/icon_biggrin.gif" border=0>)，有理解错误的地方，希望大家原谅。 <BR><BR><SPAN style="FONT-WEIGHT: bold">Tapestry4新特性(一)－default binding types</SPAN> <BR><BR>default binding types(默认的绑定类型) <BR>每一个组件的参数都可以定义默认的绑定类型，如果一个绑定的参数没有前缀，将使用默认的绑定类型。 <BR>下面的代码实现同样的功能: <BR><BR><BR>&lt;ul element="ul" jwcid="@Foreach" source="ognl:items" value="ognl:item"&gt; &lt;li&gt;&lt;span jwcid="@Insert" value="<SPAN style="FONT-WEIGHT: bold">ognl:item.name</SPAN>"/&gt; &lt;/ul&gt; <BR><BR>&lt;ul element="ul" jwcid="@Foreach" source="items" value="item"&gt; &lt;li&gt;&lt;span jwcid="@Insert" value="<SPAN style="FONT-WEIGHT: bold">item.name</SPAN>"/&gt; &lt;/ul&gt; <BR><BR>加粗的部分显示前后的变化，之所以可以这样定义，是因为Insert组件定义value参数的默认绑定类型为ongl. <BR>注意：默认的绑定参数总是可以被显式的绑定声明覆盖掉。 <BR>如果没有定义默认的绑定参数，那么在html模板中定义的默认绑定参数为literal，页面定义文件里的默认绑定参数为ognl <BR>修订： <BR><BR>从beta4版本开始，此特性已经被删除， <BR><BR>Beta4的change log： <BR><BR>Remove default-binding attribute from element(HLS) <BR><BR>但是“如果没有定义默认的绑定参数，那么在html模板中定义的默认绑定参数为literal，页面定义文件里的默认绑定参数为ognl”这个效果经测试依然存在。 <BR><BR>怀念： <BR><BR>此段文字在beta3中存在，beta4后就删掉了！ <BR><BR>Binding Type Defaults <BR>Tapestry 4.0 introduces a new idea: default binding types. Each component parameter may define a default binding type (using the default-binding attribute of the &lt;parameter&gt; element). <BR><BR>If a binding reference does not have a prefix, the default binding type is used. <BR><BR>Because of this, the following two snippets are identical: <BR><BR>&lt;ul element="ul" jwcid="@Foreach" source="ognl:items" value="ognl:item"&gt; <BR>&lt;li&gt;&lt;span jwcid="@Insert" value="ognl:item.name"/&gt; <BR>&lt;/ul&gt; <BR>&lt;ul element="ul" jwcid="@Foreach" source="items" value="item"&gt; <BR>&lt;li&gt;&lt;span jwcid="@Insert" value="item.name"/&gt; <BR>&lt;/ul&gt; <BR>This works because the Insert component defines the default-binding for the value parameter to be "ognl". Likewise, the source and value parameters of the Foreach component are defined to be "ognl". However, the element parameter of the Foreach component has a binding type of "literal". <BR><BR>This is a decision made by the component author. If a particular parameter is (nearly) always bound using a particular binding type, then a default-binding may be set. The default binding can always be overriden with an explicit binding type prefix. <BR><BR>What about parameters that don't define a default binding type? The answer to this question (which includes all informal parameters), is that it depends on whether the parameter is bound in an HTML template, or in a page or component specification. In an HTML template, the default binding type is "literal". In a specification, the default binding type is "ognl". <BR><BR><SPAN style="FONT-WEIGHT: bold">Tapestry4新特性(二)－listener method</SPAN> <BR><BR>如果使用过tapestry的应该知道listener方法在4.0以前版本中的定义，如public void formSubmit(IRequestCycle cycle)，方法必须有一个IRequestCycle参数。参数的取得方式如下：Object[] parameters = cycle.getServiceParameters(); <BR>在4.0中参数的取得可以通过以下两种方式： <BR><BR>1、调用IRequestCycle.getListenerParameters()方法,需要传入IRequestCycle实例作为参数。 <BR>2、按照参数的声明顺序依次定义为listener方法的参数。 <BR>第二种方法比较符合软件的设计思维，而且参数的类型在传入后保存，而不是想象中的统一String类型。 <BR>例如： <BR>&lt;a jwcid="@DirectLink" listener="doClick" parameters="{ objectId, index }"&gt; . . . &lt;/a&gt; <BR>其中objectId为String类型，index为int，声明中使用了默认的参数绑定类型。 <BR>对应的方法声明如下 <BR>public void doClick(String objectId, int index) <BR>{ . . . } <BR>此为第二种方式，可见方法的定义符合自然习惯，当然你也可以通过传统的方法，如下所示： public void doClick(IRequestCycle cycle) <BR>{ Object[] parameters = cycle.getListenerParameters(); <BR>String objectId = (String)parameters[0]; <BR>int index = ((Integer)parameters[1]).intValue(); . . . } <BR>这种方式是为了向后兼容以前的版本，当然也适用那种参数数目不确定的情况。 Tapestry默认搜索以下的方法声明： <BR><BR>1、public void method(parameters)（页面的跳转 cycle.activate()如何实现？） <BR>2、public void method(IRequestCycle cycle, parameters) （倾向于使用此方式） <BR>3、public void method()（无需参数传递和页面跳转的情况，估计可能性不大） <BR>4、public void method(IRequestCycle cycle)（传统方式） <BR>不要试图通过参数的类型来映射listener方法，tapestry是根据参数的数目来确定方法的。 <BR><BR><SPAN style="FONT-WEIGHT: bold">Tapestry4新特性(三)-Global Property Source(全局的消息属性配置)</SPAN> <BR><BR>消息属性配置听起来不是很舒服，暂时这样称呼好了，消息属性配置也就是通称的国际化配 <BR>置，通过配置一个properties文件使不同语言的浏览者看到对应语言的版本，一般 <BR>的使用如下，一个page页面，例如example.page,同目录下放一个 <BR>example.properties,在 example.html中使用&lt;span key="key"/&gt;来指定显示值， <BR>中文可以使用example_zh_CN.properties来配置。看起来挺方便的，可 <BR>tapestry4.0以前的版本的国际化不支持全局的属性配置文件，必须每个页面定义 <BR>自己的，无法几个页面共享，但实际开发中，多页面共享属性配置是很常见的， <BR>tapestry4.0中可以通过以下方式获得全局的属性配置文件： <BR>创建一个跟你的项目全局配置文件，如yourApp.application,此文件在4.0以前的 <BR>版本中是必须的，4.0中如果没有必要配置，可以不需要此文件(扯远了),yourApp <BR>是根据你在web.xml定义的，例如 <BR>&lt;servlet&gt; <BR>&lt;servlet-name&gt;tapesty4&lt;/servlet-name&gt; <BR>&lt;servlet-class&gt;org.apache.tapestry.ApplicationServlet&lt;/servlet-class&gt; <BR>&lt;load-on-startup&gt;1&lt;/load-on-startup&gt; <BR>&lt;/servlet&gt; <BR>那属性定义文件就应该是tapestry4.properties,这样在此文件中定义一个：test= <BR>测试，在Home.html中使用&lt; span key="test"&gt;test&lt;/span&gt;,看到“测试”正确显示。 <BR><BR><SPAN style="FONT-WEIGHT: bold">Tapestry4新特性(四)-源代码标注的异常处理</SPAN> <BR><BR>Tapestry本来提供的debug功能就十分强大，4.0版本中提供了更加详细的报错机制，可以显示错误的代码，并在报错的地方加亮标注，具体截图请看附件(谁能告诉我怎么将多余的照片删除呀) <BR><IMG src="http://storage.msn.com/x1pbglk-vqL4BsrGHxA6g8yAypmdEoHV6o7uiOO8641huAbKq4On0RCuSms4gcmE_6D-FUJP7ObABDG4T3uYbEMUcSmABtuxwMoC3GvWV-FA_3U6ogXd2v-5-LVObQna1FR6MA8TgZ-1hX9wh7VwOd0tQ" border=0> <BR><BR><SPAN style="FONT-WEIGHT: bold">Tapestry4新特性(五)-Friendly URLs</SPAN> <BR><BR>Tapestry4.0以前版本中的URL一直被人所诟病，当然现在已经有很多的解决方 <BR>案，4.0版本中已经对此做了改进， <BR>因为现在的版本需要通过hivemind来配置，所以需要设置hivemind.xml中的一些属 <BR>性，具体配置如下： <BR>&lt;?xml version="1.0"?&gt; <BR>&lt;module id="tapestry4" version="1.1.0"&gt; <BR>&lt;contribution configuration-id="tapestry.url.ServiceEncoders"&gt; <BR>&lt;page-service-encoder id="page" extension="html" service="page"/&gt; <BR>&lt;direct-service-encoder id="direct" stateless-extension="direct" <BR>stateful-extension="sdirect"/&gt; <BR>&lt;asset-encoder id="asset" path="/assets/"/&gt; <BR>&lt;extension-encoder id="extension" extension="svc" after="*"/&gt; <BR>&lt;/contribution&gt; <BR>&lt;/module&gt; <BR><BR>同时web.xml中加入映射： <BR>&lt;servlet&gt; <BR>&lt;servlet-name&gt;tapestry4&lt;/servlet-name&gt; <BR>&lt;servlet-class&gt; org.apache.tapestry.ApplicationServlet&lt;/servlet-class&gt; <BR>&lt;load-on-startup&gt;0&lt;/load-on-startup&gt; <BR>&lt;/servlet&gt; <BR>&lt;servlet-mapping&gt; <BR>&lt;servlet-name&gt;tapestry4&lt;/servlet-name&gt; <BR>&lt;url-pattern&gt;*.html&lt;/url-pattern&gt; <BR>&lt;/servlet-mapping&gt; <BR>&lt;servlet-mapping&gt; <BR>&lt;servlet-name&gt;tapestry4&lt;/servlet-name&gt; <BR>&lt;url-pattern&gt;*.direct&lt;/url-pattern&gt; <BR>&lt;/servlet-mapping&gt; <BR><BR>&lt;servlet-mapping&gt; <BR>&lt;servlet-name&gt;tapestry4&lt;/servlet-name&gt; <BR>&lt;url-pattern&gt;*.sdirect&lt;/url-pattern&gt; <BR>&lt;/servlet-mapping&gt; <BR>&lt;servlet-mapping&gt; <BR>&lt;servlet-name&gt;tapestry4&lt;/servlet-name&gt; <BR>&lt;url-pattern&gt;/assets/*&lt;/url-pattern&gt; <BR>&lt;/servlet-mapping&gt; <BR>&lt;servlet-mapping&gt; <BR>&lt;servlet-name&gt;tapestry4&lt;/servlet-name&gt; <BR>&lt;url-pattern&gt;*.svc&lt;/url-pattern&gt; <BR>&lt;/servlet-mapping&gt; <BR>如果希望首页的调用不是通过/app来映射，可以在web.xml中更改redirect： <BR>&lt;filter-name&gt;redirect&lt;/filter-name&gt; <BR>&lt;filter-class&gt;org.apache.tapestry.RedirectFilter&lt;/filter-class&gt; <BR>&lt;init-param&gt; <BR>&lt;param-name&gt;redirect-path&lt;/param-name&gt; <BR>&lt;param-value&gt;/Home.html&lt;/param-value&gt; <BR>&lt;/init-param&gt; <BR>&lt;/filter&gt; <BR>这样键入http://localhost:8080/tapestry4，系统导航到http://localhost: <BR>8080/tapestry4/Home.html, <BR>添加一个Page页面例如Test.page，在Home.html中加入&lt;a href="#" <BR>jwcid="@PageLink" page="Test"&gt;test&lt;/a&gt;， <BR>在生成的Home.html中生成的test的链接地址为：http://localhost: <BR>8080/tapestry4/Test.html <BR><BR><SPAN style="FONT-WEIGHT: bold">Tapestry4新特性(六)-自动定位页面类文件</SPAN> <BR><BR>关于此特性的介绍请参考：<A class=postlink href="http://jakarta.apache.org/tapestry/current/UsersGuide/page-class.html" target=_blank>http://jakarta.apache.org/tapestry/current/UsersGuide/page-class.html</A> <SPAN style="FONT-WEIGHT: bold"><BR>说明：</SPAN> <BR>通俗点说就是您可以不定义.page文件或者定义的.page文件中不指定class 属性，而让服务器自动根据.html文件的路径来寻找对应的类文件。 <BR><SPAN style="FONT-WEIGHT: bold">配置：</SPAN> <BR>在.application的定义文件中添加： &lt;meta key="org.apache.tapestry.page-class-packages" value="org.edynasty.pages"/&gt; 这样如果在文档根目录下有个Home.html文件，你就可以将Home.java放到 org.edynasty.pages(实际开发中配置为您自己的包名)包中，tapestry自动根据 Home.hmtl构造org.edynasty.pages.Home来定位页面的类文件,当然您也可以在WEB -INF目录下放一个Home.page,不需要定义class属性，tapestry自动按照上边的原 理定位。 <BR><SPAN style="FONT-WEIGHT: bold">效果：</SPAN> <BR>这样您可以不需要维护.page中的class属性，直接根据.html文件来写对应 的类文件。而且可以根据业务逻辑来定义目录结构，例如将 org.edynasty.pages.user定义为user相关的类，.html也就可以放到user目录下 边，目录结构如下： <BR>user/ListUsers.html <BR>user/EditUser.html <BR>course/ListCourses.html <BR>course/EditCourses.html <BR>Home.html <BR><BR><SPAN style="FONT-WEIGHT: bold">Tapestry4新特性(七)-Application和Session范围对象的使用</SPAN> <BR><BR>关于此特性的介绍请参考：http://jakarta.apache.org/tapestry/UsersGuide/state.html <BR><SPAN style="FONT-WEIGHT: bold">说明：</SPAN> <BR>Application和Session范围的概念就不说了，T4以前的版本只可以分别指定一个对象， <BR>以前版本的定义如下: <BR>&lt;property name="org.apache.tapestry.visit-class" value="your.package.Visit"/&gt; <BR>&lt;property name="org.apache.tapestry.global-class" value="your.package.Global"/&gt;, <BR>T4中可以指定任意多的对象，而且默认的visit和global仍然可以使用。 <BR><SPAN style="FONT-WEIGHT: bold"><BR>配置：</SPAN>在hivemodule.xml的定义文件中添加： <BR>&lt;contribution configuration-id="tapestry.state.ApplicationObjects"&gt; <BR>&lt;state-object name="applicationUser" scope="application"&gt; <BR>&lt;create-instance class="org.edynasty.model.User"/&gt; <BR>&lt;/state-object&gt; <BR>&lt;state-object name="sessionUser" scope="session"&gt; <BR>&lt;create-instance class="org.edynasty.model.User"/&gt; <BR>&lt;/state-object&gt; <BR>&lt;/contribution&gt; <BR>两个user分别对应Application和Session范围，在需要使用user的page中注入： <BR>&lt;inject property="applicationUser" type="state" object="applicationUser"/&gt; <BR>&lt;inject property="sessionUser" type="state" object="sessionUser"/&gt;，通过 <BR>getter和setter方法调用。 <BR><BR><SPAN style="FONT-WEIGHT: bold">效果：</SPAN>怎么说呢，可以不需要在一个visit中定义N多属性，因为Session的创建需要资源， <BR>只要操作一个visit的属性，就需要创建整个visit，分别定义之后，可以在需要存取时分别创建。</SPAN><SPAN class=postbody></SPAN><SPAN class=gensmall><BR></SPAN><img src ="http://www.blogjava.net/realzar/aggbug/30075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/realzar/" target="_blank">开源爱好者</a> 2006-02-10 01:11 <a href="http://www.blogjava.net/realzar/archive/2006/02/10/30075.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>