Thymeleaf模板引擎——JSP替代方案
介绍Thymeleaf模板引擎
翻译自 阿尔诺COGOLUÈGNES 的文章
有一堆Java模板引擎,但其中一个现在已经获得了一些动力:Thymeleaf。良好而强大的语法,灵活性,充满活力的社区以及与流行Web技术的良好集成,这些都是发现JSP替代方案的充分理由。本文列出了Thymeleaf的核心功能,并展示了如何编写和处理HTML模板。
Thymeleaf简而言之
Thymeleaf是一个Java模板引擎。它是一个开源项目,并根据Apache License 2.0获得许可。以下是Thymeleaf的核心功能:
- 简单而自然的模板
- 针对Web环境进行了优化,但可以独立运行
- 高级评估语言(OGNL或Spring Expression Language)
- 支持模板逻辑(条件,迭代)
- 全力支持国际化
- Spring MVC和Spring Web Flow集成
- 支持复合视图模式(带有片段的本机,Tiles集成,可与Sitemesh一起使用)
- 先进的模板缓存支持
- 适用于蒲公英数据表
是的,这是很多功能!继续阅读以了解如何使用数据编写和提供Thymeleaf模板...
Maven 最新模板依赖
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.10.RELEASE</version>
</dependency>
设置模板引擎
Thymeleaf基础设施非常简单:a TemplateResolver
加载模板和a TemplateEngine
进行实际处理(使用给定的上下文合并模板)。以下是独立设置的代码:
1 2 3 4 5 |
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); resolver.setTemplateMode("XHTML"); resolver.setSuffix(".html"); TemplateEngine engine = new TemplateEngine(); engine.setTemplateResolver(resolver); |
我们将从类路径的根目录加载模板。当我们要求Thymeleaf呈现一个名为的模板时home
,解析器将添加html
扩展名,因为我们设置了该suffix
属性。然后,我们将能够根据逻辑名称进行思考,并且不会担心文件的物理名称。
模板
我们的模板是home.html
位于类路径根目录的文件(例如,src/main/resources
如果我们遵循Maven约定,则在项目目录中)。模板的第一个版本仅包含HTML页面的骨架:
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-3.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>My first template with Thymeleaf</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> </body> </html> |
请注意使用特定于Thymeleaf的doctype。
处理模板
我们的模板中没有任何动态,但我们可以通过在引擎配置后添加以下代码来测试我们的设置:
1 2 3 |
StringWriter writer = new StringWriter(); Context context = new Context(); engine.process("home", context, writer); |
然后,writer
变量应包含已处理模板的输出,该输出基本上是文件的静态内容。重要的事情:
处理需要上下文。该对象通常包含我们想要在视图中显示的变量。
要调用要渲染的模板home
。解析器将负责将此逻辑名称映射到文件的物理位置。请记住,我们使用的是基于类路径的解析器,它为模板名称添加了HTML扩展。
好的,一切似乎都有效!了解Thymeleaf是如何轻量级的。模板引擎大部分时间都在Web环境中使用,但我们也可以在独立环境中轻松使用它,比如JUnit测试。
标签和国际化(i18n)
Thymeleaf的默认国际化支持非常简单:删除模板旁边的属性文件,您就完成了。让我们home.properties
在与模板相同的目录中创建一个:
1 |
hello.world=Hello World! |
还有一个home_fr.properties
法文版的文件:
1 |
hello.world=Bonjour le monde ! |
我们修改模板以引用此标签:
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-3.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>My first template with Thymeleaf</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <p th:text="#{hello.world}">Hello</p> </body> </html> |
就是这样,我们公开了如何在Thymeleaf的模板中插入动态内容:在HTML元素中添加额外的属性:
1 |
<p th:text="#{hello.world}">Hello</p> |
嵌套Hello
只是为了预览,Thymeleaf将在处理过程中用动态值替换它。请注意使用Thymeleaf的特定th:text
属性以及使用#{key}
语法来引用属性文件的条目。
如果我们执行渲染程序,我们最终得到以下输出(如果你的语言环境不是法语!):
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>My first template with Thymeleaf</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <p>Hello World!</p> </body> </html> |
法语版怎么样?我们可以在上下文中指定语言环境:
1 2 3 |
StringWriter writer = new StringWriter(); Context context = new Context(Locale.FRANCE); engine.process("home", context, writer); |
Thymeleaf使用适当的属性文件:
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>My first template with Thymeleaf</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <p>Bonjour le monde !</p> </body> </html> |
到目前为止,非常好,让我们继续讨论核心主题:在上下文中推送对象以在视图中呈现它们。
变量替换
我们假设我们想在视图中显示当前日期。我们可以使用已经格式化的字符串提供上下文:
1 2 |
String now = new SimpleDateFormat("yyyy-MM-dd").format(Calendar.getInstance().getTime()); context.setVariable("date", now); |
然后在模板中引用此变量,如下所示:
1 |
<p th:text="${date}">The date</p> |
注意这次使用${variable}
语法(我们用于#{...}
i18n)。我们再次依靠该th:text
属性来注入动态内容。如果我们再次处理模板,则输出包含预期的内容:
1 |
<p>2013-01-18</p> |
让我们看看如何显示典型的域对象。
使用Java bean进行变量替换
显示域对象是Web应用程序的常见用例。我们可以添加一个Contact
对象来显示Thymeleaf上下文:
1 |
context.setVariable("contact",new Contact("John","Doe")); |
我们对域对象状态进行了硬编码,但它也可以从数据库中加载。以下是如何显示firstname
和lastname
域对象的属性:
1 2 3 4 |
<div> <p>First name: <span th:text="${contact.firstname}">First name</span></p> <p>Last name: <span th:text="${contact.lastname}">Last name</span></p> </div> |
正如您所看到的,${...}
Thymeleaf中的内容可能是一个复杂的表达式,而不仅仅是对变量的引用。Thymeleaf使用OGNL作为其默认处理引擎,开启了广泛的可能性:运营商,连接等。
现在让我们看一个额外的功能,它可以缩短Java对象的显示。
选择语法的详细程度较低
Thymeleaf允许对对象执行选择。一旦选择了一个对象,它就可以作为评估上下文中的某种第一级变量。然后我们可以使用*{...}
语法而不是语法来引用它${...}
。
在我们的模板中,我们可以contact
使用通常的${...}
语法选择对象,然后使用以下*{...}
语法引用其属性:
1 2 3 4 |
<div th:object="${contact}"> <p>First name: <span th:text="*{firstname}">First name</span></p> <p>Last name: <span th:text="*{lastname}">Last name</span></p> </div> |
我们最终得到完全相同的渲染,但模板代码更简单。不错,不是吗?
迭代
Web应用程序的另一个常见用例是在表中显示数据:我们从数据库中加载Java对象列表并将它们显示在HTML表中。想象一下,我们用以下方式提供上下文List<Contact>
:
1 2 3 4 5 6 |
Context context = new Context(); List<Contact> contacts = new ArrayList<Contact>(); contacts.add(new Contact("John","Doe")); contacts.add(new Contact("Jane","Doe")); context.setVariable("contacts",contacts); engine.process("home", context, writer); |
迭代列表,我们使用th:each
属性:
1 2 3 4 5 6 7 8 9 10 |
<table> <tr> <th>Firstname</th> <th>Lastname</th> </tr> <tr th:each="contact : ${contacts}"> <td th:text="${contact.lastname}">The first name</td> <td th:text="${contact.firstname}">The last name</td> </tr> </table> |
我们最终得到了这个输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<table> <tr> <th rowspan="1" colspan="1">Firstname</th> <th rowspan="1" colspan="1">Lastname</th> </tr> <tr> <td rowspan="1" colspan="1">Doe</td> <td rowspan="1" colspan="1">John</td> </tr><tr> <td rowspan="1" colspan="1">Doe</td> <td rowspan="1" colspan="1">Jane</td> </tr> </table> |
注意Thymeleaf 根据所选XHTML 1.0 Strict标准的DTD 添加了一些rowspan
和colspan
属性。如果我们告诉它符合HTML 5,Thymeleaf就不会生成它们。
在完成我们对Thymeleaf的发现之前,让我们玩条件语句。
条件,«if»语法
想象一下,如果联系人列表为空,我们不想显示空表,我们可以轻松检查列表的大小,如果列表不为空,则选择显示整个表
:
1 2 3 4 5 6 7 8 9 10 |
<table th:if="${not #lists.isEmpty(contacts)}"> <tr> <th>Firstname</th> <th>Lastname</th> </tr> <tr th:each="contact : ${contacts}"> <td th:text="${contact.lastname}">The first name</td> <td th:text="${contact.firstname}">The last name</td> </tr> </table> |
请注意使用#lists
实用程序对象来检查列表是否为空。
结论
本文介绍了Thymeleaf的基本模板特征。Thymeleaf旨在用于Web应用程序,但它的灵活性使我们可以在独立环境中使用它。Thymeleaf不需要JSP编译器,可以从任何地方获取模板(文件系统,Web上下文,类路径)。您甚至可以将整个Web应用程序打包到一个简单的JAR中,这是迈向模块化的重要一步!Thymeleaf有很多功能,我们将在后续文章中看到如何将它与Spring MVC集成。
英文原文链接:https://blog.zenika.com/2013/01/18/introducing-the-thymeleaf-template-engine/
推荐阅读
-
Spring Boot 与 kotlin 使用Thymeleaf模板引擎渲染web视图的方法
-
Spring Boot 与 kotlin 使用Thymeleaf模板引擎渲染web视图的方法
-
SpringMVC中使用Thymeleaf模板引擎实例代码
-
Spring Boot Web开发与thymeleaf模板引擎
-
使用velocity 和 thymeleaf模板引擎编译模板
-
SpringMVC中使用Thymeleaf模板引擎实例代码
-
SpringBoot+ Thymeleaf模板引擎使用介绍
-
[SpringBoot——Web开发(使用Thymeleaf模板引擎)]
-
Spring Boot thymeleaf模板引擎的使用详解
-
在SpringBoot中如何使用模板引擎thymeleaf