Tiles的使用(二)- -
我们需要一种方法,在一个单独的可复用文件中定义所有的attributes和properties,当参数改变时能够重载这个文件,这就是Tiles Definitions要做的事情。好,下面就来吧!
1.)声明Definitions
如你所见,Definitions和<tiles:insert> 标记间真正的不同在于Definition 可以命名。尽管只加入了一个标识符,却拥有了新的特性:
- 可以通过传递附加或替换属性而重载
- 可以通过父类Definitions扩展为其他Definitions
- 可以通过存储在一个JSP 中的Definitions或者从一个XML 文档中装载而重用
- 可以是Struts ActionForward 的目标
有两种方法来声明Definitions:JSP和XML文档。
2.)JSP声明
这是个简单快速的方法。它不能减少你模板文件的数量,但可以通过重载来复用。在运行时需要用一个存根(stub)文件来部署Definitions。在下一节,我们将看到将这些相同的Definitions将放入到一个XML 文档,然后直接从Struts ActionForward 中进行部署,基本的流程都是一样的。过程是:声明-部署-重载-复用。
用一个JSP声明一个Definitions:
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> |
部署声明的Definition:
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> <tiles:insert beanName="definitionName" flush="true/> |
启动时,Tiles 使用XML 元素的id definitionName 创建一个Definition对象(或bean)。
运行时,<tiles:insert> 标记通过beanName 属性引用定义id。
重载:可以重载某些或全部属性。重载时,只需要一个新的属性值。要创建一个新的属性,包含一个新的属性名称和值就可以了。
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> <tiles:insert beanName="definitionName" flush="true" > <tiles:put name="title" value="New PageTitle" /> <tiles:put name="body" value="/tiles/anotherBody.jsp" /> <tiles:put name="extra" value="/extra.jsp" /> </tiles:insert> |
<tiles:insert attribute="extra" ignore="true" /> |
<%@ taglib uri="/tags/tiles" prefix="tiles" %> <%@ include file="definitionsConfig.jsp" %> <tiles:insert beanName="definitionName" beanScope="request" /> <tiles:put name="title" value="Another Page" /> <tiles:put name="body" value="/tiles/anotherBody.jsp" /> </tiles:insert> |
<%@ taglib uri="/tags/struts-logic" prefix="logic" %> <%@ taglib uri="/tags/tiles" prefix="tiles" %> <logic:notPresent name="definitionName" scope="application"> <tiles:definition id="definitionName" page="/layouts/myLayout.jsp"> <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:definition> <%-- … other definitions … --%> </logic:notPresent> |
Tiles提供一个更好的方法来一次性装载和复用Definition:使用XML文档。Definition直接用来ActionFrowards。这是个管理Tiles Definitions的好方法,请看下面的内容。
在一个XML 配置文件中声明你的Definition,应用程序在启动时装载这个文件,并创建一个包含Definition的"Definition factory"。每个Definition用其属性名称来标识,并且要是唯一的。其他组件如ActionForward,就可以通过这个名称来引用Definition。在一个XML 配置文件中声明Tiles Definition需要一些额外的设置,以允许在应用程序初始化时可以读取并装载配置文件。《Structs in action》第4 章中,可以得到关于如何在Struts 1.1 中安装Tiles。应用程序初始化时,XML 配置文件被读取,然后解析到一个"Definition factory"中,该工厂包含了每个声明过的Definition的实例。每个Definition应该有其唯一的名称,以便它可以被JSP 标记或者StrutsActionForward 引用。定义的名称及用作内部引用。它不是一个URI,不能直接被客户端引用。使用XML 文档的定义宣称的流程和使用JSP 的处理并没有什么太大的不同。主要的不同点是他们如何被创建,如何被扩展,以及Definition如何可以被Struts ActionForward 使用。
创建配置文件:
XML 配置文件的总体格式有点类似于Struts 配置文件。令人惊讶的是,XML 配置文件文件之中使用的语法和Tiles <definition>标记相似:
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd"> <tiles-definitions> <definition name="definitionName" page="/layouts/myLayout.jsp"> <put name="title" value="Hello World" /> <put name="header" value="/tiles/header.jsp" /> <put name="footer" value="/tiles/footer.jsp" /> <put name="menu" value="/tiles/menu.jsp" /> <put name="body" value="/tiles/helloBody.jsp" /> </definition> <!-- ... more definitions ... --> </tiles-definitions> |
<definition name="portal.page" extends="portal.masterPage"> <put name="title" value="Tiles 1.1 Portal" /> <put name="body" value="portal.body" /> </definition> |
这非常的酷!但我们需要一个额外的页面来放置Definition,意思是说要添加一个新内容的页面(content page),就要新增一个页面,然后再用一个页面来插入这个标识新内容的Definition。如果一个普通的应用程序有60个内容页面,就会有60个页面,那一个模板应用程序就至少会有120个页面来包含所有内容。模板页面比其常规页面要小巧而简单,但文件的管理还是个问题。一个好的解决放方案是用Structs ActionFrowards来放置Definition。
在Structs应用程序中,大多数的页面不会被直接引用,而是封装到ActionForward对象中。ActionForward给出一个唯一的逻辑名称对应实际的URL,Action选择和返回一个ActionForward给servlet控制器,ActionServlet通过ActionForward的路径值控制转发到指定的URL上。Tiles包包含一个ActionServlet的子类来检查和Definitions有关的路径值。如果Definitions的id和ActionForward的path匹配,Definitions bean被放置在request中,控制器会转发到布局,你组装好的模板就会显示。
<action path="/tutorial/testAction2" type="org.apache.struts.example.tiles.tutorial.ForwardExampleAction"> <forward name="failure" path=".forward.example.failure.page"/> //这边可以使用斜杠代替圆点:path="/forward/example/failure.page" <forward name="success" path=".forward.example.success.page"/> </action> |
<tiles:useAttribute>标签,使某个Tiles 的属性在整个页面中有效。其它标签(像Struts <bean:write>)能引用的名称用来传递参数。
<tiles:useAttribute name="myAttribute" /> <tiles:useAttribute attributeName="anAttribute" name="myAttribute" /> //标识另外一个属性名称 <bean:write name="myAttribute" /> //Struts bean 标记既可以引用这个信息 ------------------------------------------------------------------------------------------------------------------------------------------ 也可以用来声明一个脚本变量供JSP scriptlet使用: <tiles:useAttribute id="list" name="myAttribute" classname="java.util.List" /> |
每个tile 都是一个不同的"页面",每一个都有自己的页面范围。如果你想避免tile间的属性冲突,可以使用page scope。如果你想一个属性被另一个tile 共享,你可以使用request scope:
<tiles:useAttribute name="myAttribute" scope="request"/>
<useAttribute>的操作是按顺序。页面中后面tile也许可以使用某个属性,而先前的tile也许不能使用它,因为它还不存在。
2.)inportAttribute
<tiles:importAttribute>标签,和<useAttribute>不一样,它不支持重命名和作为脚本变量使用。
<tiles:importAttribute/> //把所有的tile属性导入到页面作用域中 <tiles:importAttribute name="myAttribute" scope="request"/> //指定某个属性的scope,scope默认值是page |
<tiles:put>标签,被用来联系属性和属性值,name属性用字符串来指定,属性值分三种:tag property,tag body,JavaBean。
<tiles:insert page="menu.jsp" > <tiles:putList name="items"> <tiles:add value="home" /> <tiles:add value="documentation"/> </tiles:putList> </tiles:insert> // 两个标签联合使用,指定一个列对象作为单一属性进行传递。 ------------------------------------------------------------------------------------------------------------------------------------------ <tiles:importAttribute/> <TABLE> <logic:iterate id="item" name="items" > <TR> <TD> <bean:write name="item"> </TD> </TR> </logic:iterate> </TABLE> //<putList>标签常和<useAttribute>或<importAttribute>一起使用,以便能在一个页面访问别的标签。 |
<tiles:put name="title" value="My first page" /> |