sitemesh 是一个布局管理插件,用于 Java Web 工程,由 webwork2 团队开发,目前稳定版本是2.4.2,诞生于2009-04-16,有多年没有更新了,可见还是蛮稳定的。sitemesh3 在2015年发布。sitemesh 官网是:http://wiki.sitemesh.org/wiki/display/sitemesh/Home
sitemesh 是装饰器模式(Decorator Pattern)的一个实现,它的工作原理借用官网的图说明如下:
1. 浏览器发出请求
2. 服务端用模板对目标页面进行装饰
3. 返回用户装饰後的页面
(来源:http://wiki.sitemesh.org/wiki/display/sitemesh/Start+Using+SiteMesh+in+10+Minutes)
sitemesh 可以单独使用,也可以作为 Struts 2 的插件使用,但它们的配置方式是不一样的,特别是在和 Struts 2 集成时,需要修改 Struts 2 的过滤器设置。以下分别叙述。
单独使用 sitemesh, 可以使用2.4.2,也可以使用3系列的 alpha 版本,以下都会描述。
1. 添加依赖
为项目加入相应 jar 包,可以直接在官网下载,如果使用 maven.
sitemesh2 相应配置是:
<dependency>
<groupId>opensymphony</groupId>
<artifactId>sitemesh</artifactId>
<version>2.4.2</version>
</dependency>
sitemesh3 相应的配置是:
<!-- https://mvnrepository.com/artifact/org.sitemesh/sitemesh -->
<dependency>
<groupId>org.sitemesh</groupId>
<artifactId>sitemesh</artifactId>
<version>3.0.1</version>
</dependency>
2. 添加过滤器
在 WEB-INF/web.xml 中修改,
sitemesh2:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
sitemesh3:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3. 设置 Decorator 规则
sitemesh2:
在 WEB-INF 下新增 decorators.xml 文件,示例内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<decorators defaultdir="/jsp/decorator">
<excludes>
<pattern>/jsp/decorator/*</pattern>
</excludes>
<decorator name="main" page="decorator.jsp">
<pattern>/jsp/sys/*</pattern>
<pattern>/jsp/tada/*</pattern>
<pattern>/tada/*</pattern>
<pattern>/sys/*</pattern>
</decorator>
</decorators>
sitemesh3:
在 WEB-INF 下新增 sitemesh3.xml 文件,示例内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<sitemesh>
<mapping path="/*" decorator="/jsp/decorator/decorator.jsp"/>
<mapping path="/index.jsp" exclue="true"/>
<mapping path="/jsp/sys/register.jsp" exclue="true"/>
</sitemesh>
以上两个版本的 decorator 配置文件,都能望文生义,不再解释。
4. Decorator 页面
Decorator 页面通过标签标识要装饰的内容。
sitemesh2 用 <decorator: xxx /> 的方式:
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>PIS: <decorator:title /> </title>
<link rel="shortcut icon" href="<%=path%>/favicon.ico" />
<link rel="icon" type="image/gif" href="<%=path%>/animated_favicon1.gif" />
<link href="<%=path%>/css/layout.css" rel="stylesheet" type="text/css" />
<decorator:head/>
</head>
<body>
<div id="container">
<div id="top"><%@ include file="top.jsp"%></div>
<div id="menu"><%@ include file="menu.jsp"%></div>
<div id="mainContent">
<div id="sidebar"><%@ include file="left.jsp"%></div>
<div id="content">
<decorator:body />
</div>
</div>
<div id="bottom"><%@ include file="bottom.jsp"%></div>
</div>
</body>
</html>
sitemeth3 用 <sitemesh:write property='xxx' /> 的方式:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>PIS: <sitemesh:write property='title' /></title>
<link rel="shortcut icon" href="<%=path%>/favicon.ico" />
<link rel="icon" type="image/gif" href="<%=path%>/animated_favicon1.gif" />
<link href="<%=path%>/css/layout.css" rel="stylesheet" type="text/css" />
<sitemesh:write property='head' />
</head>
<body>
<div id="container">
<div id="top"><%@ include file="top.jsp"%></div>
<div id="menu"><%@ include file="menu.jsp"%></div>
<div id="mainContent">
<div id="sidebar"><%@ include file="left.jsp"%></div>
<div id="content">
<sitemesh:write property='body' />
</div>
</div>
<div id="bottom"><%@ include file="bottom.jsp"%></div>
</div>
</body>
</html>
sitemesh 一般以插件方式与 Struts 2 集成,被集成的版本,依赖 Struts 2 的版本,据我观察,目前 Struts 2.16.3 集成的是 sitemesh 2.4.2
1. 【pom.xml dependency】
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts2.version}</version>
</dependency>
2. 【web.xml filters】
<filter>
<filter-name>struts2-prepare</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2-prepare</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts2-execute</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2-execute</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.apache.struts2.dispatcher.ng.listener.StrutsListener</listener-class>
</listener>
参考:
http://struts.apache.org/release/2.3.x/docs/sitemesh-plugin.html
这里需要特别注意,Struts 2 的 filter 分成了两个:
并将 sitemesh 的 filter 放置在它们之间。sitemesh 的 filter 所用的类也和前述单独使用的情况不同。
而通常,Struts 2 配置一个 filter 就够了:
如果集成 sitemesh 不这样配置 filter,将出现严重的问题:用于装饰的页面中 Struts 2 标签不能使用,并将报500错误。