Tiles的使用(一)
综述
可用性是当今应用程序设的主要关注点,一致性(consistency)是可用性的主要因素。用户想要专注于手上的任务,却会被应用程序界面或屏幕的布局的小问题而担搁。保持动态web应用程序一致性是个很大挑战,因为一般都是手动对每个页面进行编码的。如今已经有许多针对静态页面的布局设计工具可以提供给设计人员,但基于JSP的很少。更糟的是,应用程序的外观往往是到最后才会被确定下来,然后会在不同的版本间改变,甚至是对一个大型的web站点随意的重新布局(relaunch)。在最后的期限编码或测试,即使是改变背景色或添加一个新的链接到工具栏上,也像是一场恶梦!
在书的一开始,我们着重讲了应用程序分层的重要性,这样能减少改动带来的影响。通过对应用程序的分层,我们可以修改某个部分而不会影响其它部分。表现层使用相同的设计,实现了内容和外观的分离。将内容从布局(layout)中分离出来,可以使用动态的JSP include。JSP规范提供了静态的和动态的include。标准的动态JSP include的动作是:<jsp:include>。
我们可以使用动态include把页面分成几个片断,每个都有自己特有的用途。把一个后台模板设成缺省的布局页面,运行时用这些片断来提供内容。
Tiles框架是一种更加高级的JSP include行为的表现形式。在Tiels应用程序中,模板常被用来定义header,menu body,content和footer的位置。其它的页面用来向这些页面填充内容。如果header需要改变,只要修改模板文件就可以了。这种改变会自动的应用到每个使用模板的页面中。改动带来的影响会降到最低。
标准的HTML组件,象CSS也能很好的工作在动态模板下,这样能进一步降低改动的影响。
Dynamic element (动态元素) | JSP 的一部分,会被JSP翻译器识别,包括action,directive,expression, JSP标签, 或scriptlet |
Template data (模版数据) | JSP的一部分,通常不被JSP 翻译器转换,而被逐字传递到响应之中。 通常是标记或者可视文本 |
Template page (模版页面) | 一个包含其他页面或者被其他页面包含的JSP |
Template file (模版文件) | 一个包含模版页面的静态文件或者JSP文件 |
Tile | 模版页面的同义词 |
Layout (布局) | 描述模版文件或tiles应该如何在页面中定位 |
Tiles | 一个强大易用的模版和布局框架 |
Definition (定义) | 一个Tiles 特征,允许一个布局被标识为一个模版页面,或者一个JavaBean。也可以用一个XML 文档来描述 |
当HTML 表格第一次引入时,页面设计者马上将它作为是一种布局方式。无边框的表格可以用来包含其他表格和内容,这是一种与众不同的布局方式。同样的想法经常用在动态模板中,一个主模板用来提供页面的布局和组件位置,页面片段被包含进来填充这些组件。页面片段可以被包含进各种类型的布局:无边框表格,<div>标记,甚至最简单的将一个组件堆在另一个组件之上。
Tiles 是一个用简单但有效的标记库来实现模板和布局的框架。它可以用来替换Struts1.0 中的模板标记库但功能更强大。Tiles包也用在任何的JSP应用程序中。
通常,JSP 模板系统都是使用一个模板作为布局,而其他作为填充组件。Tiles 称之为布局文件Definitions。大多数模版系统都要求有一个额外的文件作为布局文件。为避免这种麻烦,Tiles允许布局Definitions像一个JavaBean一样被存储。而且,在Struts 中还有个扩展,允许Definitions是一个ActionForward 的目标。这是一个激动人心的特征,现在让我们从头开始,创建一个新的布局。 你可以在下面代码中见到,我们创建用来包含布局组件的地方,都放置了一个JSP 标记,像
<tiles:insert attribute="aName"/>。意思是说在这里插入属性值指代的tile(或者模板文件) 。当要在应用程序中使用这个模板的时候,只要传递给它这个文件的路径。这允许我们在多处使用同一个模板,只需要简单的传递一个或多个不同tile的路径。
在大多数情况下,每个页面的body tile可能不同,但是同一模块中所有页面可以共享相同的header和menu tile。同时,可能同一站点的所有页面都要共享同一个footer tile。当新的一年过去,需要在每个页面中更新版权声明,这时只要修改footer tile就行。接着只需要加入剩下的HTML 标记,一个完整的独立的模板页面就完成了。
为了能快速完成一个例子,我们将构建一个典型的有一个header,menu,body和footer的web页面。布局如下:
herder | |
menu | body |
footer |
创建一个像上图一个的模板页面是很容易的:
- 打开一个新的JSP页面
- 导入Tiles标记库
- 创建一个匹配上图的HTML表格
- 使用Tiles JSP tag -<tiles:insert>去命名布局中的每个部分
<%@ taglib uri="/tags/tiles" prefix="tiles" %> |
但什么是tile呢?
Tiles 框架提供的模板特性要远远超过标准Servlet 和JSP include 所提供的。框架称其模板为tiles。这有助于说明tiles比简单的JSP 模板功能更加强大。对于你的表现层,Tiles就象是积木。
学术上,tile是JSP中的一个矩形区域,有时也称为区域(region)。一个tile 也可以由其他tile 组合而成。Tiles能被递归构建,像是一颗树,树上的每个节点是一个区域,根节点是页面,最终节点或叶节点包含内容,中间的节点通常被用来布局。布局节点很有用,可以确定位置一个tile或为内容tile提供后台标签。
- Parameters--参数
在运行期间一个tile能够以参数或属性的形式接受不同的信息,据这些信息表现出不同的效果。tiles 参数通常称为属性(attribute)以避免和请求参数相冲突。Tile的属性插入tile时被定义,此属性只有在这个tile中可见。对于子tiles或包含该tile的页面也是不可见的。当相同的tile多次用在相同的页面中时,可以避免名称冲突。开发人员就可以着力于构建Tiles而不用担心名字冲突的问题了。tile属性可以是String或其它类型。 - Definitions--定义
各种属性通过一个tile组合在一起用来描述屏幕的显示。在实际中,这些描述是有关联的,往往是构建在其它tile之上的。Definitions存储一组属性,有自己标识的独立对象。声名一个base Screen Definitions,然后在这个基础上建立其它的Definitions。如果这个base Screen改变了,在这个base Screen上扩展的所有Definitions也会改变。这就将面向对象的继承和封装原理带到了你的动态页面中。Definitions是可选的,也可以随时用一个简单的JSP标记来部署Tile。
部署Tiles模板
上面说了在什么地方使用Tiles,接着要介绍怎么使用Tiles ,下面是hello.jsp的源代码,使用的是myLayout.jsp的布局方式:
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:insert page="/layouts/myLayout.jsp" flush="true"> <tiles:put name="title" value="Hello World" /> <tiles:put name="header" value="/tiles/header.jsp" /> <tiles:put name="footer" value="/tiles/footer.jsp" /> <tiles:put name="menu" value="/tiles/menu.jsp" /> <tiles:put name="body" value="/tiles/helloBody.jsp" /> </tiles:insert> |
将下面的代码:
<tiles:put name="title" value="Hello World" /> <tiles:put name="body" value="/tiles/helloBody.jsp" /> |
替换为:
<tiles:put name="title" value="Hello Again" /> <tiles:put name="body" value="/tiles/pageTwo.jsp" /> |
这就很容易产生一个只有title和body与hello.jsp不同的新页面了。
但是,要注意的是,执行上面的步骤,要创建两个新的页面:一个是hello.jsp,第二个是要插入hello.jsp的包含内容的页面,像helloBody.jsp。下面的方法就不需要产生两个页面。
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:insert page="/layouts/myLayout.jsp" flush="true"> <tiles:put name="title" value="Hello World" /> <tiles:put name="header" value="/tiles/header.jsp" /> <tiles:put name="body" type="string"> //直接打印下面的内容 <%-- Place the content from /tiles/pageTwo.jsp here --%> </tiles:put> <tiles:put name="footer" value="/tiles/footer.jsp" /> <tiles:put name="menu" value="/tiles/menu.jsp" /> </tiles:insert> |
使用put的type标签,像上面的例子中使用的type="String",直接把helloBody.jsp的内容放进这个标签中,这样就避免了创建多余的tile了。唯一不好的是screen Definitions分散在站点的各处,这使得全局的修改很困难。但对于一个小型的应用程序,还是很有用的。
添加一个CSS
<%@ taglib uri="/tags/struts-html" prefix="html" %> <HTML> <HEAD> <TITLE><tiles:getAsString name="title"/></TITLE> <html:base/> <LINK rel="stylesheet" type="text/css" ref="<html:rewrite page='/assets/styles/global.css'/>"> </HEAD> <BODY> |
还可以使用<html:base> 标记来引入CSS或其它资源。