Skip navigation.

Kappa's fresh life

Light My Fire Now!

Posts tagged with "Struts相关"

Tile布局(二)

创建tile布局

一旦找出了页面之间的相似之处(这是困难的部分),您就能够创建新的布局页面(这是容易的部分)。为了创建一个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>
<br> <tiles:getAsString name="title" ignore="true"/><br>
</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),而您已经违背了这点规则。

Tile布局(一)

构建第一个tile布局

如果站点能够重用相同的布局(使用HTML表格来实现)和图像,而不必重复相同的HTML代码,这样不是很好吗?

Tile在为站点创建共同的外观方面特别出色。话虽这样说,许多开发人员并没有认识到Tiles在创建用JSP实现的可重用组件方面同样也很出色。

如果您发现自己在多个页面上重复相同的HTML代码,就可考虑对那些页面使用tile布局。类似地,如果在不同页面上的不同地方使用相同的HTML或JSP标签,这种情形也很适合使用tile来创建小型可视组件。

作为Tiles框架的一个例子,下面将重构一个简单的股票报价应用程序来利用tile布局,如图 3 所示。



示例应用程序

这个简单的示例应用程序主要包含一个股票报价页面,它具有一个接受单个参数(即股票代码)的表单(index.jsp)。 另一个页面显示股票报价的值(quote.jsp)。

研究一下下面这两个代码清单。您将重构它们以使用各种各样的tile布局。

index.jsp
 <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
 <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

 <html>
   <head>
     <title>Stock Quote</title>
   </head>

   <body>
     <table width="500" border="0" cellspacing="0" cellpadding="0">
       <tr>
         <td> </td>
       </tr>
       <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> </td>
       </tr>
     </table>

     <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> 

   </body>
 </html>

quote.jsp
 <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

 <html>
   <head>
     <title>Stock Quote</title>
   </head>
   <body>

     <table width="500" border="0" cellspacing="0" cellpadding="0">
       <tr>
         <td> </td>
       </tr>
       <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> </td>
       </tr>
       <tr>
         <td> </td>
       </tr>
       <tr>
         <td> </td>
       </tr>
       <tr>
         <td>
           <bean:message key="app.price" />: <%= request.getAttribute("PRICE") %>
         </td>
       </tr>
       <tr>
         <td> </td>
       </tr>
     </table>
   </body>
 </html>

欲学习如何使用Tiles框架,您首先必须编写一个tile布局,然后重构上述两个例子页面,以便它们不必重复如此多的HTML代码。


逐步创建tile布局


为了创建一个tile布局,您需要做以下事情:

1. 找出两个页面的相似之处。

2. 创建一个新的布局页面。

3. 创建两个新的内容页面,它们仅包含EmployeeListing.jsp和DeptListing.jsp之间的不同之处。

4. 将tile布局插入页面 ―― 也就是让EmployeeListing.jsp和DeptListing.jsp在它们的页面中插入 tile 布局,并将内容作为参数传递,同时传递其他必要的参数(比如标题)。

由于找出两个页面之间的相似之处需要HTML布局和Web站点适用性方面的技能,事实证明这项工作更像一门艺术,而不是像一门科学。由于某些原因,拥有紫色的头发和纹身是有所帮助的。如果您不这样认为,可以问我的朋友Boo。

本教程重点集中于Struts,而不是HTML布局和Web站点适用性方面的必要技能。 因此,您不会了解关于纹身和紫色头发方面的内容。事实上,例子中的HTML布局是刻意简单化的,以防分散我们对Tiles框架的注意力。

Tiles框架和体系结构

术语解释

在更详细地讨论 Tiles 框架之前,让我们首先定义一些重要术语。

术语词汇表

Tiles
Struts 用来创建表示组件的模板框架。

页面
tile 布局包括的 Web 资源。

Tile
同页面。

区域
tile 布局中插入其他 tile 的范围。 区域拥有诸如页眉、页脚之类的逻辑名称。

Tile 布局
描述其他页面应该定位在何处的 JSP 页面。Tile 布局充当模板,定义了插入其他 tile 的区域。 一个 tile 布局可以是另一个 tile 布局的 tile。

定义
定义用于调用某个 tile 布局的参数。


Tile 布局


从某些方面看来,tile 布局工作起来就像一个显示函数。要使用某个 tile 布局,可使用 tiles:insert 标签来调用它。调用 tile 布局时要向它传递参数。这些参数将成为该 tile 布局的属性;例如,参数将放入 tile 范围。

调用 tile 时传递的参数可以是其他 JSP 页面或 Web 资源,您可以将它们插入布局中的预定义位置(称为 区域)。参数还包含能够插入 tile 布局的字符串。事实上,可以将许多类型的对象作为参数传递给 tile。这些参数会成为仅对该 tile 可用的 tile 范围内的属性。

tile 范围 类似页面范围,因为 tile 范围比请求范围更特殊化。 tile 范围允许 tile 用户给 tile 传递参数(称为属性)。tile 范围允许您传递仅对该 tile 布局或 tile 可用的变量(称为属性)。 特殊自定义标签允许您将属性从 tile 范围复制到页面、请求、会话或应用程序范围,或者将属性作为包含的 Web 资源来显示。



默认参数


有些编程语言,比如 C++、Visual Basic 和 Python,允许您向函数和方法传递默认参数。为进一步扩展这个显示函数,Tiles 框架还允许您向 tile 布局传递默认参数。为此,您必须定义一个 tile 定义 。 Tile 定义允许您定义 tile 的默认参数。Tile 定义(definition)可以在 JSP 代码或 XML 中定义。

像类扩展其他类一样,定义可以扩展其他定义。通过使用定义和 tile 布局,您能够创建可重用的显示组件。

可以结合 Struts 使用 Tiles,也可以在没有 Struts 的情况下使用 Tiles。要结合 Struts 使用 Tiles,您将使用 Struts 附带的 Tiles 标签库。 此外,Tiles 框架包括它自己的 RequestProcessor,用于将 tile 布局作为 ActionForward 来处理――从而允许您转到 tile 定义而不是转到 JSP 页面。Tile 是通过在它的 RequestProcessor 中重写 processActionForward 来实现这点的。



典型的 tile 布局


典型的 tile 布局可能为页眉、页脚、菜单和正文定义矩形区域,如图 1 所示。


图 1 所示的区域可以映射到类似图 2 所示的某个 Web 站点。


注意,只需传递正确的参数,就能够容易地重新定义这个应用程序的可重用部分。例如,雇员清单可能使用相同的页眉和页脚,但是使用不同的菜单和正文,同时仍然能够使用 tile 布局所定义的全部通用布局区域。这样允许对不同的内容重用相同的 tile 布局。 与包括 HTML 标记不同的是,您将在标记中包括内容。

Jakarta Struts编程:使用Tiles,第二部分

安装和配置Tiles

在您能够使用Tiles 框架之前,您必须确保它已安装并正确的配置在web容器中。Tiles框架并不依赖于某种特定的容器,您要做的就是获得所需的文件,并将它们放到web应用程序的正确位置上。


下载Tiles

Tiles 框架包含在struts发行版中。先前版本中,它位于contrib文件夹中,但现在是核心的一部分。您还可以在http: //www.lifl.fr/~dumoulin/tiles/index.html找到最新的源程序、二进制发行版本,以及其它一些有用的信息。


安装所需的JAR文件和相关文件

第一步是安装所需文件。对于Tiles来说,以下文件必须位于WEB-INF/lib目录中:

tiles.jar
commons-digester.jar
commons-beanutils.jar
commons-collections.jar
commons-logging.jar


如果您在使用struts,这些文件就已经存在了,此外您还需要安装Tiles TLD文件到应用程序的WEB-INF目录。

警告:不要为了避免将tiles.jar文件放到每个web应用程序的WEB-INF/lib目录,而将它放到servlet容器的classpath路径中,如果这样做的话会导致抛出ClassNotFoundException异常。

您还应该将tiles-config.dtd文件放到WEB-INF 目录。该DTD文件用来验证Tiles 定义文件(它将在本章的后面部分讲到)。


添加Tiles标签库

就象 其它的JSP标签库一样,在您能使用它们之前,您必须将Tiles标签库加入web应用程序发布描述文件中。给web.xml文件增加如下taglib元素:

<taglib>
<taglib-uri>/WEB-INF/tiles.tld</taglib-uri>
<taglib-location>/WEB-INF/tiles.tld</taglib-location>
</taglib>


如果您在使用标准的struts标签库,那么taglib元素应该已经有了。每个需要使用Tiles标签库的页面必须在顶部包含如下行:
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>


配置Tiles和Struts协同工作

Tiles框架可以和struts一起使用,也可单独使用。取决于您如何使用它,为web应用程序配置tiles可以有几种选择。因为本书是讲struts的,所以我们的重点是如何将其捆绑到struts应用程序。


提示:若使用tiles框架的先前版本,您必须在web.xml文件中配置一个叫做ActionComponentServlet的特殊 ActionServlet,而且在Struts的controller元素中还需配置一个RequestProcessor。现在这些不需了-现在有一个tiles插件,它来完成所有的初始化。

如果您正计划使用tiles,该插件是非常需要的。您也可不配置该插件而使用tiles库和struts。但是,配置它也没有什么害处,如果您以后决定使用tiles定义,它还可能节约您的时间。

在struts应用程序中加入tiles插件,请在struts配置文件中加入下列plug-in元素:

<plug-in className="org.apache.struts.tiles.TilesPlugin" >
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
<set-property property="definitions-debug" value="2" />
<set-property property="definitions-parser-details" value="2" />
<set-property property="definitions-parser-validate" value="true" />
</plug-in>


在plug-in元素中,您可以加入几个set-property元素给Plugin类传入附加的参数。definitions-config参数指定包含tiles定义的xml文件。如果使用了多个文件名,则它们之间用逗号分隔。

definitions-debug参数指定调试的层次,允许值为:

0 :不输出调试信息。

1 :提供部分调试信息。

2 :提供完整的调试信息。

缺省值为0。

definitions-parser-details参数指定当定义文件被解析时所需要的调试信息的层次,该值传给Commons Digester。所允许的值同definitions-debug参数,缺省值为0。

definitions-parser-validate参数指明解析器是否验证Tiles配置文件,允许值为true和false,缺省值为true。

还有一个叫做definitions-factory-class的参数没有显示出来。您可以创建一个自定义工厂,然后在这里给出类名,缺省值为org.apache.struts.tiles.xmlDefinition.I18NfactorySet。
December 2009
S M T W T F S
November 2009January 2010
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31