在网页开发中,大部分网页都具有相同的页头,页尾,菜单等模块。 一般情况下我们会将这些共用的代码单独抽取成一个页面,然后进行包含。 虽然这样能够达到代码复用的效果,但是如果引入的页面过多,一来会带来修改不变的效果,二来依然会形成多个页面使用相同的代码 (页面包含代码),此时我们可以使用 SiteMesh3 来妥善解决这个问题
最初页面形式
使用 JSP 进行页面包含
进行页面包含后,能达到一些共用页面的代码复用,但是如果页面布局复杂的话,会存在大量的页面包含代码,依然给我们带来了不便
SiteMesh3 方式
SiteMesh3 使用演示
使用 SiteMesh3 时需要先定义一个装饰器,在这个装饰器中我们可以定义页面的布局,然后配置动态内容输出位置即可
示例如下
1 |
|
假如此时存在一个这样的原始页面
1 |
|
经过 SiteMesh3 装饰后的页面如下
1 |
|
可以发现使用 SiteMesh3 进行装饰能够让我们更加专注于一些与页面独有的代码逻辑,能避免相同的代码在多个页面重复出现
SiteMesh3 使用说明
通过上面的一个小例子,我们可以发现使用 SiteMesh3 需要一个装饰器页面。 由此可以牵扯出另外几个问题,对哪些页面进行装饰? 使用哪个装饰页面装饰?通过以下配置可以完成这些疑问
首先我们需要引入 SiteMesh3 相关的 jar 包
1 | <dependency> |
其次,SiteMesh3 会对一些页面进行装饰,所以我们需要添加一个过滤器来进行页面过滤
1 | <filter> |
同时我们还需要配置装饰器,要装饰的页面,不需要装饰的页面等信息
在 WEB-INF
目录下创建一个 sitemesh3.xml
文件,请确保路径正确,SiteMesh3 会根据 /WEB-INF/sitemesh3.xml
加载文件
文件内容如下
1 |
|
此时我们可以将上面演示中的文件内容建立 index.jsp
和 default.jsp
页面,然后进行测试访问,会发现能达到演示中的效果
SiteMesh3 高级配置
通过上面的简单配置我们可以实现一个最基本的页面装饰,与此同时 SiteMesh3 还支持一些更为高级的配置
默认装饰器
1
2
3<!-- 如果不填写 path 路径, 则 SiteMesh3 会在找不到匹配的装饰器时, 使用这个装饰器进行装饰 -->
<!-- 推荐在该页面中定义一些全网站共用的代码, 如: 网站统计相关脚本, 浏览器渲染方式等 meta 标签 -->
<mapping decorator="/decorators/default.jsp"/>多个装饰器
1
2
3
4
5
6<mapping>
<path>/multi.jsp</path>
<decorator>/decorators/multi_1.jsp</decorator>
<decorator>/decorators/multi_2.jsp</decorator>
<decorator>/decorators/multi_3.jsp</decorator>
</mapping>
装饰器会按照配置的先后顺序进行装饰
假如
multi.jsp 中 body 内容为 0,multi_1.jsp 中内容为 1 同时在下面输出原始页面中的 body 内容
1 | <body> |
multi_2.jsp 中内容为 2 同时在下面输出原始页面中的 body 内容
最终返回的页面内容为
2
1
0
不需要装饰
1
2
3<!-- SiteMesh3 会先判断是否不需要装饰, 然后再判断是否存在匹配的装饰器 -->
<!-- /exclude/* 会对所有以 /exclude 开头的 url 都不会进行装饰 包括 /exclude/index.jsp,/exclude/item/index.jsp -->
<mapping path="/exclude/*" exclue="true"/>MIME 类型
1
2
3
4
5
6
7<!--
默认情况下, SiteMesh3 只对响应头 Content-Type 中包含 text/html 的页面进行装配
如果会需要装配其他格式的页面, 添加多个 mime-type 标签即可
-->
<mime-type>text/html</mime-type>
<mime-type>application/vnd.wap.xhtml+xml</mime-type>
<mime-type>application/xhtml+xml</mime-type>自定义输出标签
1
2
3
4
5
6
7<!--
输出标签格式 <sitemesh:write property="body"/>
SiteMesh3 默认支持 title, head, body 三个标签, 如果需要支持其他标签, 可以通过实现 org.sitemesh.content.tagrules.TagRuleBundle 接口中的 install 方法来完成对标签的拓展
-->
<content-processor>
<tag-rule-bundle class="com.github.ghthou.learning.sitemesh3.ExpandTagRuleBundle"/>
</content-processor>
ExpandTagRuleBundle 代码如下
1 | public class ExpandTagRuleBundle implements TagRuleBundle { |
此时可以使用 <sitemesh:write property="header"/>
标签在装饰器中输出原始页面的 header 标签值
其他说明
title
,head
,body
标签的实现请参考org.sitemesh.content.tagrules.html.CoreHtmlTagRuleBundle
title
,head
,body
等自定义标签只会提取原始页面中的第一个找到的标签默认配置文件路径为
/WEB-INF/sitemesh3.xml
,如果需要自定义配置路径,请在配置filter
时配置configFile
属性,如将sitemesh3.xml
配置文件放在resources
文件夹中1
2
3
4
5
6
7
8
9<filter>
<filter-name>sitemesh</filter-name>
<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
<!--设置配置文件路径 默认为 /WEB-INF/sitemesh3.xml -->
<init-param>
<param-name>configFile</param-name>
<param-value>/WEB-INF/classes/sitemesh3.xml</param-value>
</init-param>
</filter>如果装饰器是
html
文件会存在中文乱码的问题,在 SpringMVC 中可在web.xml
文件配置如下过滤器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>在 SpringMVC 中因为 SiteMesh3 需要直接访问到装饰页面,所以需要增加如下标签
1
2
3<mvc:default-servlet-handler/>
<!-- 或者配置 url 与文件夹映射关系 -->
<mvc:resources mapping="/decorators/**" location="/decorators/"/>如果装饰器为 JSP 页面,则可以使用 EL 表达式获取原始页面中的属性
假如在 SpringMVC 中设置如下属性1
2
3
4
5"/index") (value =
public String index(Model model) {
model.addAttribute("date", new Date().toLocaleString());
return "index";
}则可以在方法返回页面
/index.jsp
和该 url 的装饰页面/decorators/default.jsp
中使用 EL 表达式获取date
属性
参考资料
SiteMesh3 官网文档
SiteMesh3 GitHub