天天看點

Tapestry

Tapestry

1)概述:

Tapestry 是一個全面web application 架構,是使用JAVA 寫的。

Tapestry 不是一個application server,Tapestry 是一個使用在application server

中的架構。

Tapestry 不是一個application,Tapestry 是一個用來建立web application 的框

架。

Tapestry 不是JSP 的一種使用方式,Tapestry 和JSP 隻能夠選擇一種。

Tapestry不是一個腳本環境,Tapestry使用一種元件對象模式(component object

model),這并不是一種簡單的腳本,而是用于生成高動态性高互交性的web頁

面。

Tapestry基于Java Servlet API version 2.2,相容于JDK 1.2以上版本,Tapestry

通過變換多樣的元件模式,将一個web application分離為一個聯合元件。每一個

元件都擁有其特殊的責任用于顯示web頁面或者響應HTML請求。

2)Tapestry工作原理

Tapestry應用程式由幾個頁面組成,這些頁面都是由獨立的,可重複使用,

可配置的元件組成。

下面是用于描述Tapestry應用程式的基本術語:

1,頁面(Page):應用程式由一堆命名唯一的頁面組成,每個頁面有一個模

闆和若幹元件;

2,模闆(Template):一個用于頁面(或一個元件)的HTML模闆。Tapestry

中,一個模闆包括基本的HTML markup,以及一些用于标記元件的特殊

屬性的标簽。

3,元件(Component):用于Tapestry頁面的可重複使用的對象。當一個頁

面表現時,或者頁面中的一個連結被觸發時,元件産生相應的HTML代碼。

多個元件也可以用來構成一個新的元件。

4,參數(Parameter):元件擁有一些參數,用于元件屬性與頁面屬性之間的

連接配接。元件通常讀取自己的參數,但是一些元件(與HTML forms相關)

能夠更新自己的參數,并且更新與參數綁定的頁面屬性。

3)Tapestry與MVC

Tapestry元件扮演着控制器Controller的角色,是模式層(Model)中

pure-domain objects和包含有元件的HTML模闆之間的媒介。大多數情況下,

這種方式應用于頁面(頁面也是Tapestry元件),但是在某些情況中,一個組

件擁有自己的模闆,包含着更多的元件,并且支援與使用者的互交。

頁面通過配置一系列屬性表達式(Property expressions)連接配接模式層和表

現層。屬性表達式使用另外一種開源架構OGNL(Object Graph Navigation

Language)。OGNL的開源工程(project)獨立于Tapestry,但是在Tapestry

中起很重要的作用。OGNL主要的目的在于讀取和更新對象的Java Bean屬性。

4)Tapestry classes

Tapestry架構由400多個類和接口組成,但是建構一個Tapestry應用程式僅

需要少數幾個類,接口和方法。

Tapestry

1,兩個關鍵接口:IComponent和IPage

這兩個接口分别用于定義Tapestry元件和頁面。所有的Tapestry代碼都是繼承

于接口,而不是繼承于實作。是以IComponect一向被用于傳遞參數或者傳回值,

而不是使用其實作AbstractComponent。AbstractComponent類是一個基礎類,用來

實作元件。AbstractComponect是一個抽象類,定義卻不實作renderComponect()

方法。它的子類實作這個方法,使用JAVA代碼生成所有HTML。

BaseComponect繼承AbstractComponent,增加初始化邏輯以便定位和讀取一

個模闆。是以大多數自定義元件繼承BaseComponent。

在Tapestry中,頁面作為一個特殊的元件,Ipage繼承Icomponent和BasePage

繼承BaseComponent。是以當要建立新頁面的時候,繼承BasePage。

2,三個很有用的接口:IRequestCycle,IMarkupWriter,和IEngine

大多數Tapestry頁面群組件直接使用這三個接口的引用。

IRequestCycle:一個request cycle儲存着目前請求的資訊。它跟蹤有關的活動

頁面,用于響應response。在特殊事件中,它通常用來通路Servlet API 對象

(HttpServletRequest, HttpSession, HttpServletResponse)。

IMarkupWriter:一個markup複寫器用來生成HTML輸出,當一個頁面收到一

個響應(response)的時候。它的運作很像java.io.PrintWriter,但是它包含了其它有

用的方法,以生成markup輸出(包括XML-style元素和屬性)。

IEngine:這是引擎是一個重要對象,用于處理Tapestry應用程式挂起。最初,

這個引擎用來維護伺服器端的狀态。但是它也可以作為一個處理Tapestry内部子

系統的網關。

5)關于morkup和domain object。

1,mockup:page mockups是靜态HTML頁面,用于表現這些動态頁面在應用

程式運作時的樣子。也就是指在HTML模闆中,将會在應用程式運作時被

Tapestry元件替換掉的那部分舊HTML代碼。Tapestry元件是動态的,當對

HTML模闆做美工時,markup的存在将會提供很大的友善。這樣,Tapestry

程式員可以完全與美勞工員各負其責。

2,domain object:應用程式的運作,最終取決于整個團隊中JAVA部分的構

架師和程式員。在大多數應用程式中,怎樣連接配接使用者接口和domain objects成

為一個問題。Domain objects是中間層對象,是應用層,在整個應用程式中,

它們是全局對象,将資料儲存到資料庫,或者實作你的特殊業務。通常,我

們涉及到這些問題:這些對象中儲存着什麼資訊,怎樣将不同的對象關聯在

一起,以及它們怎樣讀取資料,或着将資料儲存到資料庫。

Tapestry

servlet作為控制器,收到請求。定位并更新domain objects,讀取或更新

資料庫資料。控制器servlet選擇一個表現層(JSP)表現響應。表現層繪制

domain objects并最終将響應頁面發送用戶端。

6)頁面結構:

在Tapestry應用程式中,一個頁面(page)由一個HTML子產品,一個頁面

規範(page specification),和一個JAVA頁面類(page class)構成。

每個Tapestry頁面有一個特殊的唯一的名稱。頁面名稱被用來定位頁面規

範和HTML模闆。頁面規範的一部分用來執行個體化JAVA類,這部分稱為頁面類

(page class),包括指定應用程式中的一些特殊屬性和方法。

表現(rendering)頁面的第一步是執行個體化頁面。Tapestry架構讀取頁面規

範和HTML模闆并生成頁面執行個體。一個Tapestry頁面不是一個單一的對象。頁

面對象是樹對象的根對象,這些對象包括頁面模闆中的元件,HTML模闆中

的内容,以及一些用來連接配接分散區域的對象。

最簡單的頁面:

1 一個HTML模闆;

2 一個頁面規範;

該規範使用XML,必須聲明:

<?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="hangman1.Home"/>

3 一個頁面類;

該類必須繼承BasePage類。

Public hangman1 extends BasePage {

}

隻要HTML模闆中使用Tapestry,就必須聲明頁面規範和頁面類,即便頁

面規範和頁面類都沒有任何屬性或方法,變量。

7)關于屬性标簽:

a) jwcid屬性:(Java Web Component ID)在模闆中用來指定元件。

b) <span>标簽:HTML<span>标簽是一個用來包容text和elements的容器,

其本身并不能顯示任何内容,僅僅是作為一個stylesheet協助對頁面顯示

的控制。

c) @記号:用來标明一個隐式元件。

8)監聽方法(Listener method):

監聽方法是普通的執行個體方法,其簽名為:

public void method(IRequestCycle cycle)

這個方法必須是public,return void,并且隻有一個類型為IRequestCycle

的參數。所有的頁面群組件從AbstractComponent基礎類中繼承一個listeners

參數。listeners參數包含一個嵌套參數,以便類中每一個監聽方法得以執行。

這裡有一個接口:IActionListener,以及一些JAVA的反射機制,用來連接配接組

件和頁面的監聽方法。

一個類中可以有多個監聽方法,每一個監聽方法必須有一個不重複的名

字,從父類繼承的監聽方法同樣可以通過listeners參數使用。

9)Visit對象

Visit對象是一個應用程式空間,用來儲存應用程式邏輯和資料。這個對

象能被應用程式中所有的頁面群組件通路,并且包含WEB應用程式中某一個

用戶端的特殊資訊。一個單一Visit對象執行個體被應用程式中所有的頁面共享。

該對象類似HttpSession在典型servlet應用程式中扮演的角色。實際上,Visit

對象最終作為一個HttpSession屬性被儲存。

為了在應用程式中使用一些通用資料,Tapestry認可Visit對象。Tapestry

并不知道也不關心Visit對象的類型。在架構中也沒有定義特殊的Visit類,每

一個應用程式自己定義Visit類。頁面方法通路Visit對象時并不會指定具體的

類型:

public Object getVisit();

注意強制轉換類型:

Visit visit = (Visit)getVisit();

Visit對象是架構自動生成的,在第一次運作時被引用。你必須配置

Tapestry提供執行個體化,一旦Visit對象生成,就将會持久化儲存在

HttpSession中。

10) PageRenderListener接口

這個接口用來通知頁面執行個體,當頁面第一次運作時,應該首先執行

pageBeginRender()方法。這個方法的簽名為:

public void pageBeginRender(PageEvent event)如:

11)屬性指定機制(specified properties)

屬性指定就是由Tapestry自動生成典型的JavaBean屬性。在代碼中,你定義

抽象方法用來讀取和更新屬性,你必須隻定義需要使用的方法。Tapestry自己會

生成一個子類來實作你的方法。你甚至不用聲明變量,隻需要在頁面規範中指明

類型即可。如:

<page-specification class="examples.Login">

<property-specification name="message"

type="java.lang.String"/>

<property-specification name="userName"

type="java.lang.String"/>

<property-specification name="password"

type="java.lang.String"/>

</page-specification>

Tapestry會自動建立一個子類來繼承Login類,并實作以JavaBean方式實作變

量。這樣做有三個好處:

第一:減輕程式員負擔;

第二:Tapestry可以確定自動重置屬性,當請求失效過期的時候。

第三:屬性可以被定義為persistent。

這種機制與EJB的container-managed persistence(CMP)一樣。

12) 元件的分類:

按照元件的使用方式:

a) 隐式元件:元件類型和其結構直接在HTML模闆中申明的元件。通常,

Tapestry已經定義好的元件都是以隐式元件的方式使用。

b) 顯示元件:其元件類型和結構儲存在頁面規範中。通常,自定義的元件都

是以顯示元件的方式使用。

我個人傾向于将元件按照其工作方式分為三類:

1)容器元件:指元件中可以包含其它元件的元件。

目前接觸到的容器元件有:Shell,Body,Conditional和Form四

種。其中最簡單的是:Shell和Body,它們僅僅是用在HTML模

闆的開頭,用來聲明<html>,<head>和<title>元素和CSS規範。

最複雜的是Form容器元件,這個元件可以包容若幹元件。而這

些被包容的元件有根據它們原理上的不同,分為面向元素元件

和面向任務元件兩大類。而Conditional元件根據使用情況,分

為兩種,較Form簡單。

2)普通元件:指容器元件以外的Tapestry定義元件,可以獨立于容器元件單

獨運作的元件。

3)自定義元件:

上面這種分類純粹是我自己的了解,并不是絕對。實際上Tapestry的元件邏輯

非常複雜,再加上OGNL表達式和屬性指定機制。甚至使得寫注釋都變得很

不容易。是以在閱讀别人寫的Tapestry代碼的時候,難免有霧裡看花,尤抱琵

琶半遮面的感覺。我的看法是,假如有看不懂的代碼,暫時死記硬背先。因

為Tapestry是一個功能強大的架構,其元件的可重複使用(reusable)能力非

常強。通常例子程式的頁面類中的某一個方法,就已經能夠解決與此方法相

關的一系列問題。

13) 普通元件:

a) DirectLink元件:

用來生成一個從應用程式中回報回來的特殊類型。這個元件是

Tapestry中兩種主要互交産生方式之一,另外一種是user-submitted forms。

DirectLink元件表現為一個HTML<a>元素,用來提供一個URL,當使用者點

擊時,觸發頁面中一個特定的監聽方法。如:

<a href="#" target="_blank" rel="external nofollow" jwcid="@DirectLink"

listener="ognl:listeners.start">

<img src="images/start.png" width="250"

height="23"

alt="Start"/></a>

實際運作原理為:

Tapestry

元件容器通過調用RenderComponent()方法,将元件表現為Java代碼。而

renderBody()方法是DirectLink元件從基礎類AbstractComponent中繼承的。

DirectLink元件通過renderComponent()方法來調用renderBody()方法,來表

現元件内容(被DirectLink的<a>和</a>标簽包圍的靜态<img>标簽)。

DirectLink元件有幾個參數以及一個請求(listener),這個監聽參數用來

找到監聽方法,并且一旦使用者點選連結通路WEB浏覽器,監聽方法就會

執行。

b)Image元件

Tapestry标準元件,用于插入<img>标簽,通過image參數生成标簽src

的屬性。标簽alt用來顯示圖檔名稱。如:

<IMG jwcid="@Image"

alt="ognl:visit.game.incorrectGuessesLeft"

image="ognl:digitImage"

height="36"

src="images/Chalkboard_3x8.png"

width="36" />

這裡需要介紹一下Asset:

Asset被用通路靜态檔案如images和stylesheets。Image元件的image參數

必須是asset object而不是String,并通過getAsset()方法作為一個object傳回。

如:

public IAsset getDigitImage()

{

Visit visit = (Visit)getVisit();

int guessesLeft =

visit.getGame().getIncorrectGuessesLeft();

return getAsset("digit" + guessesLeft);

}

Asset對象執行Iasset接口,getAsset()方法從AbstractComponent基礎類中繼

承,能夠通路在頁面規範中标示為<context-asset>的元素。如:

<context-asset name="digit0"

path="images/Chalkboard_1x7.png"/>

<context-asset name="digit1"

path="images/Chalkboard_1x8.png"/>

<context-asset name="digit2"

path="images/Chalkboard_2x7.png"/>

<context-asset name="digit3"

path="images/Chalkboard_2x8.png"/>

<context-asset name="digit4"

path="images/Chalkboard_3x7.png"/>

<context-asset name="digit5"

path="images/Chalkboard_3x8.png"/>

使用Asset來定義頁面規範:

c) Foreach元件

Foreach是一個循環元件,它周遊source參數,并在表現其内容前更新

value參數。這是Tapestry元件參數的至關重要特性:将一個屬性與一個元件

參數綁定,元件不僅讀取被綁定的屬性,而且更新屬性。

Foreach元件使用<span>标簽,當其表現(render)時,并不直接生成

任何HTML代碼。它僅僅是将内容(Text)和包含的元件重複表現。

d)Insert元件

這個元件很簡單,使用起來很像JSP中的out.print()。隻需要指定

value參數即可。

10)Form元件

現在讨論在Tapestry裡最能激動人心,也最能讓人頭暈的元件:Form。

Form在HTML裡與在Tapestry裡有很大的聯系,但是Tapestry裡Form元件邏輯

和運作方式遠比在HTML中複雜。對于HTML中Form的運作原理,我就不多說了,

僅僅列張表,以友善與Tapestry對比。

Tapestry

Tapestry引進一個全新的概念:task-oriented component面向任務元件。

Tapestry将原始的Form稱為element-oriented component面向元素元件。但是

Tapestry為了銜接HTML,并沒有完全抛棄面向元素元件。

下面是HTML與Tapestry互相對應的清單:

Form元件與一個監聽方法綁定。Tapestry為Form中的每一個元件提供一個

ID,如同原來的name參數,用來确定各種參數值。通過OGNL來讀取和更新屬性,

是以程式員隻需要關心OGNL。

Form元件的内部運作結構為:

Tapestry

name=”service”,name=”sp”和name=”Form0”是Tapestry自動添加的。

一旦form被submitted,Tapestry必須完成一些與非Tapestry應用程式一樣的工

作。

繼續閱讀