• SpringBoot系列: Pebble模板引擎


    ===============================
    Java 模板引擎选择
    ===============================
    SpringBoot Starter项目向导中可选的Java模版引擎有:
    1. Thymeleaf (百里香草叶子)
    2. Freemarker
    3. Mustache
    4. Groovy Templates

    简单评价这些模版引擎吧,
    1. Thymeleaf: SpringBoot 看起来更推荐 Thymeleaf, 但我不喜欢它自作聪明的标签定义, 满眼 th 开头的黑魔法标签, 表示看不懂, 另外 Thymeleaf 也是公认性能最差的引擎, https://github.com/mbosecke/template-benchmark
    2. Freemarker: 放弃了 Thymeleaf 后, 重点考察了 Freemarker, 断断续续学了几天, 要做一个小应用时, 还是碰到不少问题, 另外布局复用这块搞的也太复杂了.
    3. Mustache: 语法比较奇怪.
    4. Groovy Templates: 完全不是 html 语法, 完全不懂它的模版语法.

    我对后端模版引擎选择标准:
    在一个普通的web项目中, 后端模块引擎技术往往是最不被看重的领域, 一般在上面投入的时间也不多, 如果一个模版引擎一两天还不能上手, 说明这个模版引擎设计的太复杂了, 或者太另类了.

    我的最终选择:
    对benchmark (https://github.com/mbosecke/template-benchmark) 上的模版引擎都做了些研究, 综合考虑了项目成熟度/学习难度/项目活跃程度/, 最终选定 Pebble templates.


    ===============================
    关于 Pebble templates
    ===============================
    语法: Pebble templates 是 Django-like 模板引擎. 类似的引擎还有: Jinja2(Python), Twig(PHP), jtwig(Java)
    学习成本: 花上一天学习就能应付日常开发, 官方文档也不长, 学习起来非常快.

    目前稳定版: 3.0.5, 而且官方提供了 SpringBoot2 Starter 包.

    主页: https://pebbletemplates.io/
    github wiki: https://github.com/PebbleTemplates/pebble/wiki
    https://github.com/PebbleTemplates/pebble/wiki/basic-usage
    https://github.com/PebbleTemplates/pebble/wiki/installation

    ===============================
    Pebble 重要的几个类
    ===============================
    1. Loader 类: PebbleEngine 将依赖 Loader 加载原始的模板, Pebble 内置 FileLoader 和 ClasspathLoader 和 StringLoader  等几个实现类, 前者负责从文件系统中加载原始模板, 后者负责直接从字符串中加载原始模板. 引入 pebble-spring-boot-2-starter 后, 会在 Spring context 注册一个名为 pebbleLoader 的 Loader.
    2. PebbleEngine 类: 引擎核心. 引入 pebble-spring-boot-2-starter 后, 会在 Spring context 注册一个名为 pebbleEngine 的引擎对象, pebbleEngine 使用 pebbleLoader 加载原始模板.
    3. PebbleTemplate 类: 负责完成模板的渲染.
    4. PebbleViewResolver 类, 以 ModelAndView 对象作为模板参数的输入, 然后使用 PebbleTemplate 对象完成渲染. 引入 pebble-spring-boot-2-starter 后, 会在 Spring context 注册一个名为 pebbleViewResolver 的ViewResolver对象.
    一个 PebbleEngine 对象依赖一个特定类型的 Loader 对象, 如果我们的应用既有字符串模板, 又有文件模板, 我们需要定义两个 Loader 和两个 PebbleEngine 对象.

    ===============================
    Pebble 和 SpringBoot 的集成
    ===============================
    <dependency>
    <groupId>io.pebbletemplates</groupId>
    <artifactId>pebble-spring-boot-2-starter</artifactId>
    <version>3.0.5</version>
    </dependency>

    pebble-spring-boot-2-starter, 会读取一些配置属性, 完整的属性清单见 https://github.com/PebbleTemplates/pebble-spring-boot-starter
    下面是一些常用的默认属性值, 我们可以在 application.properties 文件中按需设定, 比如禁用缓存或修改后缀为.html 等.
    pebble.prefix=/templates/
    pebble.suffix=.pebble
    pebble.content-type=text/html
    pebble.cache=true
    pebble.encoding=UTF-8
    pebble.defaultLocale=null
    pebble.strictVariables=false

    自定义 Pebble Configuration 类:
    引入 pebble-spring-boot-2-starter 后, Pebble 会向 Spring context 注册一个名为 pebbleLoader 的 Loader, 以及一个名为 pebbleEngine 的引擎对象, 以及一个名为 pebbleViewResolver 的 PebbleViewResolver 对象. pebbleLoader 是一个 FileLoader, pebbleEngine 使用 pebbleLoader 加载原始模板, pebbleViewResolver 负责组装参数和原始模板.
    如果我们有特别的需求, 可以自定义自己的 Pebble Configuration, 按需注入我们自己的 pebbleLoader 和 pebbleEngine 和 pebbleViewResolver. 

    //@formatter:off
    /**
     * Pebble Config 类
     * 1. 为了处理文本模板, 增加 pebbleStringLoader 和 pebbleStringEngine bean.
     * 2. 为了处理其他目录的模板文件, 增加 pebbleFileLoader 和 pebbleFileEngine bean.
     * 3. 未对 pebble-spring-boot-2-starter 注册的 pebbleLoader pebbleEngine pebbleViewResolver  bean做任何修改.
     * @author Administrator
     *
     */
    //@formatter:on
    @Configuration
    class PebbleConfig {
        @Bean("pebbleStringLoader")
        StringLoader pebbleStringLoader() {
            return new StringLoader();
        }
    
        @Autowired
        @Bean("pebbleStringEngine")
        PebbleEngine pebbleStringEngine(@Qualifier("pebbleStringLoader") StringLoader pebbleStringLoader) {
            PebbleEngine stringEngine = new PebbleEngine.Builder().loader(pebbleStringLoader)
                    .build();
            return stringEngine;
        }
    
        @Bean
        FileLoader pebbleFileLoader() {
            FileLoader loader = new FileLoader();
            loader.setPrefix("/path/to/resources");
            loader.setSuffix(".html");
            return loader;
        }
    
        @Bean
        @Autowired
        PebbleEngine pebbleFileEngine(@Qualifier("pebbleFileLoader") FileLoader pebbleFileLoader) {
            PebbleEngine fileEngine = new PebbleEngine.Builder().loader(pebbleFileLoader)
                    .build();
            return fileEngine;
        }
    }
    
    @Component
    class PebbleConverter {
        @Autowired
        @Qualifier("pebbleStringEngine")
        PebbleEngine pebbleStringEngine;
    
        public String render(String templateRawText, Map<String, Object> context) throws IOException {
            PebbleTemplate compinedTempate = pebbleStringEngine.getTemplate(templateRawText);
            StringWriter writer = new StringWriter();
            compinedTempate.evaluate(writer, context);
            return writer.toString();
        }
    }

    ===============================
    Pebble Layout 模板设计
    ===============================
    这里简单展现一下使用Pebble如何模块化各个页面, 假设有下面文件:
    home.pebble 文件: 主页模板
    base.pebble 文件: 所有页面的母版
    navbar.pebble 文件: 头部导航条
    footer.pebble 文件: 尾部条
    sidebar.pebble 文件: 左边导航条

    这几个文件的关系是:
    base.pebble 包含 navbar.pebble 和 footer.pebble 和 sidebar.pebble 文件, home.pebble 继承自 base.pebble 文件, 并 override 一些指定的元素.
    包含指令为 {% include %}, 继承指令为 {% extends %}, override 是通过复用同名的block 块实现.

    footer.pebble 文件内容: 

        <div>
        </div> <!-- end of footer -->

    navbar.pebble 文件内容: 

        <div>
        </div> <!-- end of navbar -->    

    base.pebble 文件内容:
    使用 {% include %} 指令将 footer/sidebar/navbar 几个 pebble 文件嵌入进来, 并加入了一个 content block, base.pebble 子文件可以扩展该block.

    <!DOCTYPE html>
    <html lang="en">
        <head>
                <link rel="stylesheet" href="/css/bootstrap.min.css" />
                <link rel="stylesheet" href="/css/style.css" />
                <title>Pebble Spring Example</title>
        </head>
        <body>
            <div id="wrap">
                {% include 'navbar' %}   
                
                <div class="container">
                    <div class="row">
                        <div class="col-md-3">
                            {% include 'sidebar' %}
                        </div>
                        <div class="col-md-9">
                            {% block content %}
                                {# This section is to be overriden by child templates #}
                            {% endblock content %}
                        </div>
                    </div>            
                </div><!-- end container -->
                
            </div><!-- end wrap -->
    
            {% include 'footer' %}
        </body>
    </html>

    home.pebble 文件内容:
    使用 {% extends %} 指令继承了 base.pebble 页面, 同时使用了 {% block content %} 将真实的数据嵌入到 base.pebble 文件的 content block 中.

    {% extends 'base' %}
    {% block content %} 
      Home page
    {% endblock content%}

    ===============================
    我找到几个不错的Freemark链接
    ===============================
    https://o7planning.org/en/11547/spring-boot-and-freemarker-tutorial
    https://www.hawu.me/coding/733
    http://www.tianshouzhi.com/api/tutorials/springboot/115
    https://www.cnblogs.com/ChenD/p/6908246.html

  • 相关阅读:
    项目管理沙龙第十一次聚会纪要当敏捷没有共识的时候
    项目管理沙龙第十次聚会纪要AOM项目的敏捷实践
    项目管理沙龙第五次聚会
    微信小程序引入Vant组件
    Es6 Promise 及 截图软件Snipaste.exe
    微信小程序封装Request功能,请求接口
    我画的第二个 微信小程序页面
    我画的第一个 微信小程序页面
    微信小程序Vant获取用户信息及手机号
    小程序接入Echarts组件库
  • 原文地址:https://www.cnblogs.com/harrychinese/p/SpringBoot_pebble_intro.html
Copyright © 2020-2023  润新知