传统的 Web 项目中经常使用 Iframe 来进行 Web 视图页面的布局。在 Struts 中也提供了一个名为 tiles 的插件来实现页面布局。而在 Struts2 中则提供了一个名为 sitemesh 的开源产品整合在 Struts2 中进行页面布局。本章就详细介绍 sitemesh 在 Struts2 中的整合使用方法。
笔者在征得客户同意情况下,本章示例是一真正在使用项目。而笔者修改了其中部分代码,用以实现 sitemesh 的使用方式。
以一装修网站首页为示例,介绍 sitemesh 的使用方式。
装饰模式的 Web 布局实现。
web.xml 文件中调用 sitemesh 。
struts.xml 中有关 result 类型和 sitemesh 关系。
首先看 web.xml 文件涉及 sitemesh 部分代码:
<!-----------------------文件名:web.xml------------> ……… <filter> <!-- 定义sitemesh过滤器 --> <filter-name>sitemesh</filter-name> <!-- 定义sitemesh过滤器类文件路径 --> <filter-class> com.opensymphony.module.sitemesh.filter.PageFilter </filter-class> </filter> <filter-mapping> <!-- 定义sitemesh过滤器映射名 --> <filter-name>sitemesh</filter-name> <!-- 定义sitemesh过滤器对根目录下所有文件进行过滤 --> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>jsp/body/firstPage.jsp</welcome-file> </welcome-file-list> ………
Sitemesh 定义装饰器的 decorators.xml 文件:
<!---------------文件名:decorators.xml-----------------> <?xml version="1.0" encoding="gb2312"?> <decorators defaultdir="/jsp/template"> <!-- excludes标签中定义不会被装饰的JSP视图界面 --> <excludes> <pattern>/jsp/layout/*</pattern> <pattern>/jsp/template/*</pattern> <pattern>/jsp/image.jsp</pattern> </excludes> <!-- 定义装饰器,该装饰器为一个页面格式分为上中下三块的JSP视图界面--> <decorator name="template" page="3PartLayoutTemplate.jsp"> <pattern>/jsp/*</pattern> <pattern>/jsp/body/*</pattern> </decorator> </decorators>
被定义的装饰器 JSP 视图界面代码:
<!---------------文件名:3PartLayoutTemplate.jsp---------------> <%@ page contentType="text/html; charset=gb2312"%> <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%> <html> ………… <head> <!-- 被装饰页面的<title>中内容在这里填充 --> <title> <decorator:title default="sitemesh页面" /> </title> ……… </head> <body bgcolor="#f7c800" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> <jsp:include page="/jsp/layout/head.jsp" flush="true" /> <!-- 被装饰页面的<body>中内容在这里填充 --> <decorator:body /> <jsp:include page="/jsp/layout/bottom.jsp" flush="true" /> </body> </html>
定义 Action 的 struts.xml 文件代码:
<!----------------------文件名:struts.xml----------------> ………… <action name="index" > <result type="redirect">/jsp/body/firstPage.jsp</result> </action> …………
显示效果如图 10.1 。
图 10.1 sitemesh 使用后页面布局显示效果图
( 1 ) 首先说明开发中如果要使用 sitemesh 来进行页面布局功能开发,在 WEB-INF/lib 文件夹下一定要放入 sitemesh 支持的 jar 包。目前 sitemesh 最新版本是 sitemesh-2.3.jar 。
( 2 )然后在 web.xml 中必须定义 sitemesh 为过滤器。这样 Web 项目中的 JSP 或其他视图界面都可以被 sitemesh 调用进行页面布局。然后新建 decorators.xml 文件。该文件是用来定义所有装饰器视图界面。因为 sitemesh 是使用设计模式中的装饰模式来进行页面布局功能开发(具体装饰模式定义读者可查看相关设计模式资料)。在这里笔者只能简单说明 sitemesh 将视图页面分为装饰页面和被装饰页面两种。装饰页面又称之为装饰器。都是在 decorators.xml 文件定义,一般定义装饰器时候都指定了被装饰页面或者某文件路径,在该文件路径下的所有视图界面文件都是被装饰页面。
读者可以查看 decorators.xml 文件代码看到 <excludes> 标签,在该标签中一般都是指定不需要被装饰的视图文件。以 <pattern> 标签来一个个定义。有代码也可知道“ /jsp/layout/* ”标明在 /jsp/layout/ 目录下所有的视图界面都是不需要被装饰的。如果想指定某个视图文件不被装饰,则可以写成代码中“ /jsp/image.jsp ”形式,这样在 jsp 目录下只有 image.jsp 文件不被装饰,其他视图界面都是要被装饰的。
<decorator> 标签则是相关装饰器页面定义需要使用的标签。其中 name 属性是让开发者定义装饰器名字,而 page 属性则指定装饰器文件的路径和具体名字。在本示例代码中可知 3PartLayoutTemplate.jsp 是一个装饰器文件。
注意:在<decorators> 标签中有个defaultdir 属性,它是表明装饰器文件的路径。本示例代码中定义的是“/jsp/template ”, 也就是说之前所定义的3PartLayoutTemplate.jsp 是在该目录下。如果defaultdir 定义的是“/ ”,则装饰器定义的page 属性中定义的装饰器文件是在Web 项目根目录下。在开发环境中就是在WebRoot 文件夹下(笔者使用的是MyEclipse ,所以读者使用的开发工具不是MyEclipse 的话,则web 根目录的文件夹名字不一定是WebRoot )。如果读者想让3PartLayoutTemplate.jsp 还是在/jsp/template 目录下,而defaultdir 想定义为“/ ”,则page 属性中定义需要写成“/jsp/template/3PartLayoutTemplate.jsp ”。
在装饰器定义中,可以还是使用<pattern> 标签来指定需要被装饰的视图界面。具体做法和<excludes> 中的<pattern> 用法相同,只不过一个是指定被装饰的,另外一个指定不被装饰的。当然也可以不使用<pattern> 标签,这样可以使用 <page:applyDecorator> 标签在页面中指定需要被装饰的视图界面文件(下一小节将具体介绍如何使用),而不是在 decorators.xml 文件中指定被装饰的视图界面文件。
( 3 )在 3PartLayoutTemplate.jsp 该装饰器页面中,读者查看代码可以看见在该视图文件中,笔者先定义了 “<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%> ”用以在页面中使用<decorator> 标签 。这里只是使用了 <decorator:title> 和 < decorator:body> 两个 decorator 的基础标签。
这里 <decorator:title> 中有个 default 属性。使用该属性的目的是当被装饰视图界面文件中没有定义自己的 <title> 标签内容时候,则装饰和被装饰视图界面一起显示的页面布局界面的 title 就显示该属性中内容。在图 10.1 中,笔者也用红框特别注明了显示的 title 的内容。
而 < decorator:body> 就是表明被装饰视图界面的 <body> 中内容显示。因此可以这么理解在装饰器视图界面文件中,如果看到以 decorator 打头的标签,则是显示被装饰视图界面文件的内容。如果“:”后写的是 title 则显示的是被装饰文件中 <title> 标签中的内容。如果是 body 则显示的是被装饰文件中 <body> 标签中的内容。
在本示例中笔者将 /jsp/body/ 中的 firstPage.jsp 作为被装饰文件,在 web.xml 中定义缺省显示的就是该被装饰文件。因此运行该示例就可以看到 firstPage.jsp 不仅仅显示了自己的内容,而且将装饰器文件 3PartLayoutTemplate.jsp 中的内容也显示出来了,特别是两个<jsp:include> 的JSP 文件。给人感觉就是在3PartLayoutTemplate.jsp 显示的内容上面又加了 firstPage.jsp 内容。而被装饰的文件还可以是其他视图文件。因此在别的界面中则显示的不一定是 firstPage.jsp 内容,但是 3PartLayoutTemplate.jsp 中的内容还是会先出来的。这样就达到了页面布局的效果。
注意:开发人员还可以定义Action 来显示页面布局。在笔者使用的该示例的struts.xml 中定义了index.action ,而其中result 指向的就是 firstPage.jsp 。不过这时候 result 的 type 类型一定要是“ redirect ”(代码中黑体注明,另外说一句 result 缺省的类型是 dispatcher ,可以不显示声明)。因为如果不定义该类型,则 index.action 指向的只是单纯 firstPage.jsp 文件的内容,不会显示装饰器文件 3PartLayoutTemplate.jsp 中的内容。这和redirect 是一个重定向有关系,有关重定向的概念笔者在第二章也做过简单介绍,读者可以翻阅之前章节。