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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM