在网页开发中, 大部分网页都具有相同的页头, 页尾, 菜单等模块. 一般情况下我们会将这些共用的代码单独抽取成一个页面, 然后进行包含. 虽然这样能够达到代码复用的效果, 但是如果引入的页面过多, 一来会带来修改不变的效果, 二来依然会形成多个页面使用相同的代码 (页面包含代码), 此时我们可以使用 SiteMesh3 来妥善解决这个问题
最初页面形式
使用 JSP 进行页面包含
进行页面包含后, 能达到一些共用页面的代码复用, 但是如果页面布局复杂的话, 会存在大量的页面包含代码, 依然给我们带来了不便
SiteMesh3 方式
SiteMesh3 使用演示
使用 SiteMesh3 时需要先定义一个装饰器, 在这个装饰器中我们可以定义页面的布局, 然后配置动态内容输出位置即可
示例如下
header
假如此时存在一个这样的原始页面
title
hello,world
经过 SiteMesh3 装饰后的页面如下
title
header
hello,world
可以发现使用 SiteMesh3 进行装饰能够让我们更加专注于一些与页面独有的代码逻辑, 能避免相同的代码在多个页面重复出现
SiteMesh3 使用说明
通过上面的一个小例子, 我们可以发现使用 SiteMesh3 需要一个装饰器页面. 由此可以牵扯出另外几个问题, 对哪些页面进行装饰? 使用哪个装饰页面装饰?
通过以下配置可以完成这些疑问
首先我们需要引入 SiteMesh3 相关的 jar 包
org.sitemesh
sitemesh
3.0.1
其次, SiteMesh3 会对一些页面进行装饰, 所以我们需要添加一个过滤器来进行页面过滤
sitemesh
org.sitemesh.config.ConfigurableSiteMeshFilter
sitemesh
/*
同时我们还需要配置装饰器, 要装饰的页面, 不需要装饰的页面等信息
在 WEB-INF
目录下创建一个 sitemesh3.xml
文件,请确保路径正确,SiteMesh3会根据 /WEB-INF/sitemesh3.xml
加载文件
文件内容如下
此时我们可以将上面演示中的文件内容建立 index.jsp
和 default.jsp
页面, 然后进行测试访问, 会发现能达到演示中的效果
SiteMesh3 高级配置
通过上面的简单配置我们可以实现一个最基本的页面装饰, 与此同时 SiteMesh3 还支持一些更为高级的配置
- 默认装饰器
- 多个装饰器
/multi.jsp
/decorators/multi_1.jsp
/decorators/multi_2.jsp
/decorators/multi_3.jsp
装饰器会按照配置的先后顺序进行装饰
假如
multi.jsp 中 body 内容为 0,
multi_1.jsp 中内容为 1 同时在下面输出原始页面中的body内容
1
multi_2.jsp 中内容为 2 同时在下面输出原始页面中的body内容
最终返回的页面内容为
2
1
0
- 不需要装饰
- MIME 类型
text/html
application/vnd.wap.xhtml+xml
application/xhtml+xml
- 自定义输出标签
ExpandTagRuleBundle 代码如下
public class ExpandTagRuleBundle implements TagRuleBundle {
@Override
public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {
defaultState.addRule("header", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("header"), false));
defaultState.addRule("menu", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("menu"), false));
defaultState.addRule("footer", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("footer"), false));
}
@Override
public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {
}
}
此时可以使用
标签在装饰器中输出原始页面的 header 标签值
-
其他说明
-
title
,head
,body
标签的实现请参考org.sitemesh.content.tagrules.html.CoreHtmlTagRuleBundle
-
title
,head
,body
等自定义标签只会提取原始页面中的第一个找到的标签 - 默认配置文件路径为
/WEB-INF/sitemesh3.xml
,如果需要自定义配置路径,请在配置filter
时配置configFile
属性,如将sitemesh3.xml
配置文件放在resources
文件夹中
sitemesh org.sitemesh.config.ConfigurableSiteMeshFilter configFile /WEB-INF/classes/sitemesh3.xml - 如果装饰器是
html
文件会存在中文乱码的问题, 在 SpringMVC 中可在web.xml
文件配置如下过滤器
CharacterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 forceEncoding true CharacterEncodingFilter /* - 在 SpringMVC 中因为 SiteMesh3 需要直接访问到装饰页面, 所以需要增加如下标签
- 如果装饰器为 JSP 页面, 则可以使用 EL 表达式获取原始页面中的属性
假如在 SpringMVC 中设置如下属性
@RequestMapping(value = "/index") public String index(Model model) { model.addAttribute("date", new Date().toLocaleString()); return "index"; }
则可以在方法返回页面 `/index.jsp` 和该 url 的装饰页面 `/decorators/default.jsp` 中使用 EL 表达式获取 `date` 属性
-
参考资料
SiteMesh3 官网文档
SiteMesh3 GitHub