Tapestry入門及進階二

文章發表: suncold

發表日期: 2004-07-30

下面來談談Tapestry的開發流程。
Tapestry的開發主要有兩種:一種是控件的開發,一種是頁面的開發,其實頁面也可以被看成控件。

以我的工程爲例,我的控件全放在com.ht.components下
以我的ToolBar爲例,
我的ToolBar控件放在com.ht.components.toolbar下
下面有
IToolItemDescirption.java
IToolItemListener.java
SimpleToolItemDescription.java
ToolBar_en_US.properties
ToolBar_zh_CN.properties
ToolBar.html
ToolBar.jwc
ToolItem.html
ToolItem.java
ToolItem.jwc

因爲我是這樣設計的,一個ToolBar包括一些ToolItem項,每個ToolItem的數據由一個
IToolItemDescription來提供.

一個控件XXX的通常組成爲
一個XXX.java文件
一個XXX.jwc文件
一個XXX.html文件(當然html也可以不要,一個控件的render完全交給XXX.java去實現也是可行的)
可選的爲
XXX._en_US_properties(對應的美國英語字符資源文件)
XXX._zh_CN_properties(對應的中國大陸字符資源文件)
XXX.xxx_properties(你還可以添加其他的local字符資源文件,只要xxx是合法的locale)

我的例程實現:

package com.ht.components.toolbar;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: </p>
* @author Hery Tang
* @version 1.0
*/
import org.apache.tapestry.IAsset;

public interface IToolItemDescription {
   public IToolItemListener getToolItemListener();
   public IAsset getAsset();
   public IAsset getDisabledAsset();
   public String getLabel();
   public String getActionType();
   public boolean isSeparator();
   public boolean isEnable();
}

package com.ht.components.toolbar;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: </p>
* @author Hery Tang
* @version 1.0
*/
import org.apache.tapestry.IPage;

public interface IToolItemListener {
  public void actionPerformed();
}

package com.ht.components.toolbar;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: </p>
* @author Hery Tang
* @version 1.0
*/
import org.apache.tapestry.IAsset;

public class SimpleToolItemDescription implements IToolItemDescription{
  private IToolItemListener toolItemListener;
  private IAsset enabledAsset;
  private IAsset disabledAsset;
  private String label;
  private String actionType;
  private boolean isSeparator;
  private boolean isEnable;
  public SimpleToolItemDescription() {
    isEnable = true;
    isSeparator = false;
  }

  public IToolItemListener getToolItemListener() {
    return toolItemListener;
  }
  public void setToolItemListener(IToolItemListener listener) {
    toolItemListener = listener;
  }

  public IAsset getAsset() {
    return enabledAsset;
  }

  public void setAsset(IAsset asset) {
    this.enabledAsset = asset;
  }
  public IAsset getDisabledAsset() {
    return disabledAsset;
  }
  public void setDisabledAsset(IAsset asset) {
    this.disabledAsset = asset;
  }

  public String getLabel() {
    return label;
  }

  public void setLabel(String label) {
    this.label = label;
  }

  public void setActionType(String actionType) {
    this.actionType = actionType;
  }
  public String getActionType() {
    return actionType;
  }
 
  public boolean isSeparator() {
    return isSeparator;
  }
 
  public void setIsSeparator(boolean value) {
    isSeparator = value;
  }
 
  public boolean isEnable() {
    return isEnable;
  }
 
  public void setIsEnable(boolean value) {
    isEnable = value;
  }

}

ToolBar_en_US.properties
ToolBar_zh_CN.properties
暫時爲空,我沒有需要國際化的字符資源

ToolBar.html

<span jwcid="$content$">
<table width="100%" border="0" cellpadding="0" cellspacing="1">
        <tr>
                <span jwcid="@Conditional" condition="ognl:!isAlignLeft">
                        <td align="right">
                <table border="0" cellpadding="0" cellspacing="0">
                                        <tr>
                                                <span jwcid="@Foreach" source="ognl:toolItemDescriptions" value="ognl:currentToolItemDesc">
                                                                  <td>
                                                                          <span jwcid="@ToolItem" description="ognl:currentToolItemDesc"/>
                                                                  </td>
                                                                  <td width="10">
                                                                          &nbsp;
                                                                  </td>

                                                    </span>
                                            </tr>
                                    </table>
                            </td>
    </span>
    <span jwcid="@Conditional" condition="ognl:isAlignLeft">
        <td align="left">
                                <table border="0" cellpadding="0" cellspacing="0">
                                        <tr>
                                                <span jwcid="@Foreach" source="ognl:toolItemDescriptions" value="ognl:currentToolItemDesc">
                                                                <td>
                                                                        <span jwcid="@ToolItem" description="ognl:currentToolItemDesc"/>
                                                                </td>
                                                                <td width="10">
                                                                        &nbsp;
                                                                </td>
                                                       </span>
                                              </tr>
                                    </table>
            </td>
    </span>
            </tr>
</table>
</span>

ToolBar.java
package com.ht.components.toolbar;

import org.apache.tapestry.BaseComponent;
import org.apache.tapestry.IRequestCycle;
import java.util.List;

/**
* Simple ArrayViewer object, for the Component chapter of the Tutorial
* @author neil clayton
*/
public abstract class ToolBar extends BaseComponent {
        private IToolItemDescription currentToolItemDesc;
        private List toolItemDescriptions;

        public IToolItemDescription getCurrentToolItemDesc() {
          return currentToolItemDesc;
        }

        public void setCurrentToolItemDesc(IToolItemDescription itemDesc) {
          this.currentToolItemDesc = itemDesc;
        }

        public List getToolItemDescriptions() {
          return toolItemDescriptions;
        }

        public void setToolItemDescriptions(List descList) {
          toolItemDescriptions = descList;
        }

        /**
         * @see net.sf.tapestry.AbstractComponent#cleanupAfterRender(IRequestCycle)
         */
        protected void cleanupAfterRender(IRequestCycle cycle) {
                currentToolItemDesc = null;
                toolItemDescriptions = null;
                super.cleanupAfterRender(cycle);
        }

        public abstract boolean getIsAlignLeft();
}

ToolBar.jwc

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE component-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>


<component-specification class="com.ht.components.toolbar.ToolBar" allow-body="no" allow-informal-parameters="yes">

    <parameter
        name="toolItemDescriptions"
        type="java.util.List"
        direction="in"
        required="yes">
    </parameter>

    <parameter name="isAlignLeft"
type="boolean"
required="no"
direction="in"/>

</component-specification>

ToolItem.html

<span jwcid="$content$">
<span jwcid="@Conditional" condition="ognl:!isSeparator">
<span jwcid="@Conditional" condition="ognl:IsEnable">
        <span jwcid="link"><img jwcid="enabledImage"/><font color="White"><span jwcid="@InsertText" value="ognl:label"/></font></span>
</span>
<span jwcid="@Conditional" condition="ognl:!IsEnable">
        <img jwcid="disabledImage"/><font color="#A0A0A0"><span jwcid="@InsertText" value="ognl:label"/></font>
</span>
</span>
<span jwcid="@Conditional" condition="ognl:isSeparator">
<img jwcid="@Image" image="ognl:enabledImage"/>
</span>
</span>

ToolItem .java

package com.ht.components.toolbar;

import org.apache.tapestry.BaseComponent;
import org.apache.tapestry.IBinding;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.components.Foreach;
import org.apache.tapestry.IAsset;

public class ToolItem extends BaseComponent{
  private IToolItemDescription desc;

  /**
   * @see net.sf.tapestry.AbstractComponent#cleanupAfterRender(IRequestCycle)
   */
  protected void cleanupAfterRender(IRequestCycle cycle) {
    desc = null;
    super.cleanupAfterRender(cycle);
  }

  public IToolItemDescription getDescription() {
    return desc;
  }

  public void setDescription(IToolItemDescription desc) {
    this.desc = desc;
  }
  public void excuteCurrent(IRequestCycle cycle) {
    if(desc != null) {
      IToolItemListener listener = desc.getToolItemListener();
      listener.actionPerformed();
    }
  }
  public IAsset getEnabledAsset() {
    return desc.getAsset();
  }
  public IAsset getDisabledAsset() {
    return desc.getDisabledAsset();
  }
  public String getLabel() {
    return desc.getLabel();
  }
  public boolean getIsSeparator() {
    return desc.isSeparator();
  }
  public boolean getIsEnable() {
    return desc.isEnable();
  }
}

ToolItem.jwc

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE component-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>


<component-specification class="com.ht.components.toolbar.ToolItem" allow-body="no" allow-informal-parameters="yes">

    <parameter
        name="description"
        type="com.ht.components.toolbar.IToolItemDescription"
        direction="in"
        required="yes">
    </parameter>

    <component id="link" type="LinkSubmit">
            <binding name="listener" expression="listeners.excuteCurrent"/>
    </component>

    <component id="enabledImage" type="Image">
            <binding name="image" expression="enabledAsset"/>
    </component>

<component id="disabledImage" type="Image">
            <binding name="image" expression="disabledAsset"/>
    </component>
</component-specification>

我就拿ToolBar這個控件講:
先看ToolBar.jwc

<component-specification class="com.ht.components.toolbar.ToolBar" allow-body="no" allow-informal-parameters="yes">

這句是去說控件ToolBar對應的class爲com.ht.components.toolbar.ToolBar
allow-body="no'是說這個控件不允許有body, allow-informal-parameters="yes"是說這個控件允許帶非正式參數。

控件的參數有兩種一種是在jwc文件裏規定的,一種是沒有規定,爲什麼會有非正式參數呢?大家知道Tapestry的控件,最後render到頁面最終還是什麼
<table width="100%" border="0" cellpadding="0" cellspacing="1">
   <tr>
      <td class="xxx"></td>
   </tr>
</table>
HTML的元素如table, tr, td,span等等都是可以帶很多參數,如果我們的控件輸出一般會
對應於一個元素,這時非正式參數就會以元素的參數輸出。

<parameter
        name="toolItemDescriptions"
        type="java.util.List"
        direction="in"
        required="yes">
    </parameter>
這個說明ToolBar控件需要配製一個叫toolItemDescriptions的參數,參數類型爲java.util.List,direction爲in表示這個參數僅僅需要輸入,不要輸出,
required=yes表示這個參數是必須的,一定要提供。


    <parameter name="isAlignLeft"
type="boolean"
required="no"
direction="in"/>
意義同上。

我們再來分析一下ToolBa.html

首先這個控件的模版被一個
<span jwcid="$content$">
</span>
包圍,這個是說明,只有這個區域裏的內容纔是有意義的,區域外的全被忽略。

然後這個控件可分爲兩部分,根據isAlignLeft參數決定這個ToolBar顯示時是否向左靠齊
我們分析這一句
<span jwcid="@Conditional" condition="ognl:!isAlignLeft">

</span>
首先講講怎麼使用控件,Tapestry的控件有四種:
Tapestry自己提供的有三種:
可參考:
http://jakarta.apache.org/tapestry/doc/ComponentReference/index.html

其中包括:
1 Framework Library (基礎控件)
2 Contrib Library (Contributores 開發的控件)
3 WML Library   (應用在WML上的控件,主要用在移動設備,暫時不談)

4 自己開發的控件 

Tapestry中控件是可以由別的控件組成的,而且控件的嵌套級數不受限制,要在一個頁面或一個控件中應用已開發的控件或Tapestry的提供的控件有兩種方式:

一種是在控件規範文件(*.jwc)或頁面規範文件(*.page)聲明後再在HTML模版裏使用
一種直接在HTML模版裏使用.

不過這兩種情況有個共同點,你都會在HTML模版發現<span jwcid="***">的字樣。

第一種情況:
你看那個ToolItem.jwc
裏面含有
  <component id="link" type="LinkSubmit">
            <binding name="listener" expression="listeners.excuteCurrent"/>
    </component>

    <component id="enabledImage" type="Image">
            <binding name="image" expression="enabledAsset"/>
    </component>

<component id="disabledImage" type="Image">
            <binding name="image" expression="disabledAsset"/>
    </component>

這裏就是聲明裏三個空間,我們就看第一個,
  <component id="link" type="LinkSubmit">
            <binding name="listener" expression="listeners.excuteCurrent"/>
    </component>
 這裏聲明一個控件 id爲link,id要是唯一的(是在同一控件名字空間裏),
 type爲LinkSubmit,就是指定這個控件的類型,當然如果是使用自己開發的控件,還要注意名字空間的問題,這個問題下面再談。

 <binding name="listener" expression="listeners.excuteCurrent"/>

這句是爲這個控件listener參數綁定一個值,expression=listeners.excuteCurrent
這個表達式是一個OGNL表達式,它等同於expression=this.getListeners().getListener("excuteCurrent");這裏的this當然是com.ht.components.toolbar.ToolItem
所以我們察看ToolItem,會發現這個listener綁定的方法是

public void excuteCurrent(IRequestCycle cycle) {
    if(desc != null) {
      IToolItemListener listener = desc.getToolItemListener();
      listener.actionPerformed();
    }
}

現在這個控件(id=link)聲明配置好了,我們再看看ToolItem.html
會發現這一段
<span jwcid="link"><img jwcid="enabledImage"/><font color="White"><span jwcid="@InsertText" value="ognl:label"/></font></span>

注意<span jwcid="link">***</span>,裏面的東西暫時不管
這個<span jwcid="link">就是引用的我們剛纔那個叫link的LinkSubmit控件。

第二種是直接在HTML模版裏使用:

再回到前面看ToolBa.html裏的那一句
<span jwcid="@Conditional" condition="ognl:!isAlignLeft">

</span>

這裏就是在HTML模版裏直接使用控件的例子,這裏意思是使用一個類型爲Conditional的控件,id忽略,Tapestry會給它自動指定一個id,如果你寫成
<span jwcid="xxx@Conditional" condition="ognl:!isAlignLeft">
那麼你指定了這個控件的id爲xxx.
這裏的condition="ognl:!isAlignLeft"就跟我們規範文件(*.jwc,*.page)裏寫成的
<binding name="condition" expression="!isAlignLeft"/>是一個意義。

開發好控件的管理:

  對於自己開發的控件,我們要把它管理起來,以便在以後的開發流程中使用,
我的在這裏談談如何管理自己開發的控件的問題。具體的方法就是把它歸檔到一個library
裏去。

比如我開發了一些控件,我就把它歸檔到一個叫Common.library的xml文檔裏去。

Common.library

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE library-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>

<library-specification>
<!-- Library Section-->
<library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/>
<library id="basic" specification-path="/com/ht/components/basic/Basic.library"/>
<!-- Add more libraries here.-->
<!-- End of Library Section-->

<component-type type="TabPanel" specification-path="tabpanel/TabPanel.jwc"/>
<component-type type="Border" specification-path="border/Border.jwc"/>
<component-type type="ToolItem" specification-path="toolbar/ToolItem.jwc"/>
    <component-type type="ToolBar" specification-path="toolbar/ToolBar.jwc"/>
<component-type type="AnchorDirect" specification-path="tree/components/AnchorDirect.jwc"/>
    <component-type type="TreeDataView" specification-path="tree/components/TreeDataView.jwc"/>
    <component-type type="TreeHeaders" specification-path="tree/components/TreeHeaders.jwc"/>
    <component-type type="TreeNodeView" specification-path="tree/components/TreeNodeView.jwc"/>
    <component-type type="TreeView" specification-path="tree/components/TreeView.jwc"/>
<component-type type="FileList" specification-path="table/FileList.jwc"/>
<component-type type="WrapInsertText" specification-path="wraptext/WrapInsertText.jwc"/>
<component-type type="HighlightInsertText" specification-path="highlight/HighlightInsertText.jwc"/>
<component-type type="DefaultTableColumnComponent" specification-path="table/DefaultTableColumnComponent.jwc"/>
<component-type type="AlignRightTableColumnComponent" specification-path="table/AlignRightTableColumnComponent.jwc"/>
<component-type type="DefaultTableColumns" specification-path="table/DefaultTableColumns.jwc"/>
</library-specification>

<libray-specification>包含兩種元素
一種是library<library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/>

因爲如果被歸檔的控件還引用到其他的被歸檔的控件(控件庫),就必須在這裏包含進來。

例外一種是
<component-type type="ToolBar" specification-path="toolbar/ToolBar.jwc"/>
就是被歸檔的控件項定義,這句我們應該有印象,這個控件就是我們前面討論的ToolBar
注意這個specification-path是相對路徑。
比如我的Common.library位於com.ht.components包內,而那個ToolBar.jwc位於com.ht.components.toolbar包內。

頁面的開發:
我的Web Application只支持英語和簡體中文,以開發Home頁爲例,我所需要新建的文件
爲:
Home.java
Home.page
Home.properties
Home_zh_CN.properties
它們都位於com.ht.home包內,對應的目錄爲F:/myproject/TapestryExmaple/src/
com/ht/home

Home.html
它位於context下home目錄內,對應的目錄爲F:/myproject/TapestryExmaple/context/home

我的例程爲:
Home.java
package com.ht.home;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.tapestry.engine.AbstractEngine;
import org.apache.tapestry.html.BasePage;
import com.ht.web.PatientRecordBasePage;
import com.ht.web.PatientRecordEngine;
import com.ht.components.tabpanel.*;


/**
* @author Hery Tang
*
* Creation Date 2003-9-22
* Version 1.0
*/
public class Home extends PatientRecordBasePage {
    public void logout() {
        PatientRecordEngine engine = (PatientRecordEngine) getEngine();

        engine.logout();
    }
}

Home.page

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE page-specification PUBLIC
"-//Apache Software Foundation//Tapestry Specification 3.0//EN"
"Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>

<page-specification class="com.ht.home.Home">
<component id="border" type="common:Border">
<message-binding name="title" key="title"/>
<binding name="styleSheet" expression="assets.test"/>
</component>

<context-asset name="$template" path="home/Home.html"/>
<context-asset name="menuIcon" path="home/images/homeIcon.gif"/>
<context-asset name="test" path="home/css/test.css"/>
</page-specification>

Home_zh_CN.properties

menuText=首頁
title=首頁
actionListener.logout.menuText=註銷

welcome=歡迎
welcomeDetail=歡迎使用web病歷管理系統,這是一套基於網絡的B/S結構的病歷管理服務系統,功能新穎,界面友好,歡迎使用。


Home.properties

title=Home
menuText=Home
actionListener.logout.menuText=Logout

welcome=Welcome
welcomeDetail=Welcome to use Web Document Manage System.This system based on B/S network structure, it provides internal documents' management for your company. It's document directory organized as that: a department as a unit, departments can share documents each other. Meanwhile, it provides detailed document version control.   


Home.html

<span jwcid="border">
<table align="center" width="100%" height="100">
<tr>
<!-- ========================== START MID COL ======================= -->
<td VALIGN="TOP" width='100%'>
<table width='100%' cellpadding='0' cellspacing='0' border='0'>
<tr>
<td width='10'><img src='home/images/pixel.gif' width='10' height='1' alt='-'></td>
<td width='100%'><img src='home/images/welcome_head_icon.gif' ALIGN="BOTTOM" WIDTH="16" HEIGHT="16"  ALT="Welcome!">&nbsp;<font class='h2' style='color: #080c77;'><span key="welcome">Welcome</span></font></td>
<td width='10'><img src='home/images/pixel.gif' width='10' height='1' alt='-'></td>
</tr>
<tr>
<td height='5' colspan='3' valign='top'><img src='home/images/head_home_line.gif' width='254' height='5' alt='-'></td>
</tr>
<tr>
<td height='5' colspan='3' bgcolor='#ffffff'><img src='home/images/pixel.gif' width='1' height='5' alt='-'></td>
</tr>
<tr>
<td width='10' bgcolor='#ffffff'><img src='home/images/pixel.gif' width='10' height='1' alt='-'></td>
<td width='100%' bgcolor='#ffffff'>
<span key="welcomeDetail">Welcome to use Web Document Manage System.This system based on B/S network structure, it provides internal documents' management for your company. It's document directory organized as that: a department as a unit, departments can share documents each other. Meanwhile, it provides detailed document version control.</span>
</td>
<td width='10' bgcolor='#ffffff'><img src='home/images/pixel.gif' width='10' height='1' alt='-'></td>
</tr>
<tr>
<td height='5' colspan='3' bgcolor='#ffffff'><img src='home/images/pixel.gif' width='1' height='5' alt='-'></td>
</tr>
</table>
            </td>
        </tr>
    </table> 
</span>


對於頁面的開發,有幾個值得討論的問題,
一 框架化的頁面怎麼實現
   這個很簡單,你只要開發一個控件,預先定義好一個顯示框架,我就是這麼做的,我開發了一個叫Border的控件,然後把變動的顯示作爲Border可變的內容輸出。
你看我的 Home.html,它被<span jwcid="border">**</span>所包圍,我的Border控件負責
顯示每頁確定的內容,變動的則只在Border的一個預定的區域顯示。

二  國際化怎麼辦
    Tapestry國際化非常簡單,例如英文我要顯示welcome,中文顯示歡迎
只須這樣就行:
    <span key="welcome">Welcome</span>(中間的Welcome是預覽hmtl用的沒有
別的意義),然後你在home.properties設定key-value對爲: welcome=Welcome
在Home_zh_CN.properties設定爲: welcome=歡迎,不過最後打包時你要將你的
Home_zh_CN.properties用jdk的bin目錄下的native2ascii命令轉化一下,不然會
顯示成亂碼。

我們來分析一下Home.page

<page-specification class="com.ht.home.Home">
聲明本頁對應的class爲com.ht.home.Home
<component id="border" type="common:Border">
<message-binding name="title" key="title"/>
<binding name="styleSheet" expression="assets.test"/>
</component>
聲明並配置一個Border類型的控件
<message-binding name="title" key="title"/>
指定了本頁的title
binding name="styleSheet" expression="assets.test"/>
指定了本頁應用的StyleSheet資源

<context-asset name="$template" path="home/Home.html"/>
指定了Home頁的模版爲home/Home.html
<context-asset name="menuIcon" path="home/images/homeIcon.gif"/>
聲明一個context-asset(圖標)
<context-asset name="test" path="home/css/test.css"/>
聲明一個context-asset(Stylesheet),被上面的Border控件引用


最後講講劃分子模塊的問題:

比如我的Web Application包含兩個子模快home, patientrecord,
home對應的包爲com.ht.home,絕對路徑爲F:/myproject/TapestryExmaple/src/
com/ht/home,對應的context目錄爲home,絕對路徑爲F:/myproject/
TapestryExmaple/context/home

patientrecord對應的包爲com.ht.patientrecord,絕對路徑爲F:/myproject/TapestryExmaple/src/com/ht/patientrecord,
對應的context目錄爲patientrecord,絕對路徑爲F:/myproject/
TapestryExmaple/context/patientrecord


home模塊下的頁面有
Home,Register,Login,About,PaitentRecordException,SecurityException

patientrecord模塊下的頁面有

Browser,Create,AddTreatment,AddExamination,AddOperation,AddOperationVisit,AddOperationVisit,AddComment

我需要將這些頁面歸檔,所以對應home子模塊有Home.libray,對應於patientrecord
有PatientRecord.library

Home.library的位於com.ht.home包下,
PatientRecord.library位於com.ht.patientrecord包下

他們分別爲
Home.library

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE library-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>

<library-specification>
<!-- Library Section-->
<library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/>
<library id="common" specification-path="/com/ht/components/Common.library"/>
<!-- Add more libraries here.-->

<!-- End of Library Section-->

<page name="Home" specification-path="Home.page"/>
<page name="Register" specification-path="Register.page"/>
<page name="Login" specification-path="Login.page"/>
<page name="About" specification-path="About.page"/>
<page name="PaitentRecordException" specification-path="PRException.page"/>
<page name="SecurityException" specification-path="SecurityExceptionPage.page"/>
</library-specification>

PatientRecord.library
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE library-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>

<library-specification>
<!-- Library Section-->
<library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/>
<library id="common" specification-path="/com/ht/components/Common.library"/>
<!-- Add more libraries here.-->

<!-- End of Library Section-->

<page name="Browser" specification-path="Browser.page"/>
<page name="Create"  specification-path="Create.page"/>
<page name="AddTreatment" specification-path="AddTreatment.page"/>
<page name="AddExamination" specification-path="AddExamination.page"/>
<page name="AddOperation" specification-path="AddOperation.page"/>
<page name="AddOperationVisit" specification-path="AddOperationVisit.page"/>
<page name="AddComment" specification-path="AddComment.page"/>

</library-specification>

最後我們再看一下patientrecord.application這個Tapestry Web 應用核心配置文件:

patientrecord.application

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "Tapestry_3_0.dtd">http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd>

<application name="Patient Record System" engine-class="com.ht.web.PatientRecordEngine">
  <property name="org.apache.tapestry.visit-class" value="com.ht.web.VisitorState"/>

  <property name="com.ht.home-page" value="home:Home"/>

  <!--<property name="com.ht.exception-page" value="home:PaitentRecordException"/>--> 
  <property name="com.ht.security-exception-page" value="home:SecurityExceptionPage"/>

  <!--Overrided the Home Service to let us to decide which page will be the home page-->
  <service name="home" class="com.ht.web.HomeService"/>
 
  <library id="home" specification-path="/com/ht/home/Home.library"/>
  <library id="patientrecord" specification-path="/com/ht/patientrecord/PatientRecord.library"/>
</application>

看看最後兩行
<library id="home" specification-path="/com/ht/home/Home.library"/>
  <library id="patientrecord" specification-path="/com/ht/patientrecord/PatientRecord.library"/>

我們把那兩個libary文件包含進來了,分別對應id爲home, patientrecord
,我們要在程序裏激活Home頁,則只需
  得一個IRequestCycle對象cycle
  cycle.activate("home:Home");

注意“home:Home“,前一個home是library name,後一個是Page name.這是Tapestry
自定義的名字訪問法則。

以上,是我開發Tapestry Web Application的一點心得體會,歡迎討論批評.

msn:[email protected]
QQ:15520929

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章