1. 程式人生 > 實用技巧 >SpringBoot整合FreeMarker模板引擎

SpringBoot整合FreeMarker模板引擎

目錄

本文樣例已上傳至碼雲:https://gitee.com/tqbx/springboot-samples-learn/tree/master/spring-boot-freemarker

詳細文件地址:http://freemarker.foofun.cn/index.html

FreeMarker是什麼?

  • 一款模板引擎。即一種基於模板和要改變的資料, 並用來生成輸出文字(HTML網頁,電子郵件,配置檔案,原始碼等)的通用工具。

  • 在模板中,你可以專注於如何展現資料, 而在模板之外可以專注於要展示什麼資料,體現就是:模板+ 資料模型 = 輸出。

快速開始

  1. pom.xml確定匯入FreeMarker依賴包
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>
  1. 配置application.yml相關配置
spring:
  freemarker:
    settings:
      classic_compatible: true #處理空值
      datetime_format: yyy-MM-dd HH:mm
      number_format: 0.##
    suffix: .ftl
    template-loader-path:
      - classpath:/templates
  1. 在templates目錄下放置.ftl檔案,意為freemarker templates layer
  2. 編寫Controller,將模型存入request中:
@Controller
public class TestController{

    @GetMapping("test")
    public String test(HttpServletRequest request){
        List<User> users = new LinkedList<>();
        for(int i = 0; i < 10; i ++){
            User user = new User();
            user.setId((long)i);
            user.setUsername("name = " + i);
            users.add(user);
        }
        request.setAttribute("users",users);

        return "test";
    }
}
  1. 簡單使用FreeMarker的標籤指令:
<#list users>
    <p>Users:
    <ul>
        <#items as user>
            <li>${user.id}--${user.username}<br>
            </#items>
    </ul>
<#else>
    <p>no users!
</#list>

模板一覽

${...}: FreeMarker將會輸出真實的值來替換大括號內的表示式,被稱為插值表示式。

<#../>:FTL標籤,以#開頭,自定義標籤則以@開頭。

常用指令

條件指令:if、elseif、else

<#if animals.python.price < animals.elephant.price>
  Pythons are cheaper than elephants today.
<#elseif animals.elephant.price < animals.python.price>
  Elephants are cheaper than pythons today.
<#else>
  Elephants and pythons cost the same today.
</#if>

list指令

list 指令的一般格式為: <#list sequence as loopVariable> repeatThisrepeatThis 部分將會在給定的 sequence 遍歷時在每一項中重複, 從第一項開始,一個接著一個。在所有的重複中, loopVariable 將持有當前遍歷項的值。 這個變數僅存在於 <#list ...><#list> 標籤內。

<p>We have these animals:
<table border=1>
  <#list animals as animal>
    <tr><td>${animal.name}<td>${animal.price} Euros
  </#list>
</table>

sequence 可以是任意表達式, 比如我們可以列表顯示示例資料模型中的水果,就像這樣:

<ul>
<#list misc.fruits as fruit>
  <li>${fruit}
</#list>
</ul>

上面示例中的一個問題是如果我們有0個水果,它仍然會輸出一個空的 <ul></ul>,而不是什麼都沒有。 要避免這樣的情況,可以這麼來使用 list

<#list misc.fruits>
  <p>Fruits:
  <ul>
    <#items as fruit>
      <li>${fruit}<#sep> and</#sep>
    </#items>
  </ul>
<#else>
  <p>We have no fruits.
</#list>

include指令

使用 include 指令, 我們可以在模板中插入其他檔案的內容。

如果需要在每個頁面的下方都顯示版權資訊,可以將版權資訊單獨放在頁面檔案 copyright_footer.html 中:

<hr>
<i>
Copyright (c) 2000 <a href="http://www.acmee.com">Acmee Inc</a>,
<br>
All Rights Reserved.
</i>

使用時,用include引入該檔案即可:

<html>
<head>
  <title>Test page</title>
</head>
<body>
  <h1>Test page</h1>
  <p>Blah blah...
  <#include "/copyright_footer.html">
</body>
</html>

內建函式

內建函式很像子變數(如果瞭解Java術語的話,也可以說像方法), 它們並不是資料模型中的東西,是 FreeMarker 在數值上新增的。 為了清晰子變數是哪部分,使用 ?(問號)代替 .(點)來訪問它們。

所有內建函式參考:http://freemarker.foofun.cn/ref_builtins.html

處理不存在的變數

一個不存在的變數和一個是null值的變數, 對於FreeMarker來說是一樣的。

不論在哪裡引用變數,都可以指定一個預設值來避免變數丟失這種情況, 通過在變數名後面跟著一個 !(歎號,譯者注)和預設值。 就像下面的這個例子,當 user 不存在於資料模型時, 模板將會將 user 的值表示為字串 "visitor"。(當 user 存在時, 模板就會表現出 ${user} 的值):

<h1>Welcome ${user!"visitor"}!</h1>

也可以在變數名後面通過放置 ?? 來詢問一個變數是否存在。將它和 if 指令合併, 那麼如果 user 變數不存在的話將會忽略整個問候的程式碼段:

<#if user??><h1>Welcome ${user}!</h1></#if>

自定義指令

使用macro定義巨集

  • 未帶引數巨集呼叫
<#macro greet>
  <font size="+2">Hello Joe!</font>
</#macro>

<#--未帶引數巨集呼叫-->
    <@greet></@greet>

  • 帶引數巨集呼叫
<#macro greet_2 person>
    <font size="+2">Hello ${person}!</font>
</#macro>
<#--帶引數巨集呼叫-->
    <@greet_2 person="天喬巴夏"/>

  • 巢狀呼叫
<#macro nest_test>
    <#nested >
</#macro>
<#--巢狀呼叫-->    
    <@nest_test>
        hyh
        </@nest_test>

使用TemplateDirectiveModel擴充套件。

這部分可以參考我發在碼雲上的程式碼:https://gitee.com/tqbx/springboot-samples-learn/tree/master/spring-boot-freemarker。

    @Override
    public void execute(DirectiveHandler handler) throws Exception {
        // 獲取引數
        String username = handler.getString("username");
        String city = handler.getString("city");
        // 處理引數
        String template = "{}來自{}.";
        String format = StrUtil.format(template, username, city);
        // 傳回去
        handler.put("result",format).render();
    }


@Configuration
public class FreeMarkerConfig {

    @Autowired
    StringTemplate stringTemplate;
    @Autowired
    private freemarker.template.Configuration configuration;


    @PostConstruct
    public void setUp() {
        configuration.setSharedVariable("timeAgo", new TimeAgoMethod());
        configuration.setSharedVariable("strstr", stringTemplate);
    }
}

<@strstr username="hyh" city="杭州">
    ${result}
    </@strstr>