struts系列学习(tiles标签库二)

    技术2022-05-11  77

    Tiles的使用(二)- -                                        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.。作为一个Bean中保存在JSP中,用id 作为属性标识。<tiles:definition>标签支持scope属性,默认为page。这个Definitions只对该JSP余下的部分有效。部署声明的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。重载:可以重载某些或全部属性。重载时,只需要一个新的属性值。要创建一个新的属性,包含一个新的属性名称和值就可以了。  <%@ 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的好方法,请看下面的内容。   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>标记相似:    <!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。   将Definitions作为ActionForwards:       在Structs应用程序中,大多数的页面不会被直接引用,而是封装到ActionForward对象中。ActionForward给出一个唯一的逻辑名称对应实际的URL,Action选择和返回一个ActionForward给servlet控制器,ActionServlet通过ActionForward的路径值控制转发到指定的URL上。Tiles包包含一个ActionServlet的子类来检查和Definitions有关的路径值。如果Definitions的id和ActionForward的path匹配,Definitions bean被放置在request中,控制器会转发到布局,你组装好的模板就会显示。 <actionpath="/tutorial/testAction2"type="org.apache.struts.example.tiles.tutorial.ForwardExampleAction"><forwardname="failure"path=".forward.example.failure.page"/>   //这边可以使用斜杠代替圆点:path="/forward/example/failure.page"<forwardname="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 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>不一样,它不支持重命名和作为脚本变量使用。 <tiles:importAttribute/> //把所有的tile属性导入到页面作用域中<tiles:importAttribute name="myAttribute" scope="request"/>  //指定某个属性的scope,scope默认值是page 3.)put         <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()来                                                                                                             // 指定tile的属性值------------------------------------------------------------------------------------------------------------------------------------------<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内容初始化时被验证。      */  

    最新回复(0)