让我们在本节中考虑Tapestry XML模板. XML模板是一个格式良好的XML文档.页面的表示(用户界面)层是XML模板.除了下面给出的项目之外,XML模板还有正常的HTML标记;
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模板的简单而有效的方法.扩展使用$ {< name>}语法.有许多选项可以表达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 并动态处理它在XML模板中使用扩展 $ {name} .
每个Page类可能有也可能没有资源文件夹中的关联属性文件 - « page_name» .properties .属性文件是纯文本文件,每行具有单个键/值对(消息).让我们在 -
"/src/main/resources/com/example/MyFirstApplication/pages/helloworld.properties"中为HelloWorld页面创建一个属性文件,并添加一条"问候"消息.
Greeting = Hello
问候语消息可以在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>的用途之一在模板布局中.
通常,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 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>是一个顶级元素,包含一个tapestry命名空间.这用于指定组件的动态部分.
例如,网格组件可能需要一个模板来标识如何在HTML中呈现其行 - tr(和列td) table.
<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://img01.yuandaxia.cn/Content/img/tutorials/apache_tapestry/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> element用于指定模板的实际内容.通常,所有标记都被视为模板的一部分.如果< t:content>如果指定,则只考虑其中的标记.设计人员使用此功能设计没有布局组件的页面.
< t:remove>正好与内容元素相反. remove元素中的标记不被视为模板的一部分.它可以用于仅服务器注释和设计目的.
资产是静态资源文件,如样式表,图像和JavaScript文件.通常,资产放在Web应用程序根目录/src/main/webapp 中.
<head> <link href = "/css/site.css" rel = "stylesheet" type = "text/css"/>
Tapestry还将存储在 Java Classpath 中的文件视为资产. Tapestry提供高级选项,通过扩展选项将资产包含到模板中.
上下文 : 选项以在Web上下文中获取资源.
< img src ="$ { context:image/tapestry_banner.gif}"alt ="Banner"/>
资产 : 组件通常将自己的资产与Java类一起存储在jar文件中.从Tapestry 5.4开始,在类路径中存储资产的标准路径是 META-INF/assets .对于图书馆,存储资产的标准路径是 META-INF/assets/« library_name»/. asset:还可以调用 context:扩展来从Web上下文中获取资源.
<img src = "${context:image/tapestry_banner.gif}" alt = "Banner"/>
可以使用Inject和Path注释将资产注入Tapestry页面或组件. Path注释的参数是资产的相对路径.
@Inject @Path("images/edit.png" ) 私人资产图标;
路径参数还可以包含 AppModule.java 部分中定义的Tapestry符号.
例如,我们可以定义一个符号,skin.root,其值为context:skins/basic,并使用如下所示 :
@Inject @Path("images/edit.png") private Asset icon;
通过tapestry包含资源可提供额外的功能.一个这样的功能是"本地化". Tapestry将检查当前的语言环境并包含适当的资源.
例如,如果当前语言环境设置为 de ,则 edit_de.png
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还提供了导入注释,将样式表直接包含在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>
当前一代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中.
链接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界面 : JavaScriptSupport是由tapestry定义的接口,它有一个方法 importJavaScriptLibrary 来导入JavaScript文件.只需使用@Environmental注释声明和注释即可轻松创建JavScriptSupport对象.
@Inject @Path("context:/js/myeffects.js") private Asset myEffects; @Environmental private JavaScriptSupport javaScriptSupport; void setupRender() { javaScriptSupport.importJavaScriptLibrary(myEffects); }
只能使用
@Inject private JavaScriptSupport javaScriptSupport; public MyServiceImpl(JavaScriptSupport support) { // ... }
addScript方法 : 这类似于JavaScriptSupport接口,只是它使用 addScript 方法,代码直接添加到页面底部的输出中.
void afterRender() { javaScriptSupport.addScript( "$('%s').observe('click', hideMe());", container.getClientId()); }
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 { }