Apache Tapestry - 模板
让我们考虑本节中的 Tapestry XML 模板。 XML 模板是格式良好的 XML 文档。 页面的表示(用户界面)层是 XML 模板。 除了下面给出的项目之外,XML 模板还具有正常的 HTML 标记 −
- Tapestry 命名空间
- 扩展
- 元素
- 组件
现在让我们详细讨论它们。
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 模板的简单而有效的方法。 扩展使用 ${
属性扩展
它映射相应Page类中定义的属性。 它遵循 Java 类中属性定义的 Java Bean 规范。 它更进一步,忽略了属性名称的大小写。 让我们使用属性扩展来更改"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 Property,并使用扩展 ${name} 在 XML 模板中动态处理它。
消息扩展
每个页面类可能有也可能没有关联的属性文件 – «page_name».properties 在 resources 资源文件夹中。 属性文件是纯文本文件,每行具有单个键/值对(消息)。 让我们为 HelloWorld 页面创建一个属性文件: –
"/src/main/resources/com/example/MyFirstApplication/pages/helloworld.properties"并添加"Greeting"消息。
Greeting = Hello
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
每个元素都是为了特定目的而创建的。 可用的tapestry元素如下 −
<t:body>
当两个组件嵌套时,父组件的模板可能必须包裹子组件的模板。<t:body> 元素在这种情况下很有用。 <t:body> 的用途之一是在模板布局中。
一般来说,Web 应用程序的用户界面都会有通用的页眉、页脚、菜单等。这些通用项在 XML 模板中定义,称为模板布局或布局组件。 在 Tapestry 中,它需要由应用程序开发人员创建。 布局组件只是另一个组件,放置在组件文件夹下,该文件夹的路径如下 – 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 TutorialsPoint.</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 将从布局组件和 <t:body> 收集这些详细信息。 布局组件的内容将被 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 TutorialsPoint.</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> 是顶级元素,包含 Tapestry 命名空间。 这用于指定组件的动态部分。
例如,网格组件可能需要一个模板来确定如何在 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:content>,则仅考虑其中的标记。 设计人员使用此功能来设计没有布局组件的页面。
<t:remove>
<t:remove> 与内容元素正好相反。 删除元素内的标记不被视为模板的一部分。 它可用于仅服务器注解和设计目的。
资源
资源是静态资源文件,例如样式表、图像和 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符号。
例如,我们可以定义一个符号,skin.root,其值为 context:skins/basic 并按如下所示使用它 −
@Inject @Path("${skin.root}/style.css") private Asset style;
本地化
通过 Tapestry 包含资源可提供额外的功能。 其中一项功能是"本地化"。 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 管理样式表。 一些重要的选项是 −
Tapestry 的默认样式表可能会被删除。
@Contribute(MarkupRenderer.class) public static void deactiveDefaultCSS(OrderedConfiguration<MarkupRendererFilter> configuration) { configuration.override("InjectDefaultStyleheet", null); }
Bootstrap 也可以通过覆盖其路径来禁用。
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 中,并且在编程的每个阶段都可用。
此前,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 标签,即 − <script language = "javascript" src = "relative/path/to/js"></script>。但是,Tapestry 不推荐这些方法。 Tapestry 提供了多个选项来直接在页面/组件本身中链接 JavaScript 文件。 下面给出了其中一些。
@import annotation − @import 注解提供了使用上下文表达式链接多个 JavaScript 库的选项。 它可以应用于 Page 类及其方法。 如果应用于 Page 类,则它应用于其所有方法。 如果应用于页面的方法,则它仅应用于该方法,然后 Tapestry 仅在调用该方法时才链接 JavaScript 库。
@Import(library = {"context:js/jquery.js","context:js/myeffects.js"}) public class MyComponent { // ... }
JavaScriptSupport interface − 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 { }