SiteMesh3文档 http://wiki.sitemesh.org/wiki/pages/viewpage.action?pageId=1081348

重新搭建项目偶然发现SiteMesh有了新版本SiteMesh3,本着用新不用旧原则果断升级,多少遇了点坑,顺便记录下

SiteMesh3配置

  1. 添加maven依赖

    1. <dependency>
    2. <groupId>org.sitemesh</groupId>
    3. <artifactId>sitemesh</artifactId>
    4. <version>3.0.1</version>
    5. </dependency>
  2. 添加filter

    在web.xml中添加filter

    1. <filter>
    2. <filter-name>sitemesh</filter-name>
    3. <filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
    4. </filter>
    5. <filter-mapping>
    6. <filter-name>sitemesh</filter-name>
    7. <url-pattern>/*</url-pattern>
    8. </filter-mapping>
  3. 配置servlet

    1. <servlet-mapping>
    2. <servlet-name>default</servlet-name>
    3. <url-pattern>*.ftl</url-pattern>
    4. </servlet-mapping>
  4. 添加sitemesh配置文件

    1. 添加配置文件 sitemesh3.xml
      默认配置文件路径为:/WEB-INF/sitemesh3.xml

      sitemesh3.xml
      1. <sitemesh>
      2. <!--
      3. By default, SiteMesh will only intercept responses that set the Content-Type HTTP header to text/html
      4. This can be altered to allow SiteMesh to intercept responses for other types.
      5. 默认 SiteMesh 只对HTTP响应头中Content-Type为 text/html 的类型进行拦截和装饰,若需要处理其它mime类型需要自行添加配置
      6. -->
      7. <mime-type>text/html</mime-type>
      8. <!--
      9. Map default decorator. This shall be applied to all paths if no other paths match.
      10. 配置装饰器,仅设置decorator参数时表示为默认的装饰器,当没有任何路径被匹配时会使用默认装饰器装配
      11. -->
      12. <mapping decorator="/WEB-INF/decorators/decorator.ftl"/>
      13. <!--对不同的路径指定特定的装饰器-->
      14. <!--<mapping path="/admin/*" decorator="/WEB-INF/decorators/admin-decorator.ftl"/>-->
      15. <!--
      16. Alternative convention. This is more verbose but allows multiple decorators to be applied to a single path.
      17. 对同一路径可以同时使用多个装饰器
      18. -->
      19. <mapping>
      20. <path>/category/*</path>
      21. <decorator>/WEB-INF/decorators/common-decorator.ftl</decorator>
      22. <decorator>/WEB-INF/decorators/menu-decorator.ftl</decorator>
      23. <decorator>/WEB-INF/decorators/category-decorator.ftl</decorator>
      24. </mapping>
      25. <!--
      26. Exclude path from decoration.
      27. 排除路径,只需将exclue设置为true即可
      28. -->
      29. <mapping path="/static/*" exclue="true"/>
      30. <!--
      31. An advanced feature of SiteMesh is the ability to define custom rules that manipulate tags on a page.
      32. These are classes that implement org.sitemesh.content.tagrules.TagRuleBundle.
      33. 默认SiteMesh仅支持title、head、meta、body等tag,可以自定义tag,实现TagRuleBundle接口即可
      34. -->
      35. <content-processor>
      36. <tag-rule-bundle class="com.sankuai.shangchao.util.HtmlTagRuleBundle"/>
      37. </content-processor>
      38. </sitemesh>
    2. 修改配置文件路径
      默认配置文件路径为:/WEB-INF/sitemesh3.xml 若需要修改配置文件路径需要在filter里配置configFile参数

      1. <filter>
      2. <filter-name>sitemesh</filter-name>
      3. <filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
      4. <init-param>
      5. <param-name>configFile</param-name>
      6. <param-value>/WEB-INF/sitemesh3.xml</param-value>
      7. </init-param>
      8. </filter>
    3. 自定义tag

      HtmlTagRuleBundle.java
      1. import org.sitemesh.SiteMeshContext;
      2. import org.sitemesh.content.ContentProperty;
      3. import org.sitemesh.content.tagrules.TagRuleBundle;
      4. import org.sitemesh.content.tagrules.html.ExportTagToContentRule;
      5. import org.sitemesh.tagprocessor.State;
      6.  
      7. /**
      8. * Description: FootTagRuleBundle
      9. * Author: liuzhao
      10. * Create: 2015-08-22 09:21
      11. */
      12. public class HtmlTagRuleBundle implements TagRuleBundle {
      13. @Override
      14. public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {
      15. defaultState.addRule("foot", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("foot"), false));
      16. }
      17.  
      18. @Override
      19. public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) {
      20.  
      21. }
      22. }
  5. decorator示例

    decorator配置页面布局layout,对应的tag会被进行装饰替换

    decorator.ftl
    <!DOCTYPE html>
    <html>
    <head>
        <title>
            <sitemesh:write property="title"/>
        </title>
        <sitemesh:write property='head'/>
    </head>
    <body>
    <h1>啦拉拉,我是卖报的小行家</h1>
    <sitemesh:write property='body'/>
    <sitemesh:write property="foot"/>
    </body>
    </html>
  6. SpringMVC、FreeMarker配置(404问题处理)

    sitemesh3是完全独立的,不和任何框架进行偶合,因此SpringMVC、FreeMarker配置完全不需要考虑sitemesh3的兼容问题
    在加载装饰器的时候,会出现404问题,可能的原因是找不到ftl文件的解析器,所以需要配置下ftl使用默认的Servlet解析,在web.xml中添加如下配置

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.ftl</url-pattern>
    </servlet-mapping>

  1. decorate源码

    @Override
    protected boolean postProcess(String contentType, CharBuffer buffer,
                                  HttpServletRequest request, HttpServletResponse response,
                                  ResponseMetaData metaData)
            throws IOException, ServletException {
        WebAppContext context = createContext(contentType, request, response, metaData);
        Content content = contentProcessor.build(buffer, context);
        if (content == null) {
            return false;
        }
     
        String[] decoratorPaths = decoratorSelector.selectDecoratorPaths(content, context);
        //遍历装饰器进行装饰
        for (String decoratorPath : decoratorPaths) {
            content = context.decorate(decoratorPath, content);
        }
     
        if (content == null) {
            return false;
        }
        try {
            content.getData().writeValueTo(response.getWriter());
        catch (IllegalStateException ise) {  // If getOutputStream() has already been called
            content.getData().writeValueTo(new PrintStream(response.getOutputStream()));
        }
        return true;
    }
     
    public Content decorate(String decoratorName, Content content) throws IOException {
        if (decoratorName == null) {
            return null;
        }
     
        class CharBufferWriter extends CharArrayWriter {
            public CharBuffer toCharBuffer() {
                return CharBuffer.wrap(this.buf, 0this.count);
            }
        }
        CharBufferWriter out = new CharBufferWriter();
        decorate(decoratorName, content, out);
     
        CharBuffer decorated = out.toCharBuffer();
     
        Content lastContent = currentContent;
        currentContent = content;
        try {
            return contentProcessor.build(decorated, this);
        finally {
            currentContent = lastContent;
        }
    }
     
    @Override
    protected void decorate(String decoratorPath, Content content, Writer out) throws IOException {
        HttpServletRequest filterableRequest = new HttpServletRequestFilterable(request);
        // Wrap response so output gets buffered.
        HttpServletResponseBuffer responseBuffer = new HttpServletResponseBuffer(response, metaData, new BasicSelector(new PathMapper<Boolean>(), includeErrorPages) {
            @Override
            public boolean shouldBufferForContentType(String contentType, String mimeType, String encoding) {
                return true// We know we should buffer.
            }
        });
        responseBuffer.setContentType(response.getContentType()); // Trigger buffering.
     
        // It's possible that this is reentrant, so we need to take a copy
        // of additional request attributes so we can restore them afterwards.
        Object oldContent = request.getAttribute(CONTENT_KEY);
        Object oldContext = request.getAttribute(CONTEXT_KEY);
     
        request.setAttribute(CONTENT_KEY, content);
        request.setAttribute(CONTEXT_KEY, this);
     
        try {
            // Main dispatch.
            dispatch(filterableRequest, responseBuffer, decoratorPath);
     
            // Write out the buffered output.
            CharBuffer buffer = responseBuffer.getBuffer();
            out.append(buffer);
        catch (ServletException e) {
            //noinspection ThrowableInstanceNeverThrown
            throw (IOException) new IOException("Could not dispatch to decorator").initCause(e);
        finally {
            // Restore previous state.
            request.setAttribute(CONTENT_KEY, oldContent);
            request.setAttribute(CONTEXT_KEY, oldContext);
        }
    }
     
    protected void dispatch(HttpServletRequest request, HttpServletResponse response, String path)
            throws ServletException, IOException {
        //这里调用加载文件会出现404错误 /WEB-INF/decorators/decorator.ftl
        RequestDispatcher dispatcher = servletContext.getRequestDispatcher(path);
        if (dispatcher == null) {
            throw new ServletException("Not found: " + path);
        }
        dispatcher.forward(request, response);
    }

SiteMesh3整合SpringMVC+FreeMarker的更多相关文章

  1. sonne_game网站开发03 spring-mvc+freemarker整合

    今天的任务就是在spring+mybatis+springmvc的基础上,将freemarker整合进来. freemarker是什么? freemarker是一种模板引擎.它的目的是基于模板和数据, ...

  2. spring-mvc+freemarker整合(sonne_game网站开发03)

    今天的任务就是在spring+mybatis+springmvc的基础上,将freemarker整合进来. freemarker是什么? freemarker是一种模板引擎.它的目的是基于模板和数据, ...

  3. SpringBoot整合系列-整合SpringMVC

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9984607.html SpringBoot整合Spring MVC 步骤 第一步:添加必 ...

  4. freemarker学习 (servlet + freemarker -> Struts2+freemarker -> springMVC+freemarker)

    什么是freemarker? freemarker类似于jsp,但不是jsp!怎么说呢?freemarker文件后缀是.ftl,它不像jsp本质是servlet,它将构建模板.解析模板.使用模板分离开 ...

  5. CXF WebService整合SpringMVC的maven项目

    首先推荐博客:http://www.cnblogs.com/xdp-gacl/p/4259481.html   http://blog.csdn.net/hu_shengyang/article/de ...

  6. SpringMVC+Freemarker+JSTL支持

    前提: 网页编程中,我的思路是,通用的模块不仅仅只有后台代码,前端页面也可以独立为模块. 这个和asp.net中的UserController很像 比如有个人员基本信息的展示界面,需要在多个界面中嵌入 ...

  7. springMVC+freemarker中Could not resolve view with name... 问题解决

    用到springMVC+freemarker,自己在做demo过程中报: 严重: Servlet.service() for servlet springmvc threw exception jav ...

  8. spring整合springmvc和hibernate

    上篇文章使用maven搭建了web环境,这篇来记录下如何使用spring整合springmvc和hibernate,亦即spring+springmvc+hibernate框架整合. 第一步:首先配置 ...

  9. springmvc 项目完整示例07 设置配置整合springmvc springmvc所需jar包springmvc web.xml文件配置

    前面主要是后台代码,spring以及mybatis的整合 下面主要是springmvc用来处理请求转发,展现层的处理 之前所有做到的,完成了后台,业务层和持久层的开发完成了 接下来就是展现层了 有很多 ...

随机推荐

  1. 华硕U303L通过U盘装系统

    开机,按esc,进入bios,选择security,将secure boot control设置为disable.   在boot下,将launch csm 改为enable,按F10保存退出,重启. ...

  2. Python赋值语句与深拷贝、浅拷贝的区别

    参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...

  3. js二维数组与字符串

    1. 二维数组:数组中的元素,又引用了另一个数组对象 何时使用:只要保存横行竖列的数据, 具有上下级包含关系的数据, 创建二维数组: 1. var arr=[]; col arr[0]=[" ...

  4. SparkContext的初始化(季篇)——测量系统、ContextCleaner及环境更新

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

  5. fcc

    function spinalCase(str) { if(str.split(/\W|_/).length==1){ for(var i=0;i<str.length;i++){ if(/[A ...

  6. 手机移动端confirm替换方案

    //弹框 ;(function () { var ConfirmBox = function (options){ this.defaults = { title:"", topT ...

  7. 黑马程序员——File笔记读,写,复制

    #region ReadAllBytes byte[] buffer = File.ReadAllBytes(@"C:\Users\dell\Desktop\新建文件夹.txt") ...

  8. JDBC数据类型

    JDBC数据类型 JDBC驱动程序Java数据类型转换到适当的JDBC类型然后再将它发送到数据库.它使用默认的大多数数据类型映射.例如,一个Java int转换成一个SQL INTEGER.创建默认映 ...

  9. apache httpclient cache 实现可缓存的http客户端

    这里的cache storage 采用ehcache,而不是默认的内存式的cache storage.采用ehcache可以将内容缓存到磁盘上. maven <dependency> &l ...

  10. python post

    使用python 提交表单包括图片以及参数信息,详见代码 # -*- coding: utf-8 -*- import MultipartPostHandler, urllib2, cookielib ...