6.3.1 配置 Tiles 视图解析器
为了在 Spring 中使用 Tiles,需要配置几个 bean。我们需要一个 TilesConfigurer bean,它会负责定位和加载 Tile 定义并协调生成 Tiles。除此之外,还需要 TilesViewResolver bean 将逻辑视图名称解析为 Tile 定义。
这两个组件又有两种形式:针对 Apache Tiles 2 和 Apache Tiles 3 分别都有这么两个组件。这两组 Tiles 组件之间最为明显的区别在于包名。针对 Apache Tiles 2 的 TilesConfigurer/TilesViewResolver 位于 org.springframework.web .servlet.view.tiles2 包中,而针对 Tiles 3 的组件位于 org.springframework .web.servlet.view.tiles3包中。对于该例子来讲,假设我们使用的Tiles 3。
首先,配置 TilesConfigurer 来解析 Tile 定义。
程序清单 6.1 配置 TilesConfigurer 来解析定义
1
@Bean
2
public TilesConfigurer tilesConfigurer() {
3
TilesConfigurer tiles = new TilesConfigurer();
4
tiles.setDefinitions(new String[] {
5
"/WEB-INF/layout/tiles.xml"
6
});
7
tiles.setCheckRefresh(true);
8
return tiles;
9
}
Copied!
当配置 TilesConfigurer 的时候,所要设置的最重要的属性就是 definitions。这个属性接受一个 String 类型的数组,其中每个条目都指定一个 Tile 定义的 XML 文件。对于 Spittr 应用来讲,我们让它在 /WEB-INF/layout/ 目录下查找 tiles.xml。
其实我们还可以指定多个 Tile 定义文件,甚至能够在路径位置上使用通配符,当然在上例中我们没有使用该功能。例如,我们要求 TilesConfigurer 加载 /WEB-INF/ 目录下的所有名字为 tiles.xml 的文件,那么可以按照如下的方式设置 definitions 属性:
1
tiles.setDefinitions(new String[] {
2
"/WEB-INF/**/tiles.xml"
3
});
Copied!
在本例中,我们使用了 Ant 风格的通配符 **,所以 TilesConfigurer 会遍历 WEB-INF/ 的所有子目录来查找 Tile 定义。
接下来,让我们来配置 TilesViewResolver,可以看到,这是一个很基本的 bean 定义,没有什么要设置的属性:
1
@Bean
2
public ViewResolver viewResolver() {
3
return new TilesViewResolver();
4
}
Copied!
如果你更喜欢 XML 配置的话,那么可以按照如下的形式配置 TilesConfigurer 和 TilesViewResolver:
1
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
2
<property name="definitions">
3
<list>
4
<value>/WEB-INF/layout/tiles.xml.xml</value>
5
<value>/WEB-INF/**/tiles.xml</value>
6
</list>
7
</property>
8
</bean>
9
<bean id="viewResolver" class="org.springframework.web.servlet.view.tiles3.TilesViewResolver" />
Copied!
TilesConfigurer 会加载 Tile 定义并与 Apache Tiles 协作, 而 TilesView-Resolver 会将逻辑视图名称解析为引用 Tile 定义的视图。它是通过查找与逻辑视图名称相匹配的 Tile 定义实现该功能的。我们需要创建几个 Tile 定义以了解它是如何运转的。
定义 Tiles Apache
Tiles 提供了一个文档类型定义(document type definition,DTD),用来在 XML 文件中指定 Tile 的定义。每个定义中需要包含一个元素,这个元素会有一个或多个元素。例如,如下的 XML 文档为 Spittr 应用定义了几个 Tile。
程序清单 6.2 为 Spittr 应用定义 Tile
1
<?xml version="1.0" encoding="ISO-8859-1" ?>
2
<!DOCTYPE tiles-definitions PUBLIC
3
"-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
4
"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
5
<tiles-definitions>
6
7
<definition name="base" template="/WEB-INF/layout/page.jsp">
8
<put-attribute name="header" value="/WEB-INF/layout/header.jsp" />
9
<put-attribute name="footer" value="/WEB-INF/layout/footer.jsp" />
10
</definition>
11
12
<definition name="home" extends="base">
13
<put-attribute name="body" value="/WEB-INF/views/home.jsp" />
14
</definition>
15
16
<definition name="registerForm" extends="base">
17
<put-attribute name="body" value="/WEB-INF/views/registerForm.jsp" />
18
</definition>
19
20
<definition name="profile" extends="base">
21
<put-attribute name="body" value="/WEB-INF/views/profile.jsp" />
22
</definition>
23
24
<definition name="spittles" extends="base">
25
<put-attribute name="body" value="/WEB-INF/views/spittles.jsp" />
26
</definition>
27
28
<definition name="spittle" extends="base">
29
<put-attribute name="body" value="/WEB-INF/views/spittle.jsp" />
30
</definition>
31
32
</tiles-definitions>
Copied!
每个 <definition> 元素都定义了一个 Tile,它最终引用的是一个 JSP 模板。在名为 base 的 Tile 中,模板引用的是 /WEBINF/ layout/page.jsp。某个 Tile 可能还会引用其他的 JSP 模板,使这些 JSP 模板嵌入到主模板中。对于 base Tile 来讲,它引用的是一个头部 JSP 模板和一个底部 JSP 模板。
base Tile 所引用的 page.jsp 模板如下面程序清单所示。
程序清单 6.3 主布局模板:引用其他模板来创建视图
1
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
2
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="t" %>
3
<%@ page session="false" %>
4
<html>
5
<head>
6
<title>Spittr</title>
7
<link rel="stylesheet"
8
type="text/css"
9
href="<s:url value="/resources/style.css" />" >
10
</head>
11
<body>
12
<div id="header">
13
<t:insertAttribute name="header" />
14
</div>
15
<div id="content">
16
<t:insertAttribute name="body" />
17
</div>
18
<div id="footer">
19
<t:insertAttribute name="footer" />
20
</div>
21
</body>
22
</html>
Copied!
在程序清单 6.3 中,需要重点关注的事情就是如何使用 Tile 标签库中的 <t:insert Attribute> JSP 标签来插入其他的模板。在这里,用它来插入名为 header、body 和 footer 的模板。最终,它会形成图 6.4 所示的布局。
图 6.4 通用的布局,定义了头部、主体区以及底部
在 base Tile 定义中,header 和 footer 属性分别被设置为引用 /WEB-INF/ layout/header.jsp/WEB-INF/layout/footer.jsp。但是 body 属性呢?它是在哪里设置的呢?
在这里,base Tile 不会期望单独使用。它会作为基础定义(这是其名字的来历),供其他的 Tile 定义扩展。在程序清单 6.2 的其余内容中,我们可以看到其他的 Tile 定义都是扩展自 base Tile。它意味着它们会继承其 header 和 footer 属性的设置(当然,Tile 定义中也可以覆盖掉这些属性),但是每一个都设置了 body 属性,用来指定每个 Tile 特有的 JSP 模板。
现在,我们关注一下 home Tile,它扩展了 base。因为它扩展了 base,因此它会继承 base 中的模板和所有的属性。尽管 home Tile 定义相对来说很简单,但是它实际上包含了如下的定义:
1
<definition name="home" template="/WEB-INF/layout/page.jsp">
2
<put-attribute name="header" value="/WEB-INF/layout/header.jsp" />
3
<put-attribute name="footer" value="/WEB-INF/layout/footer.jsp" />
4
<put-attribute name="body" value="/WEB-INF/views/home.jsp" />
5
</definition>
Copied!
属性所引用的每个模板是很简单的,如下是 header.jsp 模板:
1
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
2
<a href="<s:url value="/" />"><img
3
src="<s:url value="/resources" />/images/spitter_logo_50.png"
4
border="0"/></a>
Copied!
footer.jsp 模板更为简单:
1
Copyright &copy; Craig Walls
Copied!
每个扩展自 base 的 Tile 都定义了自己的主体区模板,所以每个都会与其他的有所区别。但是为了完整地了解 home Tile,如下展现了 home.jsp:
1
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
2
<%@ page session="false" %>
3
<h1>Welcome to Spitter</h1>
4
5
<a href="<c:url value="/spittles" />">Spittles</a> |
6
<a href="<c:url value="/spitter/register" />">Register</a>
Copied!
这里的关键点在于通用的元素放到了 page.jsp、header.jsp 以及 footer.jsp 中,其他的 Tile 模板中不再包含这部分内容。这使得它们能够跨页面重用,这些元素的维护也得以简化。
要想看一下这些元素组合在一起的样子,那么可以看一下图 6.5。如图所示,它包含了一些样式和图像以增加应用的美观性。我们不是专门讨论使用 Tiles 实现页面布局的,因此在本节中不会涵盖所有的细节。但是,我们可以看到页面上的各种组件通过 Tile 定义组合在了一起,并且渲染出了 Spittr 应用的主页。
在 Java Web 应用领域,JSP 长期以来都是占据主导地位的方案。但是,在这个领域有了新的竞争者,也就是 Thymeleaf。接下来让我们 看一下如何在 Spring MVC 应用中使用 Thymeleaf。
图 6.5 Spittr 首页,通过 Apache Tiles 进行的布局
Last modified 2yr ago
Copy link