当我们需要在页面上添加一些通用元素,比如添加包含站点Logo的头部、使用样式并在底部展现版权信息。我们不会在Spittr应用中的每个JSP都进行这样的修改,而是借助Apache Tiles来为模板实现一些通用且可重用的布局。
Apache Tiles是一种布局引擎,定义适用于所有页面的通用页面布局。SpringMVC以视图解析器的形式为Apache Tiles提供了支持,这个视图解析器能够将逻辑视图名解析为Tile定义。
要在Spring中使用Tiles,需要配置几个bean。我们需要一个TilesConfigurer bean,它会负责定位和加载Tile定义并协调生产Tiles。除此之外,还需要TilesViewResolver bean将逻辑视图名解析为Tile定义。
首先,配置TilesConfigurer来解析Tile定义:
@Bean
public TilesConfigurer tilesConfigurer(){
TilesConfigurer tiles= new TilesConfigurer();
//指定Tile定义的位置
tiles.setDefinitions(new String[]{"/WEB-INF/layout/tiles.xml"});
tiles.setCheckRefresh(true); //启用刷新功能
return tiles;
}
definitions属性接受一个String类型的数组,其中每个条目都指定一个Tile定义的XML文件。接下来,我们来配置TilesViewResolver:
@Bean
public ViewResolver viewResolver(){
return new TilesViewResolver();
}
这是一个很基本的bean定义,没有设置什么属性。TilesConfigurer会加载Tile定义并与Apache Tiles协作,而TilesViewResolver会将逻辑视图名称解析为引用Tile定义的视图。
Apache Tiles提供了一个文档类型定义(document type definition,DTD),用来在XML文件中指定Tiles定义。每个定义中需要包含一个<definition>
元素,这个元素会有一个或多个<put-attribute>
元素。例如,如下的XML文档为Spittr应用定义了几个Tile:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
<!--定义基本模板-->
<definition name="base" template="/WEB-INF/layout/page.jsp">
<put-attribute name="header" value="/WEB-INF/layout/header.jsp" />
<put-attribute name="footer" value="/WEB-INF/layout/footer.jsp" />
</definition>
<!--定义填充内容-->
<definition name="home" extends="base">
<put-attribute name="body" value="/WEB-INF/layout/home.jsp" />
</definition>
<definition name="registerForm" extends="base">
<put-attribute name="body" value="/WEB-INF/layout/registerForm.jsp" />
</definition>
</tiles-definitions>
page.jsp如下所示:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="t" %>
<%@ page session="false" %>
<html>
<head>
<title>Spittr</title>
<link rel="stylesheet" type="text/css"
href="<s:url value="/resources/style.css" />" >
</head>
<body>
<div id="header">
<t:insertAttribute name="header" /> <!--插入头部-->
</div>
<div id="body">
<t:insertAttribute name="body" /> <!--插入主体-->
</div>
<div id="footer">
<t:insertAttribute name="footer" /> <!--插入尾部-->
</div>
</body>
</html>
这样,相应的模块都会插入到模板中,以达成统一布局。