Tile布局(二)
Monday, 10. July 2006, 08:44:24
一旦找出了页面之间的相似之处(这是困难的部分),您就能够创建新的布局页面(这是容易的部分)。为了创建一个tile布局,您必须做以下事情:
* 使用标签库指令将tile标签库导入JSP,同时导入需要的其他任何标签库。
* 使用字符串参数来显示像页面这样使用tiles:getAsString标签的内容。
* 使用tiles:insert标签将tile插入布局的适当区域。
* 使用tiles:put标签向内部tile传递任何需要的参数 ―― 这个标签是tiles:insert标签的子标签。
将tile标签库导入JSP,同时导入需要的其他任何标签库,如下所示(siteLayout.jsp):
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
注意:要使用 tile 标签库,不要忘了包括 web.xml 文件中的标签库:
<taglib>
<taglib-uri>/WEB-INF/struts-tiles.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-tiles.tld
</taglib-location>
</taglib>
接下来使用字符串参数显示诸如页面标题之类的内容。您不仅需要更改页面的内容,而且还需要更改出现在浏览器中的标题。为此,需要传入tile布局将要使用的标题:
<html>
<head>
<tiles:getAsString name="title" ignore="true"/>
</head>
注意该代码中使用了tiles:getAsString标签来显示字符串参数。您不仅能够传递字符串参数,而且能够传递要插入这个页面的其他页面。这里假设调用JSP页面向这个tile布局传递了一个标题;否则,标题将是空白。
注意:ignore属性:
ignore属性如果为true,这意味着在缺失该属性的情况下忽略它。否则,如果ignore属性为false,那么在没有传递该参数的情况下,Tiles框架将抛出异常,页面将不会显示出来(false是默认值)。
要插入内容JSP,可使用tiles:insert标签,它插入该框架作为tile来引用的任何页面或Web资源。这个标签实际上在tile布局中定义了一个区域。记住,tile布局的目标是将tile布置到该布局中。下面是向该布局插入一个tile的例子:
<tiles:insert attribute="content"/>
上面这个例子非常简单。如果想要插入一个tile,并向它传递当前页面范围内的项,那该怎么办呢?例如,使用Tiles框架给header.jsp传递一个标题参数(在tile范围内)是可以做到的。
调用其他 tile(传递属性)
在插入tile的任何时候,您都可以选择性地给它传递参数。传递给tile的参数将被放入该tile的标题范围(称为“标题属性”)。例如,除了让标题显示在浏览器的标题栏之外,可能还希望该标题出现在页面的页眉区域。
header.jsp文件将完成这个任务。虽然标题变量在该tile布局页面范围之内,但它不在该tile布局所插入的tile的范围之内。脆弱方法每个tile和tile布局都获取它自己的环境 ―― 也就是它自己的tile范围。因而,您必须像下面这样给页眉tile传递该tile变量:
<tiles:insert attribute="header" ignore="true">
<tiles:put name="title"
beanName="title" beanScope="tile"/>
</tiles:insert>
tiles:put标签将这个tile布局范围内的tile参数放进页眉tile的范围。然后页眉tile就能够像tile布局所做的那样,通过tiles:getAsString标签来使用这个参数。参数名称就是页眉的tile范围内的属性名称。bean参数是当前范围内(siteLayout.jsp)的bean的名称。beanScope是您在其中查找这个属性的范围(可能的值是页面、tile、请求、会话和应用程序)。 您可以从任何范围向该tile传递bean。
这个tile布局的完整清单
接下来,您会看到quote.jsp和index.jsp将要使用的这个新布局页面(siteLayout.jsp)的完整清单:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<html>
<head>
<title>
<tiles:getAsString name="title" ignore="true"/>
</title>
</head>
<body>
<table width="500" border="0" cellspacing="0" cellpadding="0">
<tr bgcolor="#36566E">
<td height="68" width="48%">
<div align="left">
<img src="images/hp_logo_rickhightower.gif"
width="220" height="74">
</div>
</td>
</tr>
<tr>
<td height="68" width="2000">
<tiles:insert attribute="header" ignore="true">
<tiles:put name="title"
beanName="title" beanScope="tile"/>
</tiles:insert>
</td>
</tr>
<tr>
<td>
<div align="center">
<tiles:insert attribute="content"/>
</div>
</td>
</tr>
<tr>
<td>
<tiles:insert attribute="footer" ignore="true"/>
</td>
</tr>
</table>
</body>
</html>
请花点时间研究一下上面的代码。注意tile是如何插入不同区域的(页眉、页脚、内容),以及如何利用HTML布局来为tile定义区域,从而为应用程序定义完整的布局。
使用tile布局
现在已经定义好了使用tiles的tile布局,您需要使用该布局。index.jsp和quote.jsp都将使用同一个布局。虽然这对两个页面来说似乎是大量的工作,但是对于真实的Web应用程序,你可能会对20个或更多的页面使用同一个布局。通过这种方式,您不必在20个位置重复HTML或包括JSP片断。
注意:为什么不就使用jsp:include呢?
在适当的位置包括JSP片断是重用HTML的脆弱方法。设想一下包括相同的5个JSP片断的20个页面 ―― 您必须重复100次。
为了使用tile,您需要执行以下步骤:
1. 使用taglib指令导入tile标签库。
2. 使用 tiles:insert 标签来将tile布局插入当前页面。
3. 使用 tiles:put 来传递字符串参数。
4. 使用 tiles:put 来传入参数tile。
通过使用tile布局,您能够在一个位置中将站点布局所需要的整个HTML外部化,然后只需将它插入每个页面。观察一下下面的例子,它显示了如何把tile布局插入index.jsp:
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<tiles:insert page="/siteLayout.jsp" flush="true">
<tiles:put name="title" type="string"
value="Get Rick Hightower Stock Quote" />
<tiles:put name="header" value="/header.jsp" />
<tiles:put name="footer" value="/footer.jsp" />
<tiles:put name="content" value="/indexContent.jsp"/>
</tiles:insert>
现在,当您想要在quote.jsp中做相同的事情时,只需更改内容和页眉。
您需要使用插入标签来调用tile布局(显示函数)。(注意用来将tile布局插入当前页面的 tiles:insert 标签):
<tiles:insert page="/siteLayout.jsp" flush="true">
page 属性指定了上一节中定义的tile布局。如果flush属性被设置为true,这个tile(以及到目前为止的页面)将在页面的其余部分之前(或在缓冲区满而迫使执行刷新时)写到浏览器。
要更改quote.jsp和header.jsp之间的页面tile,可使用子标签tiles:put:
<tiles:put name="title" type="string"
value="Get Stock Quote" />
注意tiles:put是如何向tile布局传递字符串参数的。tiles:put的name属性标签指定了参数名称。tiles:put的type属性指定了参数的类型。最后,value参数用于传递title属性的值。这允许您在使用 tiles:insert标签来调用tile布局(显示函数)时,把简单的字符串作为参数来传递。这些参数将成为该 tile 布局属性;也就是被插入该tile布局的tile范围。
注意您是如何将三个tile作为页眉、页脚和内容参数来传递的(header.jsp、footer.jsp 和 indexContent.jsp):
<tiles:put name="header" value="/header.jsp" />
<tiles:put name="footer" value="/footer.jsp" />
<tiles:put name="content" value="/indexContent.jsp"/>
header.jsp页面将被插入该tile布局的页眉区域。footer.jsp页面将被插入该tile布局的页脚区域。indexContent.jsp页面将被插入该tile布局的内容区域。 如果想插入不同的内容和tile,只需改变内容参数的值。
注意用于index.jsp的表单不再驻留在index.jsp中。该表单现在驻留在indexContent.jsp中,如下面所列出的:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<html:form action="Lookup">
<table width="45%" border="0">
<tr>
<td><bean:message key="app.symbol" />:</td>
<td><html:text property="symbol" /></td>
</tr>
<tr>
<td colspan="2" align="center"><html:submit /></td>
</tr>
</table>
</html:form>
除了将tile指定为JSP页面外,您还能够在tiles:put标签的正文内将文本作为tile来传递。quote.jsp 所做的正好就是这样:
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<tiles:insert page="/siteLayout.jsp" flush="true">
<tiles:put name="title" type="string"
value="Rick Hightower Stock Quote" />
<tiles:put name="header" value="/header.jsp" />
<tiles:put name="footer" value="/footer.jsp" />
<tiles:put name="content" type="string">
<bean:message key="app.price"/>
<%= request.getAttribute("PRICE") %>
</tiles:put>
</tiles:insert>
注意tiles:put标签的标签体包含 quote.jsp 的内容。其他每项内容都是该布局所定义的,都与上一个例子中使用的 tile 相同。这样的优点是能够减少系统中的JSP页面的数目。关于哪种方法工作得最好,很久以来一直存在争议,我的结论是它取决于put标签体中有多少代码。
您看到这里存在的问题了吗?存在这样一条规则:不要重复您自己(Don't repeat yourself,DRY),而您已经违背了这点规则。










