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 模板的简单有效方法。扩展使用 ${<name>} 语法。在 XML 模板中表达扩展有很多选项。让我们看看一些最常用的选项 -

属性扩展

它映射在相应页面类中定义的属性。它遵循 Java Bean 规范来定义 Java 类中的属性。它更进一步,忽略属性名称的大小写。让我们使用属性扩展更改“Hello World”示例。以下代码块是修改后的页面类。

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>

在这里,我们在页面类中将 name 定义为 Java Bean 属性,并在 XML 模板中使用扩展 ${name} 动态处理它。

消息扩展

每个页面类可能有也可能没有关联的属性文件 - 资源文件夹中的 «page_name».properties。属性文件是纯文本文件,每行包含一个键/值对(消息)。让我们为 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 中,它需要由应用程序开发人员创建。布局组件只是另一个组件,放置在 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 组件类中,我们声明了一个 title 字段,并通过使用注解,使其成为强制性的。现在,更改 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> 是模板中动态部分的占位符。通常,block 元素不渲染。只有在模板中定义的组件使用 block 元素。组件将动态地将数据注入到 block 元素中并渲染它。其中一个流行的用例是 AJAX

block 元素为要渲染的动态数据提供确切的位置和标记。每个 block 元素都应该有一个对应的 Java 属性。只有这样才能动态渲染它。block 元素的 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> 只是 content 元素的反面。remove 元素内的标记不被视为模板的一部分。它可以用于服务器端注释和设计目的。

资产

资产是静态资源文件,例如样式表、图像和 JavaScript 文件。通常,资产放置在 Web 应用程序根目录 /src/main/webapp 中。

<head> 
   <link href = "/css/site.css" rel = "stylesheet" type = "text/css"/>

Tapestry 也将存储在 Java 类路径 中的文件视为资产。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: 也可以调用 context: 扩展以从 Web 上下文中获取资产。

<img src = "${asset:context:image/tapestry_banner.gif}" alt = "Banner"/>

可以使用 Inject 和 Path 注解将资产注入到 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 框架。我们可以使用普通的 link 标签包含我们自己的样式表。在这种情况下,样式表应该位于 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/,要么放置在 jar 中的 META-INF/assets/ 位置

链接 JavaScript 文件

在 XML 模板中链接 JavaScript 文件最简单的方法是直接使用 script 标签,即 − <script language = "javascript" src = "relative/path/to/js"></script>。但是,Tapestry 不推荐这种方法。Tapestry 提供了几种选项,可以在页面/组件本身中直接链接 JavaScript 文件。以下是一些示例。

  • @import 注解 − @import 注解提供了使用上下文表达式链接多个 JavaScript 库的选项。它可以应用于页面类及其方法。如果应用于页面类,则它适用于该类中的所有方法。如果应用于页面的方法,则它仅适用于该方法,然后 Tapestry 仅在调用该方法时链接 JavaScript 库。

@Import(library = {"context:js/jquery.js","context:js/myeffects.js"}) 

public class MyComponent { 
   // ... 
}
  • JavaScriptSupport 接口 − JavaScriptSupport 是 Tapestry 定义的一个接口,它有一个方法 importJavaScriptLibrary 用于导入 JavaScript 文件。可以通过简单地声明并使用 @Environmental 注解进行注释来轻松创建 JavaScriptSupport 对象。

@Inject @Path("context:/js/myeffects.js") 
private Asset myEffects;  

@Environmental 
private JavaScriptSupport javaScriptSupport;  
void setupRender() { 
   javaScriptSupport.importJavaScriptLibrary(myEffects); 
}
  • JavaScriptSupport 只能使用 @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 { 
}
广告

© . All rights reserved.