使用 SiteMesh3 完善页面布局

在网页开发中, 大部分网页都具有相同的页头, 页尾, 菜单等模块. 一般情况下我们会将这些共用的代码单独抽取成一个页面, 然后进行包含. 虽然这样能够达到代码复用的效果, 但是如果引入的页面过多, 一来会带来修改不变的效果, 二来依然会形成多个页面使用相同的代码 (页面包含代码), 此时我们可以使用 SiteMesh3 来妥善解决这个问题

最初页面形式

使用 SiteMesh3 完善页面布局_第1张图片
最初页面形式

使用 JSP 进行页面包含

使用 SiteMesh3 完善页面布局_第2张图片
页面包含

进行页面包含后, 能达到一些共用页面的代码复用, 但是如果页面布局复杂的话, 会存在大量的页面包含代码, 依然给我们带来了不便

SiteMesh3 方式

SiteMesh3 使用演示

使用 SiteMesh3 时需要先定义一个装饰器, 在这个装饰器中我们可以定义页面的布局, 然后配置动态内容输出位置即可
示例如下




    
    
    
    <sitemesh:write property="title"/>
    
    
    
    
    
    
    


    
header
footer

假如此时存在一个这样的原始页面




    title
    


        hello,world


经过 SiteMesh3 装饰后的页面如下




    
    
    title
    
    
    
    
    
    
    



    
header
hello,world
footer

可以发现使用 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.jspdefault.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

你可能感兴趣的:(使用 SiteMesh3 完善页面布局)