˜q™é‡Œæœ‰è¿™ä¸ªé¡µé¢å±òq•抓图:(x¨¬)
™åµé¢æ¨¡æ¿ç”±æ ‡å‡†çš„HTMLæ ‡ç¾å’Œä¸€äº›é¢å¤–çš„å±žæ€§å’Œæ ‡ç¾æž„æˆåQŒè¿™äº›é¢å¤–çš„å±žæ€§å’Œæ ‡ç¾æ˜¯äØ“(f¨´)äº?ji¨£n)告诉Tapestry框架˜q™ä¸ª™åµé¢çš„那些部分是由Tapestry控äšg¾l„æˆã€‚页颿¨¡æ¿å˜æ”‘Öœ¨Webåº”ç”¨çš„æ ¹context目录下。通常åQŒTapestry在å¯åŠ¨æ—¶ä¼?x¨¬)寻扑֒Œå‘ˆçŽ°ä¸€ä¸ªåå?Home"的页。虽然我们å¯ä»¥æ”¹å˜è¿™¿U行为,但ä¾ç…§Tapestry的惯例会(x¨¬)更简å•ã€?br />
Home.html
   <html>
   <head>
     <title>Tapestry Pig Latin Translator</title>
   </head>
   <body>
     <h1>Pig Latin Translator</h1>
     <form jwcid="@Form"�listener="ognl:listeners.submit"�gt;
     <table border="1">
       <tr>
         <td>Value to Translate:</td>
         <td>
           <input type="text" jwcid="@TextField"�value="ognl:inputValue"/>
         </td>
       </tr>
       <tr>
         <td>Pig Latin:</td>
         <td>
           <jwcid="@Insert"�value="ognl:pigLatinValue"/>
         </td>
       </tr>
     </table>
     <input type="submit" jwcid="@Submit"�value="Translate"/>
     </form>
   </body>
   </html>
  Â
™åµé¢æ¨¡æ¿çš„ç»å¤§éƒ¨åˆ†æ˜¯æ™®é€šçš„HTML,åªæœ‰ž®‘部分Tapestryç‰ÒŽ(gu¨©)œ‰çš„å±žæ€§å’Œæ ‡ç¾ã€‚è¿™¿Uæ¨¡æ¿æœºåˆ¶çš„优势ž®±æ˜¯Tapestry™åµé¢æ¨¡æ¿å¯ä»¥åœ¨ä¸€ä¸ªå¯è§å³æ‰€å¾—çš„¾~–辑器里创å¾å’Œé¢„览。æ˜q°Tapestry控äšgéƒ¨åˆ†çš„æ ‡è¯†æ˜¯æœ‰é™çš„å’Œ½H出的ã€?br />
æ ‡è¯†é‡Œçš„jwcid所指是被应用的Tapestry控äšgçš„Java Web Component ID.在上é¢ä»£ç æ–里,我们是éšå¼åœ°ä½¿ç”¨æŽ§äšg。éšå¼çš„æŽ§äšgæ˜¯æŒ‡ç›´æŽ¥åœ¨é¡µé¢æ¨¡æ‰K‡Œå£°æ˜Žä½¿ç”¨çš„æŽ§ä»Óž¼Œã€‚jwcid的剾~€ '@ '½W¦å·ž®±æ˜¯é€šçŸ¥Tapestry˜q™é‡Œå£°æ˜Žä½¿ç”¨äº?ji¨£n)一个éšå¼æŽ§ä»¶ã€?br />
在上é¢çš„Pig Latin Translator™åµé¢æ¨¡æ¿é‡Œç”¨äº?ji¨£n)四个控ä»Óž¼?x¨¬)Formâ‘? TextFieldâ‘? Insertâ‘?å’ŒSubmitâ‘¤ã€‚å®ƒä»¬åªæ˜¯Tapestry框架æä¾›çš„包å«è¶…˜q?0个控件的控äšg库里的四个。在åŽé¢çš„范例ä¸åQŒæˆ‘们将ä¼?x¨¬)看到如何ä‹Éç”¨æ˜¾å¼æŽ§ä»¶ã€‚æ˜¾å¼æŽ§ä»¶æ˜¯æŒ‡æŽ§ä»¶åœ¨™åµé¢è§„范文äšg里声明åŽå†ä‹É用的控äšgã€?br />
在å‰é¢çš„HTML模æ¿é‡Œï¼Œä½¿ç”¨æŽ§äšgçš„åŒæ—Óž¼Œä¹ŸäØ“(f¨´)控äšg指定äº?ji¨£n)傿•°ã€‚例如控件Form①有一个listenerâ‘¡å‚æ•°å®ƒæŒ‡å®šäº?ji¨£n)å½“è¡¨å•æäº¤æ—¶å¯¹åº”çš„™åµé¢¾c»è°ƒç”¨çš„æ–ÒŽ(gu¨©)³•å称。那个ognl:å‰ç¼€çš„ä‹É用诽I‰K¡µé¢çš„HTML模æ¿åQŒæŒ‡å‘çš„æ˜?a >Object Graph Navigation Language (OGNL)。OGNL是一个强大的开æºçš„表达å¼è¯a€åQŒç”¨äºŽå°†™åµé¢å†…控件的属性绑定到™åµé¢¾cÈš„属性ã€?br />
现在我们看看™åµé¢è§„范文äšg。页é¢è§„范文件是一个扩展å为pageçš„XMLæ–‡äšgåQŒè¿™ä¸ªæ–‡ä»¶æœ‰è®¸å¤šèŒè´£åQŒåœ¨ä¼—多èŒè´£ä¸æœ€åŸºæœ¬æ˜¯æŒ‡å®šé¡µé¢å¯¹åº”çš„Java¾c…R€‚页é¢è§„èŒƒæ–‡ä»¶å˜æ”‘Öœ¨webappçš„WEB_INF目录ã€?br />
Home.page
   <?xml version="1.0"?>
   <!DOCTYPE page-specification PUBLIC
       "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
       "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>
   <page-specification class="Home">
       <property-specification name="inputValue" type="java.lang.String"/>
       <property-specification name="pigLatinValue" type="java.lang.String"/>
   </page-specification>
  Â
™åµé¢è§„范文äšgçš„æ ¹å…ƒç´ æœ‰ä¸€ä¸ªclass的属性,它指定了(ji¨£n)˜q™ä¸ª™åµå¯¹åº”çš„Java¾c…R€‚这个类必须è¦å®žçްorg.apache.tapestry.Ipage接å£ã€‚页é¢è§„èŒƒåŒæ—‰™¡µå®šä¹‰äº?ji¨£n)两个属æ€?property)å…ƒç´ åQŒä»¥ä¾¿Tapestry在页é¢ç±»é‡Œåˆ›å»ºæ–°çš„属性ã€?br />
Tapestry框架æä¾›äº?ji¨£n)org.apache.tapestry.html.BasePage class,它实çŽîCº†(ji¨£n)Ipage接å£ã€‚页é¢ç±»è¢«å˜æ”‘Öœ¨Web-INF/classesç›®å½•ä¸‹ï¼Œè·Ÿä½ çš„Web应用的所需è¦çš„å…¶ä»–¾cÀL”¾åœ¨ä¸€èµ—÷€?br />
Home.java
   import org.apache.tapestry.html.BasePage;
   import org.apache.tapestry.IRequestCycle;
   public abstract class Home extends BasePage {
       public abstract String getInputValue();
       public abstract void setInputValue(String inputValue);
       public abstract String getPigLatinValue();
       public abstract void setPigLatinValue(String pigLatinValue);
       public void submit(IRequestCycle cycle) {
           String inputValue = getInputValue();
           String pigLatinValue = new PigLatinTranslator().translate(inputValue);
           setPigLatinValue(pigLatinValue);
       }
   }
  Â
ä½ è¦æé†’çš„ç¬¬ä¸€ä»¶äº‹æˆ–è®¸æ˜¯è¿™ä¸ªç±»ä¸ÞZ»€ä¹ˆæ˜¯æŠ½è±¡¾c…R€‚它˜q˜æœ‰å‡ 个抽象æ–ÒŽ(gu¨©)³•讉K—®inputValueåQŒpigLatinValue属性。这里利用了(ji¨£n)Tapestryä¼?x¨¬)在˜q行时刻创å¾å类的功能,˜q™ä¸ªåç±»ä¼?x¨¬)创å»ÞZ½ 在页é¢è§„范里声明的属性和生æˆç›¸åº”的访问方法ã€?br />
åœ¨è¡¨å•æäº¤æ—¶™åµé¢¾cÈš„submitæ–ÒŽ(gu¨©)³•ä¼?x¨¬)è¢«è°ƒç”¨ã€‚äØ“(f¨´)什么会(x¨¬)˜q™æ ·åQŸå› 为我们在™åµé¢æ¨¡æ¿é‡Œå°†Form控äšgçš„listenerå±žæ€§æŒ‡å®šäØ“(f¨´)åQšognl:listeners.submit。这ž®±æ„味ç€ä¸€ä¸ªåå«submitçš„listenerä¼?x¨¬)通过™åµé¢¾cÈš„listeners被访问ã€?br />
所有的™åµé¢¾cÕd’ŒæŽ§äšg¾c»éƒ½ä»Žorg.apache.tapestry.AbstractComponent˜q™ä¸ª¾cÈ‘ô承æ¥ä¸€ä¸ªå«listeners的属性。当submitæ–ÒŽ(gu¨©)³•完æˆåŽï¼Œ™åµé¢ä¼?x¨¬)显½Cø™¢«¾˜»è¯‘好的è¯ã€?br />
最åŽè®²è®²Web.xml˜q™ä¸ªWebå‘布æè¿°æ–‡äšg。Tapestry,åƒè®¸å¤šå…¶ä»–çš„‹¹è¡Œçš„Webåº”ç”¨æ¡†æž¶ä¸€æ øP¼Œç”׃¸€ä¸ªServletæž„æˆåQŒä½†æ˜¯è¿˜éœ€è¦ä¸€ä¸ªå‘布æ˜q°æ–‡ä»¶ã€‚那个å‘布æ˜q°æ–‡ä»¶åº”è¯¥è¢«å˜æ”¾åœ¨WEB-INF目录ã€?br />
web.xml
   <?xml version="1.0"?>
   <!DOCTYPE web-app PUBLIC
       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
       "http://java.sun.com/dtd/web-app_2_3.dtd>
   <web-app>
       <display-name>Tapestry Pig Latin Translator</display-name>
       <servlet>
           <servlet-name>tapestry</servlet-name>
           <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
           <load-on-startup>1</load-on-startup>
       </servlet>
       <servlet-mapping>
           <servlet-name>tapestry</servlet-name>
           <url-pattern>/app</url-pattern>
       </servlet-mapping>
   </web-app>
  Â
虽然Pig Latin¾˜»è¯‘应用éžå¸¸½Ž€å•,但是它会(x¨¬)è®©ä½ å¯¹åœ¨Tapestry应用ä¸ä¸€ä¸ªé¡µé¢çš„3个组æˆéƒ¨åˆ†æœ‰äº?ji¨£n)基本的了(ji¨£n)解。它也展½CÞZº†(ji¨£n)创å¾ä¸€ä¸ªTapestry应用的一个页é¢åªéœ€å†™å¤šä¹ˆå°‘的代ç ã€?br />
表å•输入验è¯
Tapestry æä¾›äº?ji¨£n)ä¸€äº›æŽ§ä»¶ä»¥ä¾¿æ ¡éªŒç”¨æˆïL(f¨¥ng)š„è¾“å…¥ã€‚æ ¡éªŒå¾pÈ»Ÿæ˜¯ValidField控äšgçš„æ ¸å¿?j¨©)。在下é¢çš„ç™»å½•åº”ç”¨ä¸æˆ‘们ž®†ä‹É用ValidField控äšg。ValidField控äšgä½äºŽè¡¨å•å†…ï¼Œå¯¹ç”¨æˆ·åœ¨å®¢æˆ·ç«¯çš„æ ¡éªŒæä¾›äº?ji¨£n)有用的å馈和视觉上的错误æ½Cºã€?br />
区域�br />
在Tapestryä¸ï¼ŒåŒºåŸŸåŒ–是相当½Ž€å•的。Tapestryå…许文å—å’Œå›¾å½¢çš„åŒºåŸŸåŒ–ã€‚äØ“(f¨´)äº?ji¨£n)区域化™åµé¢çš„å†…å®¹ï¼Œä½ å¯ä»¥äØ?f¨´)æ¯ä¸€ä¸ªæ·»åŠ ä¸€ä¸ªpropertiesæ–‡äšgåQŒæˆ–者æä¾›ä¸€ä¸ªåŒºåŸŸåŒ–的模æÑ€‚䨓(f¨´)æ¯ä¸ª™åµé¢æä¾›ä¸€ä¸ªèµ„æºæ–‡ä»¶çš„æ–¹å¼˜qœæ¯”½Ž¡ç†å’Œç»´æŠ¤ä¸€ä¸ªå·¨å¤§çš„å…¨å±€çš„åº”ç”¨èŒƒå›´çš„èµ„æºæ–‡äšg½Ž€å•。如果页é¢çš„åŒºåŸŸåŒ–åÆˆä¸ä»…ä»…åªæ˜¯æ–‡å—ä¿¡æ¯çš„区域化,例如™åµé¢çš„布局ä¸åŒæˆ–者组æˆçš„æŽ§äšgä¸åŒåQŒè¿™æ ähƒ…冉|ä¾›åŒºåŸŸåŒ–çš„é¡µé¢æ¨¡æ¿å°±èƒ½æ´¾ä¸Šç”¨åœÞZº†(ji¨£n)。我们会(x¨¬)在下é¢çš„ç™Õd½•应用的ä‹É用Tapestry区域化ã€?br />
åˆ›å¾æŽ§äšg
Tapestryå‘布时æä¾›äº†(ji¨£n)40å¤šä¸ªè‡ªå¸¦çš„æŽ§ä»¶ã€‚å¦‚æžœä½ æƒ³çŸ¥é“æ›´å¤šçš„关于Tapestry自带控äšg的信æ¯ï¼Œè¯·å‚è€?a >Tapestry Component Reference.想看看Tapestry的控件的应用范例å¯è®¿é—?a >Tapestry Component Workbench.å¦‚æžœä½ å‘çŽîC½ 需è¦ä¸€ä¸ªTapestry本èín没æä¾›çš„æŽ§äšgåQŒä½ å¯ä»¥è‡ªå·±åˆ›å¾ä¸€ä¸ªã€‚创å»ÞZ½ 自己的Tapestry控äšg跟创å»ÞZ¸€ä¸ªé¡µé¢æ˜¯ç›æ€¼¼çš„。一个典型的Tapestry控äšgç”׃¸€ä¸ªæŽ§ä»¶è§„范文ä»Óž¼ˆXML文档åQ‰ï¼Œä¸€ä¸ªHTML控äšg模æ¿åQŒä¸€ä¸ªå®žçŽîCº†(ji¨£n)org.apache.tapestry.Icomponent接å£çš„Java¾c…R€‚这个议题有点超出本文的范围åQŒä½†æ˜¯å¦‚æžœä½ æœ‰å…´‘£å¦ä¹?f¨¤n)如何创å»ÞZ½ 自己的Tapestry控äšgåQŒä½ å¯ä»¥å‚考Tapestry的原创ähåQ?a >Tapestry In Action 一书的作è€?-Howard Lewis Ship写的 Designing Tapestry Mega-Components ã€?br />
Tapestry ç™Õd½•应用
ä½ åœ¨Pig latin¾˜»è¯‘器应用ä¸çœ‹åˆ°äº?ji¨£n)Tapestryçš„ä¸€äº›åŸºæœ¬ç‰¹æ€§ã€‚ä¸Žå…¶ç”¨ä¸€ä¸ªå¤æ‚的应用展示Tapestry所有的ç‰ÒŽ(gu¨©)€§ä»¥è‡´äºŽåŽ‹å¾—ä½ æ£ä¸è¿‡æ°”æ¥åQŒè¿˜ä¸å¦‚通过一些简å•çš„åº”ç”¨è®©ä½ æ‰‘Öˆ°ä¸€ç‚¹å¯¹Tapestry的感觉。下é¢è¿™ä¸ªåº”用展½CºTapestry如何处熙åµé¢å¯ÆDˆªåQŒåŒºåŸŸåŒ–åQŒéªŒè¯å’Œå…¶ä»–一些特性ã€?/p>
˜q™é‡Œæœ‰ä¸€ä¸ªHome™å늚„å±å¹•抓图åQŒä¸‹é¢è·Ÿç€å®ƒçš„™åµé¢æ¨¡æ¿ã€?br />
Home.html
   <html>
   <head>
       <title>Welcome to the Tapestry Login Application</title>
   </head>
   <body>
       <h1>Welcome to the Tapestry Login Application</h1>
       <span jwcid="@PageLink"�page="Login">Login</span>
   </body>
   </html>
  Â
˜q™ä¸ªHome™å늚„™åµé¢æ¨¡æ¿é™¤äº†(ji¨£n)一个jwcid属性定义ä‹É用一个Tapestry PageLinkâ‘ æŽ§ä»¶ä»¥å¤–éƒ½æ˜¯æ ‡å‡†çš„HTMLã€?br />
PageLink控äšg生æˆäº?ji¨£n)一个指å‘Login™å늚„‘…链接。既然Home™å‰|²¡æœ‰ä“Q何动æ€çš„è¡ŒäØ“(f¨´)所以它ä¸éœ€è¦é¡µé¢è§„范和™åµé¢å¯¹åº”çš„Java¾c…R€?br />
˜q™é‡Œæ˜¯Login™å늚„å±å¹•抓图åQŒåŽé¢è·Ÿç€æ˜¯å®ƒçš„页颿¨¡æÑ€?br />
Login.html
   <html>
   <head>
       <title>
           <span key="title">①Login</span>
       </title>
   </head>
   <body jwcid="@Body">�br />       <span jwcid="@Conditional" condition="ognl:beans.delegate.hasErrors">�br />           <div style="color: red">
               <span jwcid="@Delegator" delegate="ognl:beans.delegate.firstError">�br />                   Error Message
               </span>
           </div>
       </span>
       <p style="font-weight: bold" >
           <span key="hint">Hint: Your password is your username spelled backwards.</span>
       </p>
      Â
       <form jwcid="@Form" listener="ognl:listeners.login" delegate="ognl:beans.delegate">
â‘?br />Â Â Â Â Â Â Â Â Â Â Â <table>
               <tr>
                   <td align="right">
                       <span jwcid="@FieldLabel" field="ognl:components.inputUsername"�gt;
                           Username:
                       </span>
                   </td>
                   <td>
                       <input type="text" jwcid="inputUsername"�value="simpson_h"
size="30"/>
                   </td>
               </tr>
               <tr>
                   <td align="right">
                       <span jwcid="@FieldLabel" field="ognl:components.inputPassword">
                           Password:
                       </span>
                   </td>
                   <td>
                       <input type="text" jwcid="inputPassword" hidden="true" value=""
size="30"/>
                   </td>
               </tr>
               <tr>
                   <td colspan="2" align="center">
                       <input type="submit" jwcid="@Submit" value="message:login"/>
                   </td>
               </tr>
           </table>
       </form>
   </body>
   </html>
  Â
˜q™ä¸ª™åµé¢æ¨¡æ¿å¤§å¤šæ•°æ˜¯é€šå¸¸çš„HTML。我们从™åµé¢æ¨¡æ¿ä¸å¯ä»¥çœ‹åˆ°Tapestry的区域化ç‰ÒŽ(gu¨©)€§ï¼š(x¨¬)它ä‹É用一个spanå…ƒç´ åQŒè¿™ä¸ªspanå…ƒç´ å¸¦æœ‰ä¸€ä¸ªå«key的属性,keyçš„å€¼æ˜ ž®„到Login.propertiesæ–‡äšg里一个属性。一个Body控äšg被声明ä‹Éç”¨ï¼Œå› äØ“(f¨´)它对客户端的JavaScriptæ ¡éªŒæ˜¯å¿…éœ€çš„ã€?br />
为Form component⑤设定delegate属性激‹z»è¡¨å•输入验è¯ã€‚delegate属性是我们在页é¢è§„范里声明的org.apache.tapestry.valid.IvalidationDelegate的实现类。如果验è¯é”™è¯¯å‘生了(ji¨£n)åQŒæˆ‘们用Conditional component③控件判æ–delegateæ˜¯å¦æœ‰ä“Q何错误,如果有就把第一个错误④昄¡¤º¾l™ç”¨æˆ—÷€‚如果ognl 表达å¼ognl:beans.delegate.hasErrors 为true,Conditional控äšgž®†æ˜¾½Cºå®ƒçš„内容实体。所有的™åµé¢¾cÕd’ŒæŽ§äšg¾c»éƒ½ä»ŽAbstractComponent¾l§æ‰¿æ¥ä¸€ä¸ªå«beans的属性。这个beans属性是一个org.apache.tapestry.IbeanProvider的实例,利用它å¯ä»¥é€šè¿‡åå—å–得在页é¢è§„范文仉™‡Œå®šä¹‰çš„beans.FieldLabel⑥被用于为inputuserName validField控äšg昄¡¤ºæ ‡ç¾åQŒè¿™ä¸ªFieldLabel控äšg也被用æ¥ä¸Žè¡¨å•的验è¯ä»£ç†å作åQŒæŒ‡å‡ºåŒ…å«é”™è¯¯çš„输入域ã€?br />InputUserName⑦控件是一个显½CºæŽ§ä»¶çš„例åã€‚æ˜¾å¼æŽ§ä»¶æ˜¯æŒ‡åœ¨™åµé¢è§„范文äšg声明的控件。InputUsernameå’ŒinputPassword控äšg都是昑ּ的,它们与FieldLabelè”åˆæ˜„¡¤ºå®ƒä»¬çš„displayName属性ã€?br />
下é¢çš„æ˜¯Login™å늚„èµ„æºæ–‡äšg。Login.properties跟页é¢è§„范一òq¶å˜æ”‘Öœ¨WEB-INF目录ã€?br />
Login.properties
   title = Login to the Application
   hint = Hint: Your password is your username spelled backwards.
   login = Login
   username = Username:
   password = Password:
   invalidpassword = Invalid Password
  Â
Here is the page specification for the Login page.
Login.page
   <?xml version="1.0"?>
   <!DOCTYPE page-specification PUBLIC
       "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
       "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>
   <page-specification class="com.ociweb.tapestry.Login">
       <bean name="delegate" class="org.apache.tapestry.valid.ValidationDelegate"/>�br />
       <bean name="requiredValidator"�br />           class="org.apache.tapestry.valid.StringValidator">
           <set-property name="required" expression="true"/>
           <set-property name="clientScriptingEnabled" expression="true"/>
       </bean>
       <property-specification name="username" type="java.lang.String"/>
       <property-specification name="password" type="java.lang.String"/>
       <component id="inputUsername" type="ValidField"> �br />           <message-binding name="displayName" key="username"/> �br />           <binding name="validator" expression="beans.requiredValidator"/> �br />           <binding name="value" expression="username"/> �br />       </component>
       <component id="inputPassword" type="ValidField"> �br />           <message-binding name="displayName" key="password"/>
           <binding name="validator" expression="beans.requiredValidator"/>
           <binding name="value" expression="password"/>
       </component>
   </page-specification>
  Â
Page-specificationå…ƒç´ çš„class属性和两个property-specificationå…ƒç´ ä¸ŽPig Latin¾˜»è¯‘å™¨åº”ç”¨æ˜¯ç›æ€¼¼çš„ã€?br />
ä½ ä¼š(x¨¬)å‘现½W¬ä¸€ä¸ªæ–°ä¸œè¥¿-beanå…ƒç´ â‘ ï¼Œbeanå…ƒç´ æŠŠä¸€ä¸ªorg.apache.tapestry.valid.ValidationDelegate
的实例指定了(ji¨£n)åç§°"delegate"。页é¢HTML模æ¿é‡Œçš„Form控äšgæŠŠå®ƒçš„å‚æ•°delegate讑֮šä¸?br />ognl:beans.delegate,ž®±æ˜¯æŒ‡å‘äº?ji¨£n)这个org.apache.tapestry.valid.ValidationDelegate实例ã€?br />Beanå…ƒç´ â‘¡æŠŠä¸€ä¸ªorg.apache.tapestry.valid.StringValidator的实例指定了(ji¨£n)åç§°"
requiredValidator",以用于验è¯ã€‚这个beançš„requiredå±žæ€§è¢«è®¾äØ“(f¨´)true表明使用˜q™ä¸ªbean的域是必™å»è¢«éªŒè¯çš„。这个beançš„clientScriptingEnabled属性被讑֮šä¸ºture,表明使用˜q™ä¸ªbean的域客户端的JavaScript验è¯åŠŸèƒ½æ˜¯æ¿€‹zÈš„。RequiredValidator bean被用于验è¯inputUsernameå’ŒinputPassword的内å®V€?br />
控äšginputUsername③被控äšg规范声明为ValidFieldåQŒValidField是一¿U用于Tapestry验è¯åç³»¾lŸçš„ç‰ÒŽ(gu¨©)®Šç‰ˆæœ¬çš„TextField控äšg。Message-bindingå…ƒç´ è¢«ç”¨äºŽæŒ‡å®šinputUsername控äšgçš„displayName傿•°çš„å€û|¼Œ˜q™ä¸ªå€¼æ˜¯ç”?username"为关键å—从login.properties④文仉™‡Œå¾—到。InputUsername控äšgçš„validator傿•°è¢«è®¾å®šäØ“(f¨´)requiredValidator bean,˜q™æ˜¯æˆ‘们在页é¢è§„范里声明˜q‡çš„⑤。控件的value傿•°è·Ÿé¡µé¢Java¾cÈš„username属性绑定在一起⑥。控件inputPassword的控件规范跟控äšginputUsernameå‡ ä¹Žç›æ€¼¼åQŒé™¤äº?ji¨£n)用于å–å¾—displayName的关键å—和绑定的™åµé¢Java¾cÈš„属性ä¸åŒã€?br />
通过使用ValidField控äšgå’ŒäØ“(f¨´)表å•(form)æä¾›ä¸€ä¸ªValidationDelegate, 我们‹È€‹zÖMº†(ji¨£n)Login表å•的验è¯åŠŸèƒ½ã€‚é™¤äº?ji¨£n)æœåŠ¡å™¨ç«¯çš„éªŒè¯åQŒTapestry也æä¾›äº†(ji¨£n)客户端的验è¯åQˆåˆ©ç”¨JavaScriptåQ‰ã€‚下é¢å°±æ˜¯å½“用户æäº¤ä¸€ä¸ªè¡¨å•è€Œæ²¡æœ‰äØ“(f¨´)UserName域æä¾›å€¼æ—¶åQŒä¸€ä¸ªJavaScripté”™è¯¯å¯¹è¯æ¡†å¼¹å‡ºæ—¶çš„å±òq•抓图ã€?br />
下颞®±æ˜¯å½“用æˆäh交一个表å•è€Œæ²¡æœ‰äØ“(f¨´)Password域æä¾›å€¼æ—¶åQŒä¸€ä¸ªJavaScripté”™è¯¯å¯¹è¯æ¡†å¼¹å‡ºæ—¶çš„å±òq•抓图ã€?br />
下颞®±æ˜¯Login™åµå¯¹åº”çš„Java ¾c…R€?br />
Login.java
   package com.ociweb.tapestry;
   import org.apache.tapestry.html.BasePage;
   import org.apache.tapestry.IRequestCycle;
   import org.apache.tapestry.valid.ValidationConstraint;
   import org.apache.tapestry.valid.IValidationDelegate;
   public abstract class Login extends BasePage {
       public abstract String getUsername();
       public abstract void setUsername(String username);
       public abstract String getPassword();
       public abstract void setPassword(String password);
       public void login(IRequestCycle cycle) {
           String username = getUsername();
           String password = getPassword();
           StringBuffer sb = new StringBuffer(username);
           String validPassword = sb.reverse().toString();
           if (password.equals(validPassword)) {
               cycle.activate("Success");�br />           } else {
               String errorMessage = getMessage("invalidpassword");�br />               IValidationDelegate validationDelegate =
                       (IValidationDelegate) getBeans().getBean("delegate");�br />               validationDelegate.record(errorMessage,
                                         ValidationConstraint.CONSISTENCY);�br />           }
       }
   }
  Â
è·ŸPig Latin¾˜»è¯‘å™¨åº”ç”¨ä¸€æ øP¼Œæˆ‘们的页é¢ç±»ä¹Ÿæ˜¯æŠ½è±¡çš„,它有抽象æ–ÒŽ(gu¨©)³•讉K—®åœ¨é¡µé¢è§„范里定义的属æ€?properties)。Tapestryä¼?x¨¬)在˜q行时刻创å¾usernameå’Œpassword属性。Loginæ–ÒŽ(gu¨©)³•åªæ˜¯½Ž€å•的验è¯ä¸€ä¸‹ç”¨æˆ¯‚¾“入的密ç 值是å¦åˆšå¥½æ˜¯ç”¨æˆ·åçš„åå‘。如果密ç 通过验è¯åQŒç”¨æˆ·å°†è¢«å¼•领导Success pageâ‘ ã€?br />
如果密ç 输入有误åQŒæˆ‘们用关键å?invalidPassword"通过从org.apache.tapestry.AbstractComponent里ç‘ô承æ¥çš„getMessage()æ–ÒŽ(gu¨©)³•从Login.properties②里查找对应的资æºã€‚æˆ‘ä»¬éœ€è¦æŠŠå¯†ç 错误信毾Uªå½•到我们在™åµé¢è§„范ä¸å®šä¹‰çš„™åµé¢validation delegateä¸åŽ»ã€‚æˆ‘ä»¬å¯ä»¥åˆ©ç”¨æˆ‘们在™åµé¢è§„èŒƒä¸æŒ‡å®šçš„åç§°åQŒä»Ž™åµé¢çš„beanså±žæ€§ä¸æ‰‘Ö›žvalidationDelegate③。最åŽï¼Œæˆ‘们调用org.apache.tapestry.valid.IvalidationDelegateçš„recordæ–ÒŽ(gu¨©)³•æŠŠå°†è¦æ˜¾½Cºç»™ç”¨æˆ·çœ‹çš„错误信æ¯ä¿å˜èµäh¥ã€‚下é¢å°±æ˜¯å½“用户输入错误密ç çš„æäº¤åŽçš„å±òq•抓图ã€?br />
下颞®±æ˜¯Success™å늚„™åµé¢æ¨¡æ¿ã€‚Success™å늚„™åµé¢æ¨¡æ¿ä»…仅包å«HTMLæ ‡è¯†åQŒæ‰€ä»¥å®ƒä¸éœ€è¦é¡µé¢è§„范和™åµé¢
Java¾c…R€?br />
Success.html
   <html>
   <head>
       <title>Successful Login</title>
   </head>
   <body>
       <p>
           Congratulations! You have successfully logged on.
       </p>
   </body>
   </html>
  Â
æ€È»“
我希望这½‹‡æ–‡ç« å·²¾lå‘ä½ å±•½CÞZº†(ji¨£n)Tapestry框架在构建Web应用的是多么½Ž€å•,然而优雅。Tapestry与大多数ä¸ÀLµWeb应用框架最大ä¸åŒåœ¨äºŽå®ƒè®©ä½ 用基于控件的方å¼å¼€å‘,而éžä»¥æ“ä½œäØ“(f¨´)ä¸å¿ƒ(j¨©)的方å¼å¼€å‘。如果这½‹‡æ–‡ç« 激起了(ji¨£n)ä½ çš„å…´è¶£åQŒæˆ‘廸™®®ä½ 把它下载下æ¥åˆ©ç”¨å®ƒä½ 自å·Þqš„½Ž€å•çš„Webåº”ç”¨ã€‚é€šè¿‡æ„Ÿå—½Ž€å•的应用åQŒè¿™æ˜¯ä½ äº?ji¨£n)è§£˜q™ä¸ªæ¡†æž¶çš„ä¼˜ç‚¹çš„å”¯ä¸€é€”å¾„ã€‚å¦‚æžœä½ æƒ›_œ¨ä½ 的下一个项目里使用Tapestry,我强烈å¾è®®ä½ è´ä¹°
Tapestry In Action ˜q™æœ¬ä¹¦ã€‚我拥有˜q™æœ¬ä¹¦ï¼Œå¯¹å®ƒæˆ‘感到很满æ„ã€?br />
References
1 Zip file with all source code and war files from the article. (12K)
                http://www.ociweb.com/jnb/jnb2004_05.zip
2 Tapestry Home Page http://jakarta.apache.org/tapestry/
3 Tapestry In Action Page http://www.manning.com/lewisship/
4 Tapestry Wiki http://jakarta.apache.org/tapestry/wiki_frame.html
5 OGNL page http://www.ognl.org/
6 Tapestry Component Reference
                http://jakarta.apache.org/tapestry/doc/ComponentReference/index.html
7 Tapestry Component Workbench http://www.t-deli.com/app
8 Designing Tapestry Mega-Components
                http://www.onjava.com/pub/a/onjava/2001/11/21/tapestry.html
注:(x¨¬)原文地å€åQ?a >http://www.inspiresky.com/Article/java/2006-02-14/412.html