定制组件
在基于组件的框架中,重用自定义组件是最主要、最强大的功能之一。你可以描述自己的组件,这些组件可以是整个页面,也可以是较小的面板,甚至是单独的一个 HTML 元素。通过组件继承,可以很自然地设计组件模板,并且不会产生什么问题。一旦创建了这些模块,你可以根据需要将其多次插入应用程序中的任何位置。Tapestry 和 Wicket 对管理组件的重用没有任何限制,但它们的方式各有不同。
当自定义组件可以应用到各种应用程序时,将变得真正可重用。Wicket 仅仅通过创建一个包含组件类和标记模板的 JAR 归档就可以进行打包。把归档自动放入应用程序的类路径中将使组件变得可用。Tapestry 需要另外一些步骤来定义一个自定义组件库 — JAR 归档应该包含一个带有库规范元素的 XML 描述符。使用这个库的应用程序应该在该应用程序的配置文件中指定这个库。
可重用组件的一个最棒的应用是提供了普通导航面板、页眉和页脚、说明栏等内容的页面模板。接下来的模块示例是一个显示主页链接、当前登录用户的名称和 Logout 按钮的组件。
在 Tapestry 中,模板组件规范如清单 28, 29,和 30 所示:
清单 28. Tapestry 的组件模板规范
allow-informal-parameters="no"
class="com.ibm.cit.tvw.tapestry.component.Template">
<!--HTML head -->
<asset name="stylesheet" path="/style.css" />
<parameter name="pageTitle" default-value="literal:Todolist Application" />
<component id="shell" type="Shell">
<binding name="stylesheet" value="assets.stylesheet" />
<binding name="title" value="ognl:pageTitle" />
</component>
<!-- HTML body -->
<component id="body" type="Body" />
<!-- The name of the currently logged user -->
<component id="user" type="Insert">
<binding name="value" value="ognl:currentUser"/>
</component>
<!-- The home page -->
<component id="homeLink" type="PageLink">
<binding name="page" value="literal:ListActionItems" />
</component>
<!-- User Profile page -->
<component id="profileLink" type="DirectLink">
<binding name="listener" value="listener:onEditUserProfile"/>
</component>
<!-- Logout link -->
<component id="logoutLink" type="ServiceLink">
<binding name="service"
value="ognl:@org.apache.tapestry.Tapestry@RESTART_SERVICE"/>
</component>
<!-- Page content -->
<component id="pageContent" type="RenderBody"/>
</component-specification>
清单 29. Tapestry 的组件模板规范 Java 类
public String getCurrentUser() {
return getPage().getRequestCycle().getInfrastructure()
.getRequest().getUserPrincipal();
}
}
清单 30. Tapestry 的组件模板规范 HTML 标记
<body jwcid="body">
<div id="top">
<div id="header">
<a jwcid="homeLink" class="homelink">Action Items Sample Application</a>
Current user: <span jwcid="user">Davy Jones</span>
<a jwcid="logoutLink">Logout</a></span>
</div>
<div id="page-content">
<span jwcid="pageContent">This is a page content.</span>
</div>
</div>
</body>
</html>
使用模板的其他页面如清单 31 所示,这是 ViewActionItem 页面的一个例子。
清单 31. ViewActionItem 示例
<component id="template" type="Template">
<binding name="pageTitle" value="literal:View Action Item"/>
</component>
...
</page-specification>
清单 32. HTML 标记中的 ViewActionItem
<!-- Page content -->
...
</span>
在 Wicket 中,模板被表示为一个基本页面,如清单 33 和 34 所示:
清单 33. Wicket 模板
private String title;
public TemplatePage() {
add(new Label("title", new PropertyModel(this, "title")));
add(new BookmarkablePageLink("homeLink", getApplication().getHomePage()));
add(new Label("user", ((WebRequest) getRequest()).getHttpServletRequest()
.getUserPrincipal().getName()));
add(new Link("logoutLink") {
public void onClick() {
getSession().invalidate();
getRequestCycle().setResponsePage(getHomePage());
getRequestCycle().setRedirect(true);
}
});
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
清单 34. 作为 HTML 标记的 Wicket 模板
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:wicket="http://wicket.apache.org/">
<head>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<link rel="stylesheet" type="text/css" href="style.css" />
<title wicket:id="title">Sample Page Title</title>
</head>
<body>
<div id="top">
<div id="header">
<a wicket:id="homeLink" class="homelink">Action Items Sample Application</a>
Current user: <span wicket:id="user">Davy Jones</span>
<input type="button" class="button" wicket:id="logoutLink" value="Logout" /></span>
</div>
<div id="page-content">
<wicket:child />
</div>
</div>
</body>
</html>
应用这个模板的子页面应该继承模板页面,如清单 35 和 36 所示:
清单 35. 继承模板页面
public ViewActionItem() {
setTitle("View Action Item");
...
}
}
清单 36. 继承作为 HTML 标记的 Wicket 模板
<head></head>
<body>
<wicket:extend>
<!-- Page content -->
...
</wicket:extend>
</body>
</html>