Tiles的使用(二)- -
Tiles定义
我们需要一种方法,在一个单独的可复用文件中定义所有的attributes和properties,当参数改变时能够重载这个文件,这就是Tiles Definitions要做的事情。好,下面就来吧!
1.)声明Definitions
我们需要一种方法,在一个单独的可复用文件中定义所有的attributes和properties,当参数改变时能够重载这个文件,这就是Tiles Definitions要做的事情。好,下面就来吧!
1.)声明Definitions
所需信息:模板路径,零个或多个属性(属性名和值对),唯一标示符。
如你所见,Definitions和<tiles:insert> 标记间真正的不同在于Definition 可以命名。尽管只加入了一个标识符,却拥有了新的特性:
如你所见,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.。作为一个Bean中保存在JSP中,用id 作为属性标识。<tiles:definition>标签支持scope属性,默认为page。这个Definitions只对该JSP余下的部分有效。
部署声明的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/> |
要使用声明的Definition,可以用<tiles:insert>标记,通过id名称来调用上面声明的Definition。
启动时,Tiles 使用XML 元素的id definitionName 创建一个Definition对象(或bean)。
运行时,<tiles:insert> 标记通过beanName 属性引用定义id。
重载:可以重载某些或全部属性。重载时,只需要一个新的属性值。要创建一个新的属性,包含一个新的属性名称和值就可以了。
启动时,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> |
这段代码可以看到,body使用了一个新的属性值。还新增加了extra属性,这就意味着布局(layout)没有管理到这个tile,但如果提供也可以显示。布局时可以使用ignore标签,当ingore设置为true时,如果属性不存在将不会报告错误。父类Definition继承来的myLayout.jsp怎样要添加一个extra tile::
|
<tiles:insert attribute="extra" ignore="true" />
|
复用Definition:在上面的例子中看到,我们在重载某些属性前不得不重复的Definitions,这当然是非常不实际的方法。有一种更加简单的好方法,看下面的例子:
|
<%@ 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> |
使用标准的JSP include标签把Definition引入,你能够想平常一样使用Definition。在例子中,也重载了title和body属性。这种复用的方法对于拥有少量Definition来说是好的。但有个缺点,每次文件被include的时候,会把Definitions重新创建执行,这就影响了性能。在开发过程中这仍是个好方法,因为对Definition的修改在下次页面装载时就会体现出来。通常可以这样使用,在一个工作区中创建一个带有scope属性的Definition,再用Structs的<logic:notPresent>块来包含:
|
<%@ 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> |
这样做就不会重新创建Definitions了。每个页面仍然需要包含Definition并检查是否存在,但至少它们不需要再被不断创建了。
Tiles提供一个更好的方法来一次性装载和复用Definition:使用XML文档。Definition直接用来ActionFrowards。这是个管理Tiles Definitions的好方法,请看下面的内容。
Tiles提供一个更好的方法来一次性装载和复用Definition:使用XML文档。Definition直接用来ActionFrowards。这是个管理Tiles Definitions的好方法,请看下面的内容。
3.)使用配置文件声明
在一个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>标记相似:
在一个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> |
扩展Definitions:一个Definition能够被声明为另一个Definition的子类。新的Definition继承了父类Definitions的所以东西。
|
<definition name="portal.page" extends="portal.masterPage"> <put name="title" value="Tiles 1.1 Portal" /> <put name="body" value="portal.body" /> </definition> |
这种继承能力允许我们声明一个父Definition(设置缺省的属性),然后以特定的属性来扩展Definition(如title 和body)。如果你的所有定义都是从一个父Definition中扩展而来,那么在父Definition中的修改就会影响到所有从它扩展的Definition。这和重载很相似但增加了持久性。重载描述了我们在哪里标识了Definition,并且传递给他新的参数(或者属性), 就象调用一个方法,并传递给它参数。但重载不能在一个<tiles:insert>标签中调用另一个<tiles:insert>,所以重载Definitions是不能被引用和复用的。通过使用extend 属性就可以创建一个新的Definition。这个新的Definition可以被插入和重载,甚至被其他Definition扩展,它通过继承关系仍然指向它们的祖先Definition。重载或扩展一个Definitions能显著的减少页面多余的信息。每个标签,导航栏和内容组件在你的web站点中只要声明一次。这些组件就能被复用到任何你想要的地方了。
这非常的酷!但我们需要一个额外的页面来放置Definition,意思是说要添加一个新内容的页面(content page),就要新增一个页面,然后再用一个页面来插入这个标识新内容的Definition。如果一个普通的应用程序有60个内容页面,就会有60个页面,那一个模板应用程序就至少会有120个页面来包含所有内容。模板页面比其常规页面要小巧而简单,但文件的管理还是个问题。一个好的解决放方案是用Structs ActionFrowards来放置Definition。
这非常的酷!但我们需要一个额外的页面来放置Definition,意思是说要添加一个新内容的页面(content page),就要新增一个页面,然后再用一个页面来插入这个标识新内容的Definition。如果一个普通的应用程序有60个内容页面,就会有60个页面,那一个模板应用程序就至少会有120个页面来包含所有内容。模板页面比其常规页面要小巧而简单,但文件的管理还是个问题。一个好的解决放方案是用Structs ActionFrowards来放置Definition。
将Definitions作为ActionForwards:
在Structs应用程序中,大多数的页面不会被直接引用,而是封装到ActionForward对象中。ActionForward给出一个唯一的逻辑名称对应实际的URL,Action选择和返回一个ActionForward给servlet控制器,ActionServlet通过ActionForward的路径值控制转发到指定的URL上。Tiles包包含一个ActionServlet的子类来检查和Definitions有关的路径值。如果Definitions的id和ActionForward的path匹配,Definitions bean被放置在request中,控制器会转发到布局,你组装好的模板就会显示。
在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> |
然而,用斜杠的方式可能和与Action 和页面URI 相关的标识符相冲突。推荐在Tile 定义中使用点号,而在ActionForward 中使用斜杠语法,确保名称是会冲突。Action类常会忽略ActionFrom路径,而是通过它的名称来处理。所以用Tiles Definition来代替URL,大部分Action类不需要重新构建。你可以混合使用常规的ActionForwards和Tiles-Definition-ActionForwards,这样模板页面的数量会明显的下降。对需拥有60个页面的应用程序,我们只需要60个内容页面加上少量提供标准的导航和布局的工具tile 。但是创建第61 个页面时,只需要再创建一个提供内容的JSP 和一个XML Definition,而后者只不过是简单的一行文字。
Tiles属性
1.)useAttribute
<tiles:useAttribute>标签,使某个Tiles 的属性在整个页面中有效。其它标签(像Struts <bean:write>)能引用的名称用来传递参数。
<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" /> |
<useAttribute> 标记与<useBean> 动作和Struts <bean:define> 标记相对应,允许访问Tiles中的属性。
每个tile 都是一个不同的"页面",每一个都有自己的页面范围。如果你想避免tile间的属性冲突,可以使用page scope。如果你想一个属性被另一个tile 共享,你可以使用request scope:
<tiles:useAttribute name="myAttribute" scope="request"/>
<useAttribute>的操作是按顺序。页面中后面tile也许可以使用某个属性,而先前的tile也许不能使用它,因为它还不存在。
2.)inportAttribute
<tiles:importAttribute>标签,和<useAttribute>不一样,它不支持重命名和作为脚本变量使用。
每个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 |
3.)put
<tiles:put>标签,被用来联系属性和属性值,name属性用字符串来指定,属性值分三种:tag property,tag body,JavaBean。
<tiles:put>标签,被用来联系属性和属性值,name属性用字符串来指定,属性值分三种:tag property,tag body,JavaBean。
4.)putList and add
|
<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" />
或:<tiles:put name="title" value="<%=myObject%>" /> // 是运行时的表达式
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title">My first page</tiles:put>
或:<tiles:put name="title"><bean:write message="first.pageTitle"/></tiles:put> // 是标记体
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" beanName="myBean" beanScope="session" /> /* 获取beanName标识的对象,然后其值被用作为属性值。beanScope用来搜索bean的作用域,如果没指定会调用pageContext.findAttribute()方法,这边添加了Tiles中专有的"tiles"的作用域(支持page,request,application),用来在tiles中搜索bean。*/
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" beanName="myBean" beanProperty="myProperty"/> // 相当于调用myBean.getMyProperty()来
或:<tiles:put name="title" value="<%=myObject%>" /> // 是运行时的表达式
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title">My first page</tiles:put>
或:<tiles:put name="title"><bean:write message="first.pageTitle"/></tiles:put> // 是标记体
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" beanName="myBean" beanScope="session" /> /* 获取beanName标识的对象,然后其值被用作为属性值。beanScope用来搜索bean的作用域,如果没指定会调用pageContext.findAttribute()方法,这边添加了Tiles中专有的"tiles"的作用域(支持page,request,application),用来在tiles中搜索bean。*/
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" beanName="myBean" beanProperty="myProperty"/> // 相当于调用myBean.getMyProperty()来
// 指定tile的属性值
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="footer" value="/tiles/footer.jsp" type="page"/> //type有三种:string -- value值做为字符串输出;
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="footer" value="/tiles/footer.jsp" type="page"/> //type有三种:string -- value值做为字符串输出;
// page-- value值做为一个URL;
// definition-- value值做为Definition名称
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" value="myValue" role="myManager"/>
/* 当使用基于容器的安全认证时,你也可以为一个tile指定role,如果用户不是指定的role,value值就不会被设置,这允许你为每个安全角色指定一个tile,而让框架为当前的用户选择相应的Tile。 如果<put>用在<tiles:insert>标签中,role立即被验证,用在<tiles:definition>中,role在Tiles内容初始化时被验证。 */
------------------------------------------------------------------------------------------------------------------------------------------
<tiles:put name="title" value="myValue" role="myManager"/>
/* 当使用基于容器的安全认证时,你也可以为一个tile指定role,如果用户不是指定的role,value值就不会被设置,这允许你为每个安全角色指定一个tile,而让框架为当前的用户选择相应的Tile。 如果<put>用在<tiles:insert>标签中,role立即被验证,用在<tiles:definition>中,role在Tiles内容初始化时被验证。 */
本文深入讲解了Tiles框架的高级应用,包括定义的声明、部署、重载及复用等技巧,并探讨了如何通过JSP和XML配置文件声明定义,以及如何利用ActionForward实现定义的灵活使用。
1369

被折叠的 条评论
为什么被折叠?



