Tapestry 模板
让我们考虑本节中的 Tapestry XML 模板。 XML 模板是格式良好的 XML 文档。页面的表示(用户界面)层是 XML 模板。除了下面给出的项目之外,XML 模板还具有正常的 HTML 标记-
Tapestry Namespace
Expansions
Elements
Components
现在让我们详细讨论它们。
Tapestry 命名空间
Tapestry 命名空间只不过是 XML 命名空间。命名空间应该在模板的根元素中定义。它用于在模板中包含 Tapestry 组件和组件相关信息。最常用的命名空间如下-
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd" — 用于标识 Tapestry 的元素、组件和属性。
xmlns:p = "tapestry:parameter" — 用于将任意代码块传递给组件。
Tapestry 命名空间的示例如下-
<html xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p = "tapestry:parameter">
<head>
<title>Hello World Page</title>
</head>
<body>
<h1>Hello World</h1>
<t:eventlink page = "Index">refresh page</t:eventlink>
</body>
</html>
扩展
扩展是在页面呈现阶段动态更改 XML 模板的简单而有效的方法。扩展使用 ${
} 语法。有多种表达方式s 在 XML 模板中的扩展。让我们看看一些最常用的选项-
属性拓展
它映射了在相应的 Page 类中定义的属性。它遵循 Java Bean 规范在 Java 类中的属性定义。通过忽略属性名称的大小写,它更进了一步。让我们使用属性扩展来更改"Hello World"示例。以下代码块是修改后的 Page 类。
package com.example.MyFirstApplication.pages;
public class HelloWorld {
// Java Bean Property
public String getName {
return "World!";
}
}
然后,更改相应的 XML 模板,如下所示。
<html xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<head>
<title>Hello World Page</title>
</head>
<body>
<!--expansion-->
<h1>Hello ${name}</h1>
</body>
</html>
这里,我们在 Page 类中将
name 定义为
Java Bean 属性,并使用扩展
${name}.
消息扩展
每个页面类在资源文件夹中可能有也可能没有关联的属性文件-
«page_name».properties。属性文件是纯文本文件,每行只有一个键/值对(消息)。让我们在 –
处为 HelloWorld 页面创建一个属性文件
"/src/main/resources/com/example/MyFirstApplication/pages/helloworld.properties"并添加"问候"消息。
Greeting 消息可以在 XML 模板中用作
${message:greeting}
<html xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<head>
<title>Hello World Page</title>
</head>
<body>
<!--expansion-->
<h1>${message:greeting} ${name}</h1>
</body>
</html>
元素
Tapestry 有一小组要在 XML 模板中使用的元素。元素是在 Tapestry 命名空间下定义的预定义标签-
https://tapestry.apache.org/schema/tapestry_5_4.xsd
每个元素都是为特定目的而创建的。可用的挂毯元素如下-
<t:body>
当两个组件嵌套时,父组件的模板可能要包装子组件的模板。
元素在这种情况下很有用。
的用途之一是在模板布局中。
一般而言,Web 应用程序的用户界面将具有通用页眉、页脚、菜单等。这些通用项在 XML 模板中定义,称为模板布局或布局组件。在 Tapestry 中,它需要由应用程序开发人员创建。布局组件只是另一个组件,位于 components 文件夹下,其路径如下-
src/main/«java|resources»/«package_name»/components。
让我们创建一个名为
MyCustomLayout 的简单布局组件。 MyCustomLayout 的代码如下-
<!DOCTYPE html>
<html xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<head>
<meta charset = "UTF-8" />
<title>${title}</title>
</head>
<body>
<div>Sample Web Application</div>
<h1>${title}</h1>
<t:body/>
<div>(C) 2016 Lidihuo.</div>
</body>
</html>
package com.example.MyFirstApplication.components;
import org.apache.tapestry5.*;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.BindingConstants;
public class MyCustomLayout {
@Property
@Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
private String title;
}
在 MyCustomLayout 组件类中,我们声明了一个标题字段,并通过使用注释将其强制化。现在,更改 HelloWorld.html 模板以使用我们的自定义布局,如下面的代码块所示。
<html>
t:type = "mycustomlayout" title = "Hello World Test page"
xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<h1>${message:greeting} ${name}</h1>
</html>
我们在这里可以看到 XML 模板没有 head 和 body 标签。 Tapestry 将从布局组件中收集这些详细信息,并且布局组件的
将被 HelloWorld 模板替换。一切都完成后,Tapestry 将发出如下指定的类似标记-
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8" />
<title>Hello World Test Page</title>
</head>
<body>
<div>Sample Web Application</div>
<h1>Hello World Test Page</h1>
<h1>Hello World!</h1>
<div>(C) 2016 Lidihuo.</div>
</body>
</html>
布局可以嵌套。例如,我们可以通过包含管理功能来扩展我们的自定义布局,并将其用于管理部分,如下所述。
<html t:type = "MyCommonLayout"
xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<div><!--Admin related items--><div>
<t:body/>
</html>
<t:container>
<t:container> 是顶级元素,包括一个挂毯命名空间。这用于指定组件的动态部分。
例如,网格组件可能需要一个模板来确定如何在 HTML 表格中呈现其行-tr(和列 td)。
<t:container xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<td>${name}</td>
<td>${age}</td>
</t:container>
<t:block>
<t:block> 是模板中动态部分的占位符。通常,块元素不会渲染。只是,模板中定义的组件使用块元素。组件将数据动态注入块元素并呈现它。一种流行的用例是
AJAX。
块元素为要渲染的动态数据提供准确的位置和标记。每个块元素都应该有一个对应的 Java 属性。只有这样它才能动态呈现。块元素的 id 应遵循 Java 变量标识符规则。下面提供了部分示例。
@Inject
private Block block;
<html t:type = "mycustomlayout" title = "block example"
xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd"
xmlns:p = "tapestry:parameter">
<h1>${title}</h1>
<!--
...
...
-->
<t:block t:id = "block">
<h2>Highly dynamic section</h2>
I'v been updated through AJAX call
The current time is: <strong>${currentTime}</strong>
</t:block>
<!--
...
...
-->
</html>
<t:content>
<t:content> 元素用于指定模板的实际内容。通常,所有标记都被视为模板的一部分。如果指定了
,则只会考虑其中的标记。设计人员使用此功能来设计没有布局组件的页面。
<t:remove>
<t:remove>与内容元素正好相反。 remove 元素内的标记不被视为模板的一部分。它可用于仅服务器评论和设计目的。
Assets
资产是静态资源文件,例如样式表、图像和 JavaScript 文件。通常,资产放置在Web应用程序根目录
/src/main/webapp。
<head>
<link href = "/css/site.css" rel = "stylesheet" type = "text/css"/>
Tapestry 还将存储在
Java 类路径 中的文件视为资产。 Tapestry 提供高级选项,通过扩展选项将资产包含到模板中。
Context-在网络上下文中获取可用资产的选项。
<img src = "${context:image/tapestry_banner.gif}" alt = "Banner"/>
asset-组件通常将自己的资产与 Java 类一起存储在 jar 文件中。从 Tapestry 5.4 开始,在类路径中存储资产的标准路径是
META-INF/assets。对于图书馆,存储资产的标准路径是
META-INF/assets/«library_name»/。 asset: 还可以调用
context: 扩展以从 web 上下文中获取资产。
<img src = "${asset:context:image/tapestry_banner.gif}" alt = "Banner"/>
资产可以使用注入和路径注释注入到 Tapestry 页面或组件中。 Path注解的参数是资产的相对路径。
@Inject
@Path("images/edit.png")
private Asset icon;
Path 参数还可以包含在
AppModule.java 部分中定义的 Tapestry 符号。
例如,我们可以使用值 context:skins/basic 定义一个符号 skin.root 并使用它,如下所示-
@Inject
@Path("${skin.root}/style.css")
private Asset style;
本地化
通过挂毯包含资源提供了额外的功能。其中一项功能是"本地化"。Tapestry 将检查当前的语言环境并包含适当的资源。
例如,如果当前语言环境设置为
de,则将包含
edit_de.png 而不是 edit.png。
CSS
Tapestry 具有内置的样式表支持。 Tapestry 将注入
tapestry.css 作为核心 Javascript 堆栈的一部分。从 Tapestry 5.4 开始,tapestry 还包括
bootstrap css 框架。我们可以使用普通的链接标签包含我们自己的样式表。在这种情况下,样式表应位于 Web 根目录-
/src/main/webapp/。
<head>
<link href = "/css/site.css" rel = "stylesheet" type = "text/css"/>
Tapestry 提供了高级选项,通过前面讨论的扩展选项将样式表包含到模板中。
<head>
<link href = "${context:css/site.css}" rel = "stylesheet" type = "text/css"/>
Tapestry 还提供了 Import 注释以将样式表直接包含到 Java 类中。
@Import(stylesheet="context:css/site.css")
public class MyCommonLayout {
}
Tapestry 提供了很多选项来通过 AppModule.java 管理样式表。一些重要的选项是-
挂毯默认样式表可能会被删除。
@Contribute(MarkupRenderer.class)
public static void
deactiveDefaultCSS(OrderedConfiguration<MarkupRendererFilter> configuration) {
configuration.override("InjectDefaultStyleheet", null);
}
也可以通过覆盖其路径来禁用引导程序。
configuration.add(SymbolConstants.BOOTSTRAP_ROOT, "classpath:/METAINF/assets");
启用资产(CSS 和 JavaScript)的动态最小化。我们还需要包含 tapestry-webresources 依赖项(在 pom.xml 中)。
@Contribute(SymbolProvider.class)
@ApplicationDefaults
public static void contributeApplicationDefaults(
MappedConfiguration<String, String> configuration) {
configuration.add(SymbolConstants.MINIFICATION_ENABLED, "true");
}
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-webresources</artifactId>
<version>5.4</version>
</dependency>
客户端 JavaScript
当前这一代 Web 应用程序严重依赖 JavaScript 来提供丰富的客户端体验。 Tapestry 承认这一点,并为 JavaScript 提供一流的支持。 JavaScript 支持深深植根于挂毯中,并且在编程的每个阶段都可用。
之前,Tapestry 过去仅支持 Prototype 和 Scriptaculous。但是,从 5.4 版开始,tapestry 完全重写了 JavaScript 层,使其尽可能通用,并为 JQuery(事实上的 JavaScript 库)提供一流的支持。此外,tapestry 鼓励基于模块的 JavaScript 编程并支持 RequireJS,这是 AMD 的流行客户端实现(异步模块定义-JavaScript 规范,以异步方式支持模块及其依赖项)。
位置
JavaScript 文件是 Tapestry 应用程序的资产。根据资产规则,JavaScript 文件放置在 web 上下文中,
/sr/main/webapp/ 或放置在
META-INF/assets/location 下的 jar 中。
链接 JavaScript 文件
在 XML 模板中链接 JavaScript 文件的最简单方法是直接使用脚本标记,即-
<script language="javascript" src="relative/path/to/js"></script> 。但是,tapestry 不推荐这些方法。 Tapestry 提供了几个选项来链接页面/组件本身中的 JavaScript 文件。下面给出了其中一些。
@import 注释-@import 注释提供了使用上下文表达式链接多个 JavaScript 库的选项。它可以应用于 Page 类及其方法。如果应用于 Page 类,则适用于其所有方法。如果应用于页面的方法,则仅应用于该方法,然后 Tapestry 仅在调用该方法时链接 JavaScript 库。
@Import(library = {"context:js/jquery.js","context:js/myeffects.js"})
public class MyComponent {
// ...
}
JavaScriptSupport 接口-JavaScriptSupport 是一个由 Tapestry 定义的接口,它有一个方法,importJavaScriptLibrary 来导入 JavaScript 文件。只需使用 @Environmental 注释声明和注释即可轻松创建 JavScriptSupport 对象。
@Inject @Path("context:/js/myeffects.js")
private Asset myEffects;
@Environmental
private JavaScriptSupport javaScriptSupport;
void setupRender() {
javaScriptSupport.importJavaScriptLibrary(myEffects);
}
JavaScripSupport 只能使用 @Environmental 注释注入到组件中。对于服务,我们需要使用 @Inject 注释或将其作为参数添加到服务构造函数方法中。
@Inject
private JavaScriptSupport javaScriptSupport;
public MyServiceImpl(JavaScriptSupport support) {
// ...
}
addScript 方法-这类似于 JavaScriptSupport 接口,除了它使用 addScript 方法并且代码直接添加到页面底部的输出中。
void afterRender() {
javaScriptSupport.addScript(
"$('%s').observe('click', hideMe());", container.getClientId());
}
JavaScript 堆栈
Tapestry 允许将一组 JavaScript 文件和相关的样式表组合起来并用作一个单一的实体。目前,Tapestry 包括基于 Prototype 和基于 JQuery 的堆栈。
开发人员可以通过实现
JavaScriptStack 接口并在
AppModule.java 中注册来开发自己的堆栈。注册后,可以使用
@import 注释导入堆栈。
@Contribute(JavaScriptStackSource.class)
public static void addMyStack(
MappedConfiguration<String, JavaScriptStack> configuration) {
configuration.addInstance("MyStack", myStack.class);
}
@Import(stack = "MyStack")
public class myPage {
}