模板
让我们在本节中考虑Tapestry XML模板。 XML模板是一个格式良好的XML文档。 页面的表示(用户界面)层是XML模板。 除下面给出的项目外,XML模板还具有普通的HTML标记 -
- Tapestry命名空间
- Expansions
- Elements
- Components
现在让我们详细讨论它们。
Tapestry命名空间
Tapestry命名空间只是XML命名空间。 应在模板的根元素中定义命名空间。 它用于在模板中包含Tapestry组件和组件相关信息。 最常用的命名空间如下 -
xmlns:t =“https://tapestry.apache.org/schema/tapestry_5_4.xsd” - 用于标识Tapestry的元素,组件和属性。
xmlns:p =“tapestry:parameter” - 用于将任意代码块传递给组件。
Tapestry Namespace的一个例子如下 -
<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>
扩展(Expansions)
扩展是在页面的呈现阶段动态更改XML模板的简单而有效的方法。 扩展使用$ {}语法。 有许多选项可以表达XML模板中的扩展。 让我们看看一些最常用的选项 -
物业扩张
它映射相应Page类中定义的属性。 它遵循Java Bean中的属性定义的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 Template中对其进行动态处理。
消息扩展
每个Page类可能有也可能没有资源文件夹中的关联属性文件 - «page_name».properties 。 属性文件是纯文本文件,每行具有单个键/值对(消息)。 让我们为HelloWorld Page创建一个属性文件 -
“/src/main/resources/com/example/MyFirstApplication/pages/helloworld.properties”并添加“问候”消息。
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>
元素 (Elements)
Tapestry有一小组要在XML模板中使用的元素。 元素是在Tapestry命名空间下定义的预定义标记 -
https://tapestry.apache.org/schema/tapestry_5_4.xsd
每个元素都是为特定目的而创建的。 可用的挂毯元素如下 -
当嵌套两个组件时,父组件的模板可能必须包装子组件的模板。 元素在这种情况下很有用。 的一个用途是在模板布局中。
通常,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 xnip.</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 xnip.</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》
是一个顶级元素,包含一个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》
是模板中动态部分的占位符。 通常,块元素不呈现。 仅,模板中定义的组件使用块元素。 组件会将数据动态注入块元素并进行渲染。 一个流行的用例是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:remove》
与内容元素正好相反。 remove元素中的标记不被视为模板的一部分。 它可用于仅用于服务器的注释和用于设计目的。
Assets
资产是静态资源文件,例如样式表,图像和JavaScript文件。 通常,资产放在Web应用程序根目录/src/main/webapp 。
<head>
<link href = "/css/site.css" rel = "stylesheet" type = "text/css"/>
Tapestry还将存储在Java Classpath中的文件视为Assets。 Tapestry提供了高级选项,可通过扩展选项将资产包含到模板中。
Context - 在Web上下文中获取资产的选项。
<img src = "${context:image/tapestry_banner.gif}" alt = "Banner"/>
asset - 组件通常将自己的资产与Java类一起存储在jar文件中。 从Tapestry 5.4开始,在类路径中存储资产的标准路径是META-INF/assets 。 对于库,存储资产的标准路径是META-INF/assets/«library_name»/. asset: META-INF/assets/«library_name»/. asset:还可以调用context: expansion来从Web上下文中获取资产。
<img src = "${asset:context:image/tapestry_banner.gif}" alt = "Banner"/>
可以使用Inject和Path注释将资产注入Tapestry页面或组件。 Path注释的参数是资产的相对路径。
@Inject
@Path("images/edit.png")
private Asset icon;
Path parameter还可以包含AppModule.java部分中定义的Tapestry符号。
例如,我们可以使用值context:skin/basic定义一个符号skin.root并使用它,如下所示 -
@Inject
@Path("${skin.root}/style.css")
private Asset style;
本地化(Localization)
通过tapestry包含资源可提供额外的功能。 一个这样的功能是“本地化”。 Tapestry将检查当前的语言环境并包含适当的资源。
例如,如果当前区域设置设置为de ,则将包含edit_de.png而不是edit.png。
CSS
Tapestry具有内置样式表支持。 Tapestry将注入tapestry.css作为核心Javascript堆栈的一部分。 从Tapestry 5.4开始,tapestry也包含bootstrap css framework 。 我们可以使用普通链接标记包含我们自己的样式表。 在这种情况下,样式表应该位于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过去只支持Prototype和Scriptaculous。 但是,从版本5.4开始,tapestry完全重写了JavaScript层,使其尽可能通用,并为JQuery(JavaScript的事实库)提供了一流的支持。 此外,tapestry鼓励基于模块的JavaScript编程,并支持RequireJS,这是AMD的一种流行的客户端实现(异步模块定义 - JavaScript规范,以异步方式支持模块及其依赖性)。
Location
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 annotation - @import annotation提供了使用上下文表达式链接多个JavaScript库的选项。 它可以应用于Page类及其方法。 如果应用于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 method - 这与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 {
}