1. 程式人生 > >Thymeleaf 3 遷移指南

Thymeleaf 3 遷移指南

如果你是打算從Thymeleaf2遷移到Thymeleaf3的使用者。首先,一個好訊息是你當前的Thymeleaf模板與Thymeleaf3完全相容。所以,如果要進行遷移,你只要做一些配置上的修改。

Thymeleaf 3.0 BETA版本是穩定且完全覆蓋2.1版本的特性,所以,推薦你進行升級。因為新版本的效能更好而且有許多新的特性。

唯一的問題是,不是所有的Thymeleaf方言(dialect)都遷移到了Thymeleaf 3中。因此,在遷移前要做好這方面的相容性檢查。

下面來介紹一下Thymeleaf 3中的一些變化和特性。

1. 模板變化

唯一的變化是,推薦你去掉模板中的 th:inline=“text”

屬性。因為在HTML或XML模板中,不再需要該屬性去支援文字中內聯表示式的特性。當然,只是推薦你去去掉該屬性,不去掉,你原來模板一樣可以工作。去掉的好處是會給你帶來執行效能方面的提升。

詳細資訊可參見下文的內聯機制部分。

2. 配置變化

看一個thymeleaf-spring4整合的配置檔案的例子。

首先你需要更新Maven依賴

<dependency>
  <groupId>org.thymeleaf</groupId>
  <artifactId>thymeleaf</artifactId>
  <version>
3.0.0.BETA02</version> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring4</artifactId> <version>3.0.0.BETA02</version> </dependency>

然後是spring 配置

@Configuration
@EnableWebMvc
@ComponentScan("com.thymeleafexamples"
) public class ThymeleafConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware { private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Bean public ViewResolver viewResolver() { ThymeleafViewResolver resolver = new ThymeleafViewResolver(); resolver.setTemplateEngine(templateEngine()); resolver.setCharacterEncoding("UTF-8"); return resolver; } private TemplateEngine templateEngine() { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setTemplateResolver(templateResolver()); return engine; } private ITemplateResolver templateResolver() { SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); resolver.setApplicationContext(applicationContext); resolver.setPrefix("/WEB-INF/templates/"); resolver.setTemplateMode(TemplateMode.HTML); return resolver; } }

與Thymeleaf 2相比,第一個區別是,現在推薦的模板解析類是 SpringResourceTemplateResolver。該類依賴於 Spring的ApplicationContext 上下文。因此,你的配置類需要實現 ApplicationContextAware 介面。

第二個區別是。提供了TemplateMode.HTML 列舉常量。模板型別的方法引數不再是string型別的。

如果你需要新增其他方言,可以通過engine.addDialect(…)方法,當然你需要先確認Thymeleaf 3是否支援。

你可以到官方下載一些整合配置的例子。

3. 完整的HTML5 標記支援

Thymeleaf 3.0 不再是基於XML結構的。由於引入新的解析引擎,模板的內容格式不再需要嚴格遵守XML規範。即不在要求標籤閉合,屬性加引號等等。當然,出於易讀性考慮,還是推薦你按找XML的標準去編寫模板。

下面的程式碼在Thymeleaf 3.0裡是合法的:

<div><p th:text=${mytext} ng-app>Whatever

4. 模板型別

Thymeleaf 3 移除了之前版本的模板型別,新的模板型別為:

  • HTML
  • XML
  • TEXT
  • JAVASCRIPT
  • CSS
  • RAW

2個標記型模板(HTML和XML),3個文字型模板(TEXT, JAVASCRIPT和CSS) 一個無操作(no-op)模板 (RAW)。

HTML模板支援包括HTML5,HTML4和XHTML在內的所有型別的HTML標記。且不會檢查標記是否完整閉合。此時,標記的作用範圍按可能的最大化處理。

4.1 文字型模板

文字型模板使得Thymeleaf可以支援輸出CSS、Javascript和文字檔案。在你想要在CSS或Javascript檔案中使用服務端的變數時;或者想要輸出純文字的內容時,比如,在郵件中,該特性是否有用。

在文字模式中使用Thymeleaf的特性,你需要使用一種新的語法,例如:

[# th:each="item : ${items}"]
  - [# th:utext="${item}" /]
[/]

4.2 增強的內聯機制

現在可無需額外的標籤,直接在文字中輸出資料:

This product is called [[${product.name}]] and it's great!

詳見:Inlined output expressions 關於內聯機制的討論: Refactoring of the inlining mechanism

5. 片段(Fragment)表示式

Thymeleaf 3.0 引入了一個新的片段表示式。形如:~{commons::footer}。

該特性十分有用(真的是是否有用,直接解決了一直困擾我的定義通用的header和footer的問題)。直接看例子來理解一下該語法吧:

<head th:replace="base :: common_header(~{::title},~{::link})">
  <title>Awesome - Main</title>
  <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
  <link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">
</head>

這裡,將兩外另個包含<title>和<link>標籤的片段作為引數傳遞給了common_header片段,在common_header中使用如下:

<head th:fragment="common_header(title,links)">
  <title th:replace="${title}">The awesome application</title>

  <!-- Common styles and scripts -->
  <link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}">
  <link rel="shortcut icon" th:href="@{/images/favicon.ico}">
  <script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"></script>

  <!--/* Per-page placeholder for additional links */-->
  <th:block th:replace="${links}" />

</head>

渲染出結果如下:

<head>

  <title>Awesome - Main</title>

  <!-- Common styles and scripts -->
  <link rel="stylesheet" type="text/css" media="all" href="/awe/css/awesomeapp.css">
  <link rel="shortcut icon" href="/awe/images/favicon.ico">
  <script type="text/javascript" src="/awe/sh/scripts/codebase.js"></script>

  <link rel="stylesheet" href="/awe/css/bootstrap.min.css">
  <link rel="stylesheet" href="/awe/themes/smoothness/jquery-ui.css">

</head>

6. 無操作標記(token)

Thymeleaf 3.0 另一個新的特性就是無操作(NO-OP no-operation)標記,下劃線"_",代表什麼也不做。

例如:

<span th:text="${user.name} ?: _">no user authenticated</span>

當user.name 為空的時候,直接輸出標籤體中的內容:no user authenticated。該特性讓我們可以直接使用原型模板中的值作為預設值。

7 模板邏輯解耦

Thymeleaf 3.0 允許 HTML和XML模式下的模板內容和控制邏輯完全解耦。

例如,在3.0版本里,一個“乾淨”的home.html模板內容如下:

<!DOCTYPE html>
<html>
  <body>
    <table id="usersTable">
      <tr>
        <td class="username">Jeremy Grapefruit</td>
        <td class="usertype">Normal User</td>
      </tr>
      <tr>
        <td class="username">Alice Watermelon</td>
        <td class="usertype">Administrator</td>
      </tr>
    </table>
  </body>
</html>

我們只需額外定義一個home.th.xml檔案,就可以把之前的home.html檔案當作Thymeleaf模板來使用,內容如下:

<?xml version="1.0"?>
<thlogic>
  <attr sel="#usersTable" th:remove="all-but-first">
    <attr sel="/tr[0]" th:each="user : ${users}">
      <attr sel="td.username" th:text="${user.name}" />
      <attr sel="td.usertype" th:text="#{|user.type.${user.type}|}" />
    </attr>
  </attr>
</thlogic>

邏輯解耦時,指定的屬性會在模本解析的過程中插入指定的位置。通過sel屬性指定選擇器。

邏輯解耦,意味著可以使用純HTML檔案作為設計模板,允許設計人員不再需要具備Thymeleaf的相關知識。 詳細介紹:Decoupled Template Logic

8. 效能提升

除了之前提到的特性之外,Thymeleaf 3.0 的另外一個重要突破就是有明顯的效能提升。

2.1版本之前採用的基於XML的模板引擎,雖然有助於實現很多的特性,但是在有些情況下也造成了效能的損失。在絕大多數的專案裡Thymeleaf的渲染時間是幾乎可以忽略不計的,這也就凸顯出來了Thymeleaf在某些特定情景下的效能問題。(例如:在高負載的網站中處理成千上萬行的表格)。

Thymeleaf 3 重點關注效能問題並完全重寫了引擎。因此與之前版本相比效能有很大的提升。而且,這種提升不僅僅侷限於渲染時間,也包括更低的記憶體佔用以及在高併發場景下的低延遲。

值得一提的是,效能提升不僅是架構層面的事,也包括3.0 版本里的一些有助於效能提升的新特性。例如,在3.0版本里使用SpringEL表示式的編譯器(從Spring Framework4.2.4版本開始),在使用Spring的場景下,可進一步的提升效能。具體參見:Configuring the SpringEL compiler

即使沒有使用Spring而是使用OGNL表示式,在3.0版本里也有效能優化。Thymeleaf甚至給OGNL程式碼庫貢獻了很多原始碼,這些程式碼有助於提升Thymeleaf在新的MVC1.0(JSR371)標準環境下的效能。

9. 不依賴於Servlet API

其實Thymeleaf3.0 之前版本在離線執行的情況下已經做到了不依賴於Java Servlet API,就是說在執行模板的過程中不依賴於Web容器。一個實用的場景就是用作郵件模板。

然而,在Thymeleaf3.0裡做到了在Web環境下也完全不依賴Servlet API。這樣就使得與那些不依賴Java Servlet框架(如 vert.x, RatPack, Play Framework)的整合更加簡單方便。

10. 新的方言系統

Thymeleaf 3 提供了新的方言系統。如果你在早期版本上開發了Thymeleaf的方言,你需要使其與Thymeleaf 3 相容。

新的方言介面十分簡單

public interface IDialect {

  public String getName();

}

可以通過實現IDialect的子類介面,實現更多不同的特性。

列舉一下新方言系統增強的點:

  • 除了processors之外,還提供了pre-processors 和 post-processors,模板的內容可以在處理之前和之後被修改。例如,我們可以使用pre-processors來快取內容或者用post-processors來壓縮輸出結果。
  • 提出了方言優先順序的概念,可以對方言的處理器(processor)進行排序。處理器優先順序的排序是跨方言的。
  • 物件表示式方言提供可以模本內任意地方使用的新的表示式物件和工具物件。如:#strings, #numbers, #dates 等。

更多特性,可參見:

11 重構了核心API

核心介面進行了深度重構,詳見:

12 總結

Thymeleaf 3 是Thymeleaf 模板引擎經過4年多不懈的努力和工作後的一個重要的里程碑式的成果。提供了許多令人興奮的新特性以及許多隱藏的改進。 所以,別再猶豫,趕緊來試試吧。

參考: