一個 JWC (Java Web Component) 包含:
jwcid 屬性標記元件位置BasePage 或 BaseComponent,提供邏輯與資料<html>
<head><title>Welcome to Tapestry!</title></head>
<body>
Hello <span jwcid="user">User Name</span>! Welcome to Tapestry!
</body></html>
jwcid="user" 表示此處插入名為 user 的元件。<span> 不影響版面,利於美工使用 Dreamweaver/FrontPage。
<page-specification class="demo.Home">
<component id="user" type="Insert">
<binding name="value" expression="userName"/>
</component>
<context-asset name="$template" path="Home.html"/>
</page-specification>
id 對應模板 jwcidtype="Insert" 為內建元件,將值插入模板expression="userName" 透過 OGNL 綁定 Java 類的 userName 屬性package demo;
import org.apache.tapestry.html.BasePage;
public class Home extends BasePage {
private String userName = "Jack";
public String getUserName() { return this.userName; }
}
實際執行時,OGNL 讀取 getUserName() 回傳值,更新 Insert 元件的 value,最終輸出 "Jack"。
<application name="Tapestry Illustration 1">
<page name="Home" specification-path="Home.page"/>
</application>
<servlet>
<servlet-name>Welcome</servlet-name>
<servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Welcome</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>
訪問 https://localhost:8080/Welcome/app 即見成果。
<html jwcid="@Shell" title="Welcome Page">
<body jwcid="@Body">
<form jwcid="@Form" listener="ognl:listeners.submit">
Customer Name: <input jwcid="custName" type="text"/><br/>
Date-of-Birth: <input jwcid="dob" type="text" format="MMM dd, yyyy"/><br/>
<input type="submit" value="Submit"/>
</form>
</body></html>
@Shell, @Body, @Form 為隱式元件,無需在 .page 定義,參數直接寫在模板。
<page-specification class="demo.Welcome">
<property-specification name="custName" type="java.lang.String"/>
<property-specification name="dob" type="java.util.Date"/>
<component id="custName" type="TextField">
<binding name="value" expression="custName"/>
</component>
<component id="dob" type="DatePicker">
<binding name="value" expression="dob"/>
</component>
</page-specification>
property-specification 讓 Tapestry 自動產生 getter/setter,Java 類只需宣告 abstract 方法DatePicker 核心元件自動產生彈出式日期選擇 UI,零 JavaScript 成本public abstract class Welcome extends BasePage {
public abstract void setCustName(String custName);
public abstract void setDob(Date dob);
public abstract String getCustName();
public abstract Date getDob();
public void submit(IRequestCycle cycle) {
if (getCustName() != null && !getCustName().trim().equals("") && getDob() != null) {
Welcome welcome = (Welcome) cycle.getPage("Welcome");
welcome.setCustName(getCustName());
welcome.setDob(getDob());
cycle.activate(welcome); // 頁面跳轉
}
}
}
listener="ognl:listeners.submit" 綁定 submit 方法,IRequestCycle 控制頁面流程。
Tapestry 以元件化思維重塑 Web 開發:HTML 模板純淨、XML 定義清晰、Java 類專注邏輯。內建豐富元件庫(含 DatePicker、Foreach 等控制元件),支援自訂元件繼承組合。開源社群活躍,原始碼可讀性高,適合追求可維護性、團隊協作與豐富 UI 的企業級專案。