Thymeleaf笔记
内容来自易百教程https://www.yiibai.com/thymeleaf/
Theymeleaf官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#introducing-thymeleaf
一、简介
Thymeleaf 是用于Web和独立环境的现代服务器端Java模板引擎。
Thymeleaf的主要目标是将自然模板带到您的开发工作流程中,HTM能够在浏览器中正确的显示,并且可以作为静态原型,从而在开发团队中实现更强大的协作。
Thymeleaf的主要目标是提供一个优雅和高度可维护的创建模板的方式。 为了实现这一点,它建立在自然模板的概念之上,以不影响模板作为设计原型的方式将其逻辑注入到模板文件中。 这改善了设计沟通,弥合了前端设计和开发人员之间的理解偏差。
1.Thymeleaf可以处理何种模板
- HTML
- XML
- TEXT
- JAVASCRIPT
- CSS
- RAW
2.标准方言
一个将某些逻辑应用于标记工件(标签,一些文本,注释或者仅仅是模板不是标记的占位符)的对象被称为处理器,而这些处理器的集合(可能还有一些额外的工件)是方言组成。核心库提供的方言是标准方言。
3.HelloWorld
使用Servlet进行Helloworld的演示
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yiibai</groupId>
<artifactId>helloworld</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Provided dependencies -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- Compile dependencies -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
<defaultGoal>compile</defaultGoal>
</build>
</project>
TemplateEngineUtil.java
package com.yiibai.thymeleaf3.config;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import org.thymeleaf.TemplateEngine;
/**
* Store and retrieves Thymeleaf TemplateEngine into the application servlet context.
*/
@WebListener
public class TemplateEngineUtil {
private static final String TEMPLATE_ENGINE_ATTR = "com.yiibai.thymeleaf3.TemplateEngineInstance";
public static void storeTemplateEngine(ServletContext context, TemplateEngine engine) {
context.setAttribute(TEMPLATE_ENGINE_ATTR, engine);
}
public static TemplateEngine getTemplateEngine(ServletContext context) {
return (TemplateEngine) context.getAttribute(TEMPLATE_ENGINE_ATTR);
}
}
ThymeleafConfig.java
package com.yiibai.thymeleaf3.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
/**
* Thymeleaf configuration.
*/
@WebListener
public class ThymeleafConfig implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
TemplateEngine engine = templateEngine(sce.getServletContext());
TemplateEngineUtil.storeTemplateEngine(sce.getServletContext(), engine);
}
public void contextDestroyed(ServletContextEvent sce) {
}
private TemplateEngine templateEngine(ServletContext servletContext) {
TemplateEngine engine = new TemplateEngine();
engine.setTemplateResolver(templateResolver(servletContext));
return engine;
}
private ITemplateResolver templateResolver(ServletContext servletContext) {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(servletContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setCharacterEncoding("UTF-8");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
}
indexServlet.java
package com.yiibai.thymeleaf3.web;
import com.yiibai.thymeleaf3.config.TemplateEngineUtil;
import java.io.IOException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
@WebServlet("/")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
TemplateEngine engine = TemplateEngineUtil.getTemplateEngine(request.getServletContext());
WebContext context = new WebContext(request, response, request.getServletContext());
response.setCharacterEncoding("utf-8");
context.setVariable("recipient", "Yiibai");
engine.process("index.html", context, response.getWriter());
}
}
index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Thymeleaf3 + Servlet3 示例</title>
</head>
<body>
<h1>Thymeleaf 3 + Servlet 3 示例</h1>
<p>
Hello <span th:text="${recipient}"></span>!
</p>
</body>
</html>
二、标准方言
1.啥是标准方言
Thymeleaf是非常非常可扩展的,它允许自定义的名字来定义一组模板属性(或者甚至是标签),用自定语法评估计算表达式和应用逻辑。
它还带有一些称为标准方言(称为Standard和SpringStandard)的东西,它们定义了一组功能,这些功能应该足以满足大多数情况。可以识别这些标准方言在模板中的使用,因为它将包含以th
前缀开头的属性,如<span th:text="...">
2.标准表达式
大多数Thymeleaf属性允许将它们的值设置为包含表达式,由于它们使用的方言,我们将其称为标准表达式。这些表达式可以有五种类型:
- ${}:变量表达式
- *{}:选择表达式
- #{}:消息(i18n)表达式
- @{}:连接(URL)表达式
- ~{}:片段表达式
变量表达式${}
变量表示是OGNL表达式
${session.user.name}
<span th:text="${session.user.name}">
<li th:each="book:${books}">
选择表达式*{}
选择表达式就像变量表达式一样,它们不是整个上下文变量映射上执行,而是在先前选择的对象。
它们说作用的对象由th:object属性指定:
<div th:object="${book}">
<span th:text="*{title}">
</span>
</div>
消息(i18n)表达式#{}
消息表达式(用于国际化、文本外部化)允许从外部源文件中检索特定于语言环境的消息。通过键来引用这引用消息。
<table>
<th th:text="#{header.address.city}">...</th>
<th th:text="#{header.address.country}">...</th>
</table>
链接(URL)表达式@{}
链接表达式在构建URL并向其添加有用的上下文和会话信息,对于部署在web服务器的/myapp上下文中的Web引用程序。可以使用以下的表达式:
<a href="@{/order/list}"></a>
相当于
<a href="@{/myapp/order/list}"></a>
其中网址也可以带参数
<a th:href="@{/order/details(id=${orderId},type=${orderType})}">...</a>
片段表达式~{}
片段表达式是一种简单的方法用来表示标记的片段并将其移动到模板中,由于这些片段可以被复制,传递到其他模板的参数
常用的是th:insert或者th:replace
<div th:insert="~{commons :: main}">...</div>
<div th:with="frag=~{footer :: #main/text()}">
<p th:insert="${frag}">
</div>
标准表达式中的内容
- 文字
- 文本文字,例如:
'one text'
,'Another one!'
,…
- 数字文字,例如:
0
,10
,314
,31.01
,112.83
,…
- 布尔文字,例如:
true
,false
- Null文字,例如:
Null
- 文字标记,例如:
one
,sometext
,main
,…
- 文本文字,例如:
- 文本操作:
- 字符串连接:
+
- 文字替换:
|The name is ${name}|
- 字符串连接:
- 算术运算:
- 二进制操作:
+
,-
,*
,/
,%
- 减号(一元运算符):
-
- 二进制操作:
- 布尔运算:
- 二进制运算符,
and
,or
- 布尔否定(一元运算符):
!
,not
- 二进制运算符,
- 比较和相等:
- 比较运算符:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - 相等运算符:
==
,!=
(eq
,ne
)
- 比较运算符:
- 条件操作符:
- If-then:
(if) ? (then)
- If-then-else:
(if) ? (then) : (else)
- Default:
(value) ?: (defaultvalue)
- If-then:
三、标准url语法
1.绝对网址
用于创建到其他服务器的链接。它们需要指定一个协议名称(http://或者https://)
<a th:href="@{https://www.baidu.com}"></a>
会被渲染成
<a th:href="https://www.baidu.com"></a>
2.上下文相关的URL
如果将一个名称为myapp.war
的文件部署到一个Tomcat服务器中,那么应用程序一般是通过URL:http://localhost:8080/myapp
来访问,myapp
就是上下文名称。
与上下文相关的URL以/字符开头
<a href="@{/order/list}"
相当于
<a href="/myapp/order/list">
3.与服务器相关的URL
服务器相关的URL与上下文相关的URL非常相似,只是它们不假定URL要链接到应用程序上下文中的资源,因此允许链接到同一服务器中的不同上下文:
<a th:href="@{~/billing-app/showDetails.html}">
当前应用程序的上下文将被忽略,因此尽管应用程序部署在http:// localhost:8080 / myapp
,但该URL将输出:
<a href="/billing-app/showDetails.html">
4.与协议相关的URL
实际上是绝对的URL,它将保持用于显示当前页面的协议(HTTP,HTTPS)。 它们通常用于包括样式,脚本等外部资源:
<script th:src="@{//scriptserver.example.net/myscript.js}">...</script>
它将呈现与上面一致的URL(URL重写除外),如:
<script src="//scriptserver.example.net/myscript.js">...</script>
### 5.添加参数
<a th:href="@{/order/details(id=3,action='show_all')}"></a>
相当于
<a href="/order/details?id=3&action=show_all"></a>
还可以使用正常参数的路径变量的形式包含参数,但在URL的路径中指定一个占位符:
<a th:href="@{/order/{id}/details(id=3,action='show_all')}">
上面输出结果为:
<a href="/order/3/details?action=show_all">
四、Thymeleaf+SpringMVC实例
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yiibai</groupId>
<artifactId>springmvc5thymeleaf</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>Spring MVC - Thymeleaf Integration example</name>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Embedded Apache Tomcat required for testing war -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.8.v20171121</version>
</plugin>
</plugins>
</build>
</project>
myWebConfig.java
package com.yiibai.spring.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan("com.yiibai.spring.controller")
public class MvcWebConfig implements WebMvcConfigurer {
@Autowired
private ApplicationContext applicationContext;
/*
* STEP 1 - Create SpringResourceTemplateResolver
* */
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
return templateResolver;
}
/*
* STEP 2 - Create SpringTemplateEngine
* */
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
/*
* STEP 3 - Register ThymeleafViewResolver
* */
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
}
MvcWebApplicationInitializer.java
package com.yiibai.spring.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MvcWebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
MyController.java
package com.yiibai.spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping("/")
public String index(Model model) {
model.addAttribute("message", "Hello Spring MVC 5!");
return "index";
}
}
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>SpringMVC5+Thymeleaf示例</title>
</head>
<body>
<h1>Spring MVC + Thymeleaf Hello World example</h1>
<p th:text="${message}"></p>
</body>
</html>
五、Thymeleaf 显示bean的值
Product.java
package com.yiibai.spring.bean;
import java.util.Date;
public class Product {
private String description;
private Integer price;
private Date availableFrom;
public Product(final String description, final Integer price, final Date availableFrom) {
this.description = description;
this.price = price;
this.availableFrom = availableFrom;
}
//**** getter and setter**/
}
myController.java
package com.yiibai.spring.controller;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.yiibai.spring.bean.Product;
@Controller
public class MyController {
@GetMapping("/")
public String index(Model model) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Product product = new Product("花生油", 129, sdf.parse("2018-02-18"));
model.addAttribute("product", product);
return "index";
}
}
index.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" th:href="@{/css/main.css}" />
<title>SpringMVC5+Thymeleaf示例</title>
</head>
<body>
<h2>Spring MVC5 + Thymeleaf Bean示例</h2>
<h2>产品信息</h2>
<dl>
<dt>产品名称:</dt>
<dd th:text="${product.description}">默认产品名称</dd>
<dt>产品价格:</dt>
<dd th:text="${product.price}">350</dd>
<dt>产品有效时间:</dt>
<dd th:text="${product.availableFrom}">28-Jun-2018</dd>
</dl>
</body>
</html>
六、Thmeleaf 迭代
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" th:href="@{/css/main.css}" />
<title>Thymeleaf迭代器示例</title>
</head>
<body>
<h2>Thymeleaf迭代器示例</h2>
<table>
<thead>
<tr>
<th>产品名称</th>
<th>价格</th>
<th>有效日期</th>
</tr>
</thead>
<tbody th:remove="all-but-first">
<tr th:each="product : ${productList}">
<td th:text="${product.description}">Red chair</td>
<td th:text="${'¥' + #numbers.formatDecimal(product.price, 1, 2)}">¥350</td>
<td th:text="${#dates.format(product.availableFrom, 'dd-MM-yyyy')}">2018-02-20</td>
</tr>
</tbody>
</table>
</body>
</html>
七、条件判断
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" th:href="@{/css/main.css}" />
<style>
span.offer {
font-weight: bold;
color: green;
}
</style>
<title>Thymeleaf条件示例</title>
</head>
<body>
<h2>Thymeleaf条件示例</h2>
<table>
<thead>
<tr>
<th>行序号</th>
<th>产品名称</th>
<th>价格</th>
<th>有效日期</th>
<th>备注</th>
</tr>
</thead>
<tbody th:remove="all-but-first">
<tr th:each="product : ${productList}">
<td th:text="${productStat.count}">1</td>
<td th:text="${product.description}">Red chair</td>
<td th:text="${'¥' + #numbers.formatDecimal(product.price, 1, 2)}">¥350</td>
<td th:text="${#dates.format(product.availableFrom, 'dd-MM-yyyy')}">2018-02-20</td>
<td><span th:if="${product.price gt 100}" class="offer">特殊提供</span></td>
</tr>
<
</tbody>
</table>
</body>
</html>
八、表单
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" th:href="@{/css/main.css}" />
<title>Thymeleaf 表单示例</title>
</head>
<body>
<h2>Thymeleaf 表单示例</h2>
<form th:action="@{/saveProduct}" th:object="${product}" method="POST">
<label for="firstName">产品名称:</label>
<input type="text" th:field="*{name}" value="" /><br/>
<label for="firstName">有效日期:</label>
<input type="text" th:field="*{availableFrom}" value="2018-03-28" /> <br/>
<label for="price">价格 (RMB):</label>
<input type="text" th:field="*{price}" size="10" value="198" /><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>