美文网首页
SpringBoot+FreeMarker+SiteMesh环境

SpringBoot+FreeMarker+SiteMesh环境

作者: linfengfxl | 来源:发表于2019-04-11 16:41 被阅读0次

    准备搭建SpringBoot+FreeMarker+SiteMesh的框架,选用了springBoot2.1版本,安装一些教程无脑复制粘贴,把maven依赖和freemarker配置凑齐

    pom依赖

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.sitemesh/sitemesh -->
            <dependency>
                <groupId>org.sitemesh</groupId>
                <artifactId>sitemesh</artifactId>
                <version>3.0.1</version>
    </dependency>
    

    application

    #server
    server:
       servlet:
          context-path: /basis
    
    #DB
    #sqlserver
    spring:
       datasource: ######
          driverClassName: #####
          url: ####
          username: ####
          password: ####
       mvc:
          view:
             prefix: classpath:/templates
             suffix: ftl
       freemarker:
          cache: false
          charset: UTF-8
          content-type: text/html
          suffix: .ftl
          check-template-location: true
          template-loader-path: classpath:/templates
          #expose-request-attributes: true
          #expose-session-attributes: true
          #expose-spring-macro-helpers: true
          #allow-request-override: true
          request-context-attribute: request
          settings:
             default_encoding: UTF-8
             output_encoding: UTF-8
             url_escaping_charset: UTF-8
             tag_syntax: auto_detect
             locale: zh_CN
             datetime_format: yyyy-MM-dd HH:mm:ss
             date_format: yyyy-MM-dd
             time_format: HH:mm:ss
    

    freemarker注释掉的4行造成了给解决问题造成了很大的干扰
    SiteMeshFilter

    @WebFilter("/*")
    public class SitemeshFilter extends ConfigurableSiteMeshFilter {
        Logger logger = LoggerFactory.getLogger(SitemeshFilter.class);
        @Override
        protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
            //设置模板装饰的请求,参数(拦截的请求(可以采用通配符方式),装饰该请求的装饰模板)
            //index是一个页面模板放在src/main/resource/templates/decorators目录下
            builder
            .addDecoratorPath("/*", "/layouts/default")
            //可设置不同请求用不同模板装饰
            .addExcludedPath("/static/*") //白名单,不进行过滤的请求
            .addExcludedPath("/api/*")
            .addExcludedPath("/Images/*")
            .addExcludedPath("/Scripts/*")
            .addExcludedPath("/Styles/*")
            .addExcludedPath("/AjaxHandler/*")
            .addExcludedPath("/waiterChat/*")
            .addExcludedPath("/statistic")
            //.builder.addTagRuleBundles(new DivExtractingTagRuleBundle())  //用于添加自定义标签
            ;
            logger.info("------------ sitemeshFilter config-----------");
        }
    }
    

    粗暴的复制粘贴给后面带来了一系列的问题:

    1. sitemesh 模板文件 default.ftl 放在 templates/layouts 目录下找不到,报404错误
    2. 将 default.ftl 文件移到static 目录下则被识别为资源文件,浏览器访问变成下载保存

    看源码sitemesh拦截到请求后,会在请求返回前通过forward方法请求模板文件
    org.sitemesh.webapp.WebAppContext

    /**
         * Dispatch to the actual path. This method can be overriden to provide different ways of dispatching
         * (such as cross web-app).
         */
        protected void dispatch(HttpServletRequest request, HttpServletResponse response, String path)
                throws ServletException, IOException {
            RequestDispatcher dispatcher = servletContext.getRequestDispatcher(path);
            if (dispatcher == null) {
                throw new ServletException("Not found: " + path);
            }
            dispatcher.forward(request, response);
        }
    

    由于模板文件 default.ftl 在template 目录下,受资源访问的保护,必须提供一个访问入口

    /**
         * 
         * siteMesh decorator 访问
         *
         * @param decorator 模板文件名
         * @return
         * 
         * @author ###
         * @date 2019年4月11日 下午4:06:15
         */
        @RequestMapping(value = "/layouts/{decorator}", method = RequestMethod.GET)
        public String decorator(@PathVariable String decorator) {
            return "/layouts/"+decorator;
        }
    

    访问请求报错

    javax.servlet.ServletException: Cannot expose request attribute 'request' because of an existing model object of the same name
    

    将相关设置注释掉,使用默认设置,问题解决.

    1. 碰到新问题,使用post提交数据时,服务器端 sitemesh 进行 forward请求后报错
    Request method 'POST' not supported
    

    重新修改sitemesh模板访问入口,支持对post请求的页面进行包装

        /**
         * 
         * siteMesh decorator 访问
         *
         * @param decorator 模板文件名
         * @return
         * 
         * @author ###
         * @date 2019年4月11日 下午4:06:15
         */
    @RequestMapping(value = "/layouts/{decorator}",method = {RequestMethod.GET,RequestMethod.POST})
        public String decorator(@PathVariable String decorator) {
            return "/layouts/"+decorator;
        }
    
    1. sitemesh3 中模板也无法加载目标body元素中的样式属性
    <!-- sitemesh2中可用,但在sitemesh3无效 -->
    <body <sitemesh:getProperty property="body.class" writeEntireProperty="1"/> >
        <sitemesh:body/>
    </body>
    
    <!-- sitemesh3中作者推荐的处理方法--> 
    <body>
    <input id="meta.body.id" type="hidden" value="<sitemesh:write property="body.id" />"/>
    <input id="meta.body.class" type="hidden" value="<sitemesh:write property="body.class" />"/>
    <script type="text/javascript">
        var bodyClass = document.getElementById('meta.body.class').value;
        var bodyId = document.getElementById('meta.body.id').value;
        if (bodyId) {
            document.body.id = bodyid;
        }
        if (bodyClass) {
            document.body.className = bodyClass;
        }
    </script>
        <sitemesh:write property='body' />
    </body>
    

    sitemesh3已经在2015.5.29以后停止维护了,不知道有没有同样好用的易于后端开发人员上手的前端装饰组件 (´༎ຶД༎ຶ`)

    相关文章

      网友评论

          本文标题:SpringBoot+FreeMarker+SiteMesh环境

          本文链接:https://www.haomeiwen.com/subject/ubbtwqtx.html