thymeleaf模板引擎
学习链接
velocity模板引擎
freemarker模板引擎
thymeleaf模板引擎
thymeleaf官网
thymeleaf官方文档
文章目录
- 学习链接
- 工作方式
- 基本使用
- 1.字符串模板
- 2.模板文件
- 3.设置模板文件前后缀
- springboot整合thymeleaf使用
- 1.pom.xml
- 2.application.yml
- 3.启动类
- 4.IndexController
- 5.index.html
- 2. 表达式语法
- 2.1 表达式分类
- 2.2 变量表达式 ${..}
- 获取对象的属性和方法
- 常用的内置对象
- 常用的内置方法
- 2.3 链接表达式 @{..}
- 链接表达式好处
- 链接表达式结构
- 2.4 消息表达式 #{...}
- ==2.5 选择表达式 *{..}==
- 2.6 标准表达式
- 文本
- 数字
- 布尔
- null和""
- 比较逻辑运算符
- 三元表达式
- 3. 设置属性值
- th:attr
- th:text, th:utext
- th:each
- th:if, th:unless
- 4. 模板使用
- 1) 定义模板语法
- 2) 引用模板语法
- 引用其它模板中的fragment
- 引用当前模板中的fragment
- 使用id引用dom
- 3)删除模板
- 4)动态指定fragment
- 5. 内联表达式 [[..]]
- 6. th:with 局部变量
- 7. 工具类对象
- #execInfo
- #uris
- #dates
- #numbers
- #strings
- #Arrays
- #Lists
- #Maps
- #Sets
- 8. 内置对象
- #ctx
- #locale
- #request
- #session
- #servletContext
- 9. 快捷对象
- **param**
- **session**
- **application**
工作方式
基本使用
1、环境搭建
建立maven项目,引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<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.zzhua</groupId><artifactId>thymeleaf-01</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf</artifactId><version>3.0.9.RELEASE</version></dependency></dependencies></project>
2、使用
1.字符串模板
package com.zzhua;import org.junit.Test;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;public class ThymeleafTest {// 使用字符串模板@Testpublic void test01() {// 创建模板引擎TemplateEngine engine = new TemplateEngine();// 准备模板String input = "<input type='text' th:value='${name}' />";String input2 = "[[${name}]]";// 准备数据,使用contextContext context = new Context();context.setVariable("name", "zzhua");// 调用引擎,处理模板和数据String out = engine.process(input, context);String out2 = engine.process(input2, context);System.out.println("结果数据:" + out); // 结果数据:<input type='text' value='zzhua' />System.out.println("结果数据:" + out2); // 结果数据:zzhua}
}
2.模板文件
1、在resources目录下创建main.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"><!--可以不加这个命名空间-->
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>模板:[[${name}]]<input type="text" th:value="${name}"/>
</body>
</html>
2、测试
import org.junit.Test;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;public class ThymeleafTest {// 使用类路径下(resources目录)的模板文件@Testpublic void test02() {TemplateEngine engine = new TemplateEngine();// 读取磁盘中的模板文件ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();// 设置引擎使用resolverengine.setTemplateResolver(resolver);// 指定数据Context context = new Context();context.setVariable("name", "zzhua");// 处理模板String html = engine.process("main.html", context);System.out.println("html=" + html);/*输出结果html=<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body>模板:zzhua<input type="text" value="zzhua"/></body></html>*/}
}
3.设置模板文件前后缀
在resources目录下创建templates目录,并创建main.html文件
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"><!--可以不加这个命名空间-->
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>模板:[[${name}]]<input type="text" th:value="${name}"/>
</body>
</html>
测试
package com.zzhua;import org.junit.Test;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;public class ThymeleafTest {@Testpublic void test03() {TemplateEngine engine = new TemplateEngine();// 读取磁盘中的模板文件ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();resolver.setPrefix("templates/"); // 后面一定要加这个“/”resolver.setSuffix(".html");// 设置引擎使用resolverengine.setTemplateResolver(resolver);// 指定数据Context context = new Context();context.setVariable("name", "zzhua");// 处理模板String html = engine.process("main", context);System.out.println("html=" + html);/*输出结果html=<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body>模板:zzhua<input type="text" value="zzhua"/></body></html>*/}
}
springboot整合thymeleaf使用
1.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.zzhua</groupId><artifactId>thymeleaf-02</artifactId><version>0.0.1-SNAPSHOT</version><name>thymeleaf-02</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>RELEASE</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
2.application.yml
spring:thymeleaf:prefix: classpath:/templates/suffix: .htmlencoding: UTF-8cache: false
3.启动类
@SpringBootApplication
public class Thymeleaf02Application {public static void main(String[] args) {SpringApplication.run(Thymeleaf02Application.class, args);}}
4.IndexController
@Controller
public class IndexController {/*** 返回值经过返回值处理器,* 再经由 ThymeleafViewResolver 视图解析器通过controller方法返回的字符串返回view 视图对象* 调用view视图对象的render方法渲染页面返回给浏览器* @return*/@RequestMapping("index")public String index(Model model, HttpServletRequest request) {model.addAttribute("name", "zzhua");request.setAttribute("age", 25);return "index";}}
5.index.html
<!doctype html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><title>Document</title>
</head>
<body>[[${name}]]<input type="text" th:value="${name}"><input type="text" th:value="${age}"></body>
</html>
2. 表达式语法
2.1 表达式分类
序号 | 表达式 | 描述 | 例子 |
---|---|---|---|
1 | ${…} | 变量表达式,可以于获取后台传过来的值 | 中国 |
2 | *{…} | 选择变量表达式 | |
3 | #{…} | 消息表达式 | |
4 | @{…} | 链接网址表达式,可用于替换网页中的src、href等属性的值 | th:href=“@{/css/home.css}” |
5 | ~{…} | 片段表达式,可以用于引用公共的目标片段 |
2.2 变量表达式 ${…}
变量表达式有丰富的内置方法,使其更强大,更方便。
变量表达式功能
一、可以获取对象的属性和方法
二、可以使用ctx,vars,locale,request,response,session,servletContext内置对象
三、可以使用dates,numbers,strings,objects,arrays,lists,sets,maps等内置方法
获取对象的属性和方法
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>变量表达式</title>
</head>
<body><p>获取简单类型的数据</p><p th:text="${myname}"></p><p th:text="${myage}"></p><br/><p>对象类型的属性值</p><p th:text="${student.id}">id</p><p th:text="${student.name}">name</p><p th:text="${student.getName()}">name</p><p th:text="${student.email}">email</p><p th:text="${student.age}">age</p><br/><div>性别:<span th:text="${student.sex}"></span> </div><br/><div>学校名称:<span th:text="${student.mySchool.schname}"></span>学校地址:<span th:text="${student.mySchool.schaddress}"></span>学校地址2:<span th:text="${student.mySchool.getSchaddress()}"></span></div>
</body>
</html>
@Controller
public class ExpressController {@RequestMapping("/express-var")public String express_var(Model model){//添加简单类型的数据model.addAttribute("myname","zzhua");model.addAttribute("myage",25);//添加对象类型Student student = new Student();student.setId(1001);student.setName("zzhua");student.setEmail("xx@xx.com");student.setAge(26);student.sex="男";//创建shool对象School school = new School();school.setSchname("cslg");school.setSchaddress("cs");student.setMySchool(school);model.addAttribute("student",student);return "var-variable";}
}
常用的内置对象
一、ctx:上下文对象。
二、vars:上下文变量。
三、locale:上下文的语言环境。
四、request:(仅在web上下文)的 HttpServletRequest 对象。
五、response:(仅在web上下文)的 HttpServletResponse 对象。
六、session:(仅在web上下文)的 HttpSession 对象。
七、servletContext:(仅在web上下文)的 ServletContext 对象
这里以常用的Session举例,用户刊登成功后,会把用户信息放在Session中,Thymeleaf通过内置对象将值从session中获取。
// java 代码将用户名放在session中
session.setAttribute("userinfo",username);
// Thymeleaf通过内置对象直接获取
th:text="${session.userinfo}"
常用的内置方法
一、strings:字符串格式化方法,常用的Java方法它都有。比如:equals,equalsIgnoreCase,length,trim,toUpperCase,toLowerCase,indexOf,substring,replace,startsWith,endsWith,contains,containsIgnoreCase等
二、numbers:数值格式化方法,常用的方法有:formatDecimal等
三、bools:布尔方法,常用的方法有:isTrue,isFalse等
四、arrays:数组方法,常用的方法有:toArray,length,isEmpty,contains,containsAll等
五、lists,sets:集合方法,常用的方法有:toList,size,isEmpty,contains,containsAll,sort等
六、maps:对象方法,常用的方法有:size,isEmpty,containsKey,containsValue等
七、dates:日期方法,常用的方法有:format,year,month,hour,createNow等
示例
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>ITDragon Thymeleaf 内置方法</title>
</head>
<body><h2>ITDragon Thymeleaf 内置方法</h2><h3>#strings </h3><div th:if="${not #strings.isEmpty(itdragonStr)}" ><p>Old Str : <span th:text="${itdragonStr}"/></p><p>toUpperCase : <span th:text="${#strings.toUpperCase(itdragonStr)}"/></p><p>toLowerCase : <span th:text="${#strings.toLowerCase(itdragonStr)}"/></p><p>equals : <span th:text="${#strings.equals(itdragonStr, 'itdragonblog')}"/></p><p>equalsIgnoreCase : <span th:text="${#strings.equalsIgnoreCase(itdragonStr,'itdragonblog')}"/></p><p>indexOf : <span th:text="${#strings.indexOf(itdragonStr, 'r')}"/></p><p>substring : <span th:text="${#strings.substring(itdragonStr, 2, 8)}"/></p><p>replace : <span th:text="${#strings.replace(itdragonStr, 'it', 'IT')}"/></p><p>startsWith : <span th:text="${#strings.startsWith(itdragonStr, 'it')}"/></p><p>contains : <span th:text="${#strings.contains(itdragonStr, 'IT')}"/></p></div><h3>#numbers </h3> <div><p>formatDecimal 整数部分随意,小数点后保留两位,四舍五入: <span th:text="${#numbers.formatDecimal(itdragonNum, 0, 2)}"/></p><p>formatDecimal 整数部分保留五位数,小数点后保留两位,四舍五入: <span th:text="${#numbers.formatDecimal(itdragonNum, 5, 2)}"/></p></div><h3>#bools </h3><div th:if="${#bools.isTrue(itdragonBool)}"><p th:text="${itdragonBool}"></p></div><h3>#arrays </h3><div th:if="${not #arrays.isEmpty(itdragonArray)}"><p>length : <span th:text="${#arrays.length(itdragonArray)}"/></p><p>contains : <span th:text="${#arrays.contains(itdragonArray, 5)}"/></p><p>containsAll : <span th:text="${#arrays.containsAll(itdragonArray, itdragonArray)}"/></p></div><h3>#lists </h3><div th:if="${not #lists.isEmpty(itdragonList)}"><p>size : <span th:text="${#lists.size(itdragonList)}"/></p><p>contains : <span th:text="${#lists.contains(itdragonList, 0)}"/></p><p>sort : <span th:text="${#lists.sort(itdragonList)}"/></p></div><h3>#maps </h3><div th:if="${not #maps.isEmpty(itdragonMap)}"><p>size : <span th:text="${#maps.size(itdragonMap)}"/></p><p>containsKey : <span th:text="${#maps.containsKey(itdragonMap, 'thName')}"/></p><p>containsValue : <span th:text="${#maps.containsValue(itdragonMap, '#maps')}"/></p></div><h3>#dates </h3><div><p>format : <span th:text="${#dates.format(itdragonDate)}"/></p><p>custom format : <span th:text="${#dates.format(itdragonDate, 'yyyy-MM-dd HH:mm:ss')}"/></p><p>day : <span th:text="${#dates.day(itdragonDate)}"/></p><p>month : <span th:text="${#dates.month(itdragonDate)}"/></p><p>monthName : <span th:text="${#dates.monthName(itdragonDate)}"/></p><p>year : <span th:text="${#dates.year(itdragonDate)}"/></p><p>dayOfWeekName : <span th:text="${#dates.dayOfWeekName(itdragonDate)}"/></p><p>hour : <span th:text="${#dates.hour(itdragonDate)}"/></p><p>minute : <span th:text="${#dates.minute(itdragonDate)}"/></p><p>second : <span th:text="${#dates.second(itdragonDate)}"/></p><p>createNow : <span th:text="${#dates.createNow()}"/></p></div></body>
</html>
// 后台给负责给变量赋值,和跳转页面。
@RequestMapping("varexpressions")
public String varexpressions(ModelMap map) {map.put("itdragonStr", "itdragonBlog");map.put("itdragonBool", true);map.put("itdragonArray", new Integer[]{1,2,3,4});map.put("itdragonList", Arrays.asList(1,3,2,4,0));Map itdragonMap = new HashMap();itdragonMap.put("thName", "${#...}");itdragonMap.put("desc", "变量表达式内置方法");map.put("itdragonMap", itdragonMap);map.put("itdragonDate", new Date());map.put("itdragonNum", 888.888D);return "grammar/varexpressions";
}
2.3 链接表达式 @{…}
链接表达式好处
不管是静态资源的引用,form表单的请求,凡是链接都可以用@{…}。这样可以动态获取项目路径,即便项目名变了,依然可以正常访问,修改项目名,链接表达式会自动修改路径,避免资源文件找不到
- @{…} 表达式用于处理web 应用中的url地址,可以是相对地址,也可以是绝对地址。
- @{/} 是相对应用根路径,其他都是相对当前路径,斜杠开头表示相对整个应用根目录,“/”表示”/应用上下文路径"
链接表达式结构
无参:@{/xxx}
有参:@{/xxx(k1=v1,k2=v2)}对应url结构:xxx?k1=v1&k2=v2
引入本地资源:@{/项目本地的资源路径}
引入外部资源:@{/webjars/资源在jar包中的路径}
列举:第三部分的实战引用会详细使用该表达式
示例
控制器
@Controller
public class LinkControlller {@RequestMapping("/link/test")public String doLink(Model model){model.addAttribute("myname","zhangsan");return "link";}}
跳转的模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>@{}链接地址</title><script src="@{/js/jquery.3.4.1.js}" type="text/javascript"></script><script th:src="@{/js/jquery.3.4.1.js}" type="text/javascript"></script>
</head>
<body><p>链接表达式</p><a th:href="@{mytest}">1.@{mytest}</a><br/><a th:href="@{./queryStudent(id=1001)}">2. ./queryStudent</a><br/><a th:href="@{../user/list(id=1002,age=20,email='zs@163.com')}">3. ../user/list</a><br/><a th:href="@{http://www.baidu.com}">4. http://www.baidu.com</a><a th:href="@{/user/home(id=1005,name=${myname})}">5. /user/home</a><a href="/user/home">6. /user/home</a><a href="user/home">7. /user/home</a><a href="./user/home">8. /user/home</a><a href="../user/home">9. /user/home</a><br/>
</body>
</html>
将项目的根路径设置为app
server.servlet.context-path=/app
访问http://localhost:8080/app/link/test,检查网页源代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>@{}链接地址</title><script src="@{/js/jquery.3.4.1.js}" type="text/javascript"></script><!--th:src='@{/..}'中以/开头会添加上项目路径--><script src="/app/js/jquery.3.4.1.js" type="text/javascript"></script></head>
<body><p>链接表达式</p><!--th:src='@{..}'中不以/开头会添加上项目路径--><a href="mytest">1.@{mytest}</a><br/><a href="./queryStudent?id=1001">2. ./queryStudent</a><br/><a href="../user/list?id=1002&age=20&email=zs@163.com">3. ../user/list</a><br/><a href="http://www.baidu.com">4. http://www.baidu.com</a><!--th:src='@{/..}'中以/开头会添加上项目路径--><a href="/app/user/home?id=1005&name=zhangsan">5. /user/home</a><!--从这里就可以看出区别了,再模板里面直接写/开头不会带上项目路径--><a href="/user/home">6. /user/home</a><!-- http://localhost:8080/app/link/user/home --><a href="user/home">7. /user/home</a><!--./表示当前,../表示上级,(这两种都是相对当前地址栏的路径);/表示根路径(即ip:port/),所以如果要带上项目路径,要借助@{/..}这个模板标签,让模板渲染出项目路径出来--><!-- http://localhost:8080/app/link/user/hom --><a href="./user/home">8. /user/home</a><!-- http://localhost:8080/app/user/home --><a href="../user/home">9. /user/home</a><br/>
</body>
</html>
2.4 消息表达式 #{…}
消息表达式一般用于国际化的场景。结构:th:text=“#{msg}”。
示例
1、在resources目录下,新建【i18n】文件夹,并在此文件夹下创建3个文件【messages.properties、messages_en_US.properties、messages_zh_CN.properties】,并在application.yml文件添加配置。
【messages.properties】
login=login|登录
【messages_en_US.properties】
login=login
【messages_zh_CN.properties】
login=登录
【application.yml】
spring:thymeleaf:prefix: classpath:/templates/suffix: .htmlencoding: UTF-8cache: falsemessages:basename: i18n/messages
2、创建LocalResolver的bean放入spring容器(名字是localResovler),将会自动被DispatcherServlet获取
@Component("localeResolver")
public class MyLocaleResolver implements LocaleResolver {@Overridepublic Locale resolveLocale(HttpServletRequest request) {String lang = request.getParameter("lang");Locale locale = Locale.getDefault();if (!StringUtils.isEmpty(lang)) {String[] data = lang.split("_");locale = new Locale(data[0], data[1]);}return locale;}@Overridepublic void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {}
}
3、controller控制器和模板
@Controller
public class LoginController {@RequestMapping("login")public String login() {return "login";}}
<!doctype html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><title>Document</title>
</head>
<body><input type="text" th:value="#{login}"/>国际化:[[#{login}]]</body>
</html>
4、测试
2.5 选择表达式 *{…}
示例
控制器
@GetMapping("select")
public String select(Model model, HttpServletRequest request,HttpSession httpSession) {model.addAttribute("user", new User("zzhua", 25));request.setAttribute("requestUser", new User("zjj", 24));httpSession.setAttribute("sessionUser", new User("zj", 26));return "frag/select";
}
select.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>注意:即便注释了代码,<span th:inline="none">[[${..}]],</span>
仍然会被解析(这里使用了禁用内联,否则还是回去解析),所以如果遇到报错,不要忽略注释
<br/>==============================<br/>[[${user}]]
[[${#request.getAttribute('user')}]]
[[${#request.getAttribute('user').getName()}]]
[[${#request.getAttribute('user').getAge()}]]<br/>==============================<br/>request或者model中的数据可以直接通过${}去拿,注意request没有快捷对象,因为可以直接拿
[[${requestUser}]]
[[${#request.getAttribute('requestUser')}]]
[[${#request.getAttribute('requestUser').getName()}]]
[[${#request.getAttribute('requestUser').getAge()}]]<br/>==============================<br/>session中的数据不能直接这样去取,需要使用内置对象#session去属性中拿
-[[${sessionUser}]]-[[${#session.getAttribute('sessionUser')}]]
[[${#session.getAttribute('sessionUser').getName()}]]
[[${#session.getAttribute('sessionUser').getAge()}]]<br/>或者使用快捷对象去拿
[[${session}]]
[[${session.sessionUser}]]
[[${session.sessionUser.getName()}]]
[[${session.sessionUser.getAge()}]]<br/>==============================<br/><div th:object="${user}"><p>name: <span th:text="*{name}">Sebastian</span></p><p>age: <span th:text="*{age}">Pepper</span></p><p>name: <span th:text="${user.name}">Sebastian</span></p><p>age: <span th:text="${user.age}">Pepper</span></p>
</div></body>
</html>
测试
2.6 标准表达式
文本
文本文字只是在单引号之间指定的字符串。它们可以包含任何字符,如果字符之中没有空格,可以不加单引号。使用“+”连接文本。也可以使用“|”连接文本。
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>文本使用</p><p th:text="学习文本表达式">文本处理</p><p th:text="'hello thymeleaf'">有空格的文本</p><p th:text="'宝马'+'良驹'">连接字符串+</p><p th:text="'学习'+${info}">学习开发语言</p><p th:text="学习+${info}">学习开发语言</p><p th:text="|'您学习'${info}|">学习</p><p th:text="|您学习${info}|">学习</p><p th:text="您好 + |${n1},${n2}|">学习开发语言</p><p th:text="123">数字文本</p><p th:text="true">boolean文本</p>
</body>
</html>
控制器
@Controller
public class TextController {@RequestMapping("/text")public String doText(Model model){model.addAttribute("info","语言java 和 go");model.addAttribute("n1","zhangsan");model.addAttribute("n2","lisi");return "text";}}
渲染模板
数字
数字文字就是:数字,算术运算也可用:+,- ,*,/和%,表达式中的值可以与进行比较>,<,>=和<=符号,以及== 和!=可以被用来检查是否相等。一些符合需要使用实体gt( > ) ,lt(< ) , ge( >= ),le ( <= ) , not ( !)。还有eq ( == ) , neq ( !=)。
示例
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>数字表达式使用</p><p th:text="'55'"></p><p th:text="55">字面常量数字</p><p th:text="6+6">数字运算</p><p th:text="'6'+'6'"></p><p th:text="'6'+6"></p><p th:text="6+6+'这个一个字符串'+10+20">字符串连接</p><p th:text="6+6+'连接字符串'+(10+20)">使用括号提高优先级</p><p th:text="${n1}-${n2}">使用模型中数据</p><p th:text="100-${n2}">计算</p>
</body>
</html>
控制器
@GetMapping("/num")
public String doNum(Model model){model.addAttribute("n1",100);model.addAttribute("n2",20);return "num";
}
布尔
布尔是true , false。and(与),or(或),not(非)、!(非)
th:if="布尔值”,布尔值为true显示标签,反之不显示
示例
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p> boolean 表达式</p><p th:text="true">真</p><p th:if="${married}">已婚了,married=true</p><p th:if="${age1} > 18">已经成年了</p><p th:if="${age1} > 18">没有成年</p><p th:if="${age2} < 18">没有成年</p><p th:if="${age2} < 18">没有成年</p><p th:if="${married} and ${age1} > 18">组合使用and</p><p th:if="${married} and ${age2} < 18">组合使用and</p>[[${age1} < ${age2}?'zzhua':'zj']][[${age1} > ${age2}?'zzhua':'zj']][[${age1} + ${age2}]]
</body>
</html>
控制器
@GetMapping("/bool")
public String doBool(Model model){model.addAttribute("age1",19);model.addAttribute("age2",16);model.addAttribute("married",true);return "bool";
}
渲染模板
null和""
null字面量,可以在页面直接使用,也可以判断数据是否为null。当数据为null,标签和内容不显示。空字符串和null处理结果一样。
示例
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>null和""字符串使用</p><p th:text="null">null值</p><p th:text="''">空字符串</p><p th:if="${name} == null">name 是 null</p><p th:if="${myname} ==''">myname 是''字符串</p><p th:if="${name} eq null">使用eq判断null</p><p th:if="${myname} eq ('')">使用eq判断''字符串</p><p th:if="${sex} != null">sex1</p><p th:if="${sex} == null">sex2</p><p th:if="${sex} == null" th:text="sex3">sex2</p></body>
</html>
控制器
@GetMapping("/null")
public String doNull(Model model){model.addAttribute("name",null);model.addAttribute("myname","");return "null";
}
渲染模板
比较逻辑运算符
表达式中的值可以与>,< ,>= ,<= ,== ,!= 符号进行比较。一个更简单的替代方案是使用这些运算符的文本别名gt(>)lt(<) ge(>=),le(<=),eq(==) , neq( ! =)。
逻辑运算符:and(与)、or(或)、!(非),not(非)
示例
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p th:if="10>5">10大于5</p><p th:if="10 > 6">10大于6</p><p th:if="10 > 2 and 5!=6"> 10大于2 , 5不等于6</p><p th:if="not(false)"> not(false)=true</p><p th:if="!(false)"> !(false)=true</p><p th:if="${islogin}"> 已经登录系统</p><p th:if="not(${islogin})">没有登录</p>
</body>
</html>
控制器
@GetMapping("/comp")
public String doComp(Model model){model.addAttribute("n1",100);model.addAttribute("n2",20);model.addAttribute("islogin",false);return "comp";
}
渲染模板
三元表达式
Thymeleaf中的三元运算与Java以及 JavaScript中基本一致,如A>B?X:Y,在x、Y中可以继续嵌套,只是Thymeleaf中需要使用括号包含起来,否则报错。
示例
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p th:text="10>5?'10大于5':'10不大于5'"> 判断10大于 5</p><p th:text="${age}>20 ? '大于20':'小于20'">判断20</p><p th:text="${age} == null ? 'age是null': ${age}">判断age是不是null</p><p th:text="${age} !=null ? (${age}>30?'age大于20':'不够30') : 'age 是null' ">嵌套使用三元</p><p th:text="${islogin}?'登录'">省略y表达式</p><p th:text="!${islogin}?'没有登录'">省略y</p><p th:text="${unknow} == null?'null或未定义':${unknow}"></p><p th:text="${unknow} == null?${unknow}:${unknow}">123</p><p th:text="${age} == null?'null或未定义':${age}"></p>
</body>
</html>
控制器
@GetMapping("/ternary")
public String ternary(Model model){model.addAttribute("age",20);model.addAttribute("islogin",true);return "ternary";
}
渲染模板
3. 设置属性值
属性 | 作用 |
---|---|
th:text | 计算其值表达式并将结果设置为 标签的标签体 |
th:utext | th:text 会对结果中的特殊字符转 义,th:utext 不会转义 |
th:attr | 为标签中的任意属性设置,可以 一次设置多个属性 |
th:* | 为 html 指定的属性设值,一次设 置一个 |
th:alt-title | 同时为 alt 与 title 属性赋值 |
th:lang-xmllang | 同时为 lang 、xml:lang 属性赋 值 |
th:fragment | 定义模板片段 |
th:insert | 将被引用的模板片段插⼊到自己 的标签体中 |
th:replace | 将被引用的模板片段替换掉自己 |
th:include | 类似于 th:insert,⽽不是插⼊⽚段,它只插⼊此⽚段的内容 |
th:remove | 删除模板中的某些代码片段 |
th:each | 迭代数据,如 数组、List、Map 等 |
th:if | 条件为 true 时,显示模板⽚段, 否则不显示 |
th:unless | 条件为 false 时,显示模板⽚段, 否则不显示 |
th:switch | 与 Java 中的 switch 语句等效, 有条件地显示匹配的内容 |
th:case | 配合 th:switch 使用 |
th:with | 定义局部变量 |
th:inline | 禁用内联表达式,内联 js,内联 css |
th:attr
th:attr 提供了更改标签任何属性值的能力。th:attr 使用比较少,因为他的使用比较难,语法不优雅。对于标签的特定属性,请使用 th:value,th:action, th:href,th:class,th:src,th:onclick 等等.
参考文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-attribute-values
示例
控制器
@RequestMapping("/attr")
public String doAttr(Model model){model.addAttribute("myaction","/user/login");model.addAttribute("mytext","请登录");model.addAttribute("selected",true);model.addAttribute("unselect",false);return "attr";
}
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:lang-xmllang="en"><meta charset="UTF-8"><title>Title</title><style type="text/css">.large-font{font-size: 20pt;color: red;}</style><script type="text/javascript">function fun1() {alert("button click");}</script>
</head>
<body><form action="/hello.html" method="post" th:attr="action=${myaction}">账号:<input type="text" name="username"><br/>密码:<input type="text" name="pwd"><br/><input type="button" value="登录" th:attr="onclick='fun1()',value=${mytext}"></form><br/><form th:action="@{/user/listuser}" method="get">username:<input type="text" value="" name="username"><br/>password:<input type="text" value="" name="pwd"><br/><input type="submit" th:value="${mytext}"></form><br/><a th:href="@{/hello.html} " th:class="large-font">连接地址</a><br/><img th:src="@{/img/ex1.jpg}" th:alt-title="我的图片"><br/><input type="checkbox" value="游泳" th:checked="${selected}">游泳<br/><input type="checkbox" value="骑行" th:checked="${unselect}">骑行<br/>
</body>
</html>
渲染模板
<!DOCTYPE html>
<html lang="en">
<head lang="en" xml:lang="en"><meta charset="UTF-8"><title>Title</title><style type="text/css">.large-font{font-size: 20pt;color: red;}</style><script type="text/javascript">function fun1() {alert("button click");}</script>
</head>
<body><form action="/user/login" method="post">账号:<input type="text" name="username"><br/>密码:<input type="text" name="pwd"><br/><input type="button" value="请登录" onclick="fun1()"></form><br/><form action="/user/listuser" method="get">username:<input type="text" value="" name="username"><br/>password:<input type="text" value="" name="pwd"><br/><input type="submit" value="请登录"></form><br/><a href="/hello.html" class="large-font">连接地址</a><br/><img src="/img/ex1.jpg" alt="我的图片" title="我的图片"><br/><input type="checkbox" value="游泳" checked="checked">游泳<br/><input type="checkbox" value="骑行">骑行<br/>
</body>
</html>
th:text, th:utext
th:text:用来计算表达式并将结果设置标签体,会对计算结果中特殊字符进行转义。
th:utext: 用来计算表达式并将结果设置标签体,不转义
示例
控制器
@RequestMapping("/body/text")
public String doText(Model model){model.addAttribute("msg","学习的开发语言<b>java</b>");model.addAttribute("content","全栈开发<b>vue</b>,<b>java</b>,<b>mysql</b>");return "body";}
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p th:text="${msg}">text</p><br/><p th:utext="${content}">utext</p><p th:text="${unknow}">unknow</p>
</body>
</html>
渲染模板
th:each
th:each 处理循环,类似 jstl 中的<c:foreach>。
特点:
①:循环的对象如果是 null,不存在则不循环。
②:循环包含自身和标签内全部内容。
③:可以遍历的对象:数组;任何实现 java.util.Iterable 接⼝的对象;Enumeration 枚举;实现 Map 接口对象
语法格式:
<tr th:each="元素:${集合}"><td th:text="${元素.属性}"> 列 </td>
</tr>
状态变量
使⽤ th:each 时,Thymeleaf 提供了⼀种⽤于跟踪迭代状态的机制:状态变量。状态变量在每个 th:each 属性中定义,并包含以下数据:
①index 属性:当前迭代索引,从 0 开始
②count 属性:当前的迭代计数,从 1 开始
③size 属性:迭代变量中元素的总量
④current 属性:每次迭代的 iter 变量,即当前遍历到的元素
⑥even/odd 布尔属性:当前的迭代是偶数还是奇数。
⑦first 布尔属性:当前的迭代是否是第⼀个迭代
⑧last 布尔属性:当前的迭代是否是最后⼀个迭代
示例
控制器
@RequestMapping("/body/each")
public String doEach(Model model){List<MyStudent> list = new ArrayList<>();list.add( new MyStudent(1001,"刘备",30));list.add(new MyStudent(1002,"关羽",26));list.add(new MyStudent(1003,"张飞",22));list.add(new MyStudent(1004,"黄忠",29));list.add(new MyStudent(1005,"马超",24));model.addAttribute("students",list);//创建MapMap<String,String> stumap = new HashMap<>();stumap.put("id","学生编号1001");stumap.put("name","学生名称张飒");stumap.put("age","20");stumap.put("classname","java高级一班");model.addAttribute("stumap",stumap);// list -map结构List<Map<String, MyStudent>> listmap = new ArrayList<>();MyStudent s1 = new MyStudent(1001,"李四",20);MyStudent s2 = new MyStudent(1002,"周芳",21);Map<String,MyStudent> map = new HashMap<>();map.put("stu-1-1",s1);map.put("stu-1-2",s2);listmap.add(map);//创建map 和MyStudentmap = new HashMap<>();MyStudent s3 = new MyStudent(1003,"周宇",28);MyStudent s4= new MyStudent(1004,"张力",23);MyStudent s5 = new MyStudent(1005,"李思维",19);map.put("stu-2-1",s3);map.put("stu-2-2",s4);map.put("stu-2-3",s5);listmap.add(map);model.addAttribute("listmap",listmap);//数组String names[]= new String[]{"刘备","曹操","孙权"};model.addAttribute("names",names);//Map<String,String> 给select准备的数据Map<String,String> citys = new HashMap<>();citys.put("010","北京");citys.put("021","上海");citys.put("022","天津");citys.put("023","重庆");model.addAttribute("citys",citys);//指定select中选中的值model.addAttribute("choice","北京");return "each";}
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>循环each使用</p><br/><table><thead><tr><td>id</td><td>姓名</td><td>年龄</td></tr></thead><tbody><tr th:each="mystu:${students}"><td th:text="${mystu.id}"></td><td th:text="${mystu.name}"></td><td th:text="${mystu.age}"></td></tr></tbody></table><br/><br/><p>循环each -Map<String,String></p><p th:each="m:${stumap}"><span th:text="${m.key}"></span><span th:text="${m.value}"></span></p><br/><br/><p>循环List<Map></p><div><ul th:each="lm:${listmap}"><li th:each="entry:${lm}" th:text="${entry.key}"></li><li th:each="entry:${lm}" th:text="${entry.value}"></li></ul></div><br/><br/><p>循环数组</p><ul><li th:each="na:${names}" th:text="${na}">值</li></ul><br/><br/><p>select组件</p><div><select><option th:each="city:${citys}"th:value="${city.key}"th:text="${city.value}"th:selected="${city.value} eq ${choice}">文本</option></select></div><br/><br/><p>使用循环的状态变量,获取循环中的信息</p><table border="1" cellspacing="0" cellpadding="0"><thead><tr><td>信息</td><td>id</td><td>姓名</td><td>年龄</td><td>奇偶行</td></tr></thead><tbody><tr th:each="stu,loopStatus:${students}"><td th:text="${loopStatus.count} + '/' + ${loopStatus.size}"></td><td th:text="${stu.id}"></td><td th:text="${stu.name}"></td><td th:text="${stu.age}"></td><td th:text="${loopStatus.odd ? '奇数行':'偶数行'}"></td></tr></tbody></table></body>
</html>
th:if, th:unless
th:if 当条件满足时,显示代码片段。 条件常用 boolean 表示,true满足,反之不满足。
th:unless 是不满足条件显示代码片段, 类似 java 中 if 的 else 部分。
thymeleaf 中,true 不是唯一满足条件
1)如果表达式结果为布尔值,则为 true 或者 false
2)如果表达式的值为 null,th:if 将判定此表达式为 false
3)如果值是数字,为 0 时,判断为 false;不为零时,判定为 true
4)如果值是 String,值为 “false”、“off”、“no” 时,判定为 false,否则判断为 true,字符串为空时,也判断为 true
5)如果值不是布尔值,数字,字符或字符串的其它对象,只要不为 null,则判断为 true
示例
控制器
//判断if
@RequestMapping("/body/if")
public String doIf(Model model){//truemodel.addAttribute("old",true);model.addAttribute("login","login");model.addAttribute("num1",10);model.addAttribute("num2",-2);model.addAttribute("obj1", new MyStudent());model.addAttribute("str0","");//falsemodel.addAttribute("yong",false);model.addAttribute("str1","off");model.addAttribute("str2","no");model.addAttribute("str3","false");model.addAttribute("num3",0);model.addAttribute("obj2",null);return "if";
}
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Title</title></head><body><p>true判断</p><p th:if="true">判断boolean,true</p> [显示]<p th:if="5>0">boolean判断 5>0</p> [显示]<p th:if="'true'">判断'true'字符串</p> [显示]<p th:if="'ok'">判断'ok'</p> [显示]<p th:if="99">数字99</p> [显示]<p th:if="${old}">模型中true</p> [显示]<p th:if="${login}">模型中的string</p> [显示]<p th:if="${num1}">数字10</p> [显示]<p th:if="${num2}">数字-2</p> [显示]<p th:if="${str0}">""字符串也是true</p> [显示]<p th:if="${obj1}">非null的Student对象</p>[显示]<br/><p>不满足条件</p><p th:unless="${yong}"> yong 是 false,boolean</p> [显示]<p th:unless="${str1}">str1 是 off</p> [显示]<p th:unless="${str2}">str2 是 no</p> [显示]<p th:unless="${str3}">str3是 false字符串</p> [显示]<p th:unless="${num3}">num3是0</p> [显示]<p th:unless="${obj2}">obj2 is null</p> [显示]</body>
</html>
4. 模板使用
模板就是公用资源,可以多次重复使用的内容。 经常把页眉,页脚,菜单做成模板,在各个其他页面使用。
模板使用:先定义再使用。可以在当前页面定义模板,也可在其他页面中定义模板
1) 定义模板语法
<div th:fragment=”模板名称”>模板内容
</div>
2) 引用模板语法
① 把模板插入到当前标签中
<div th:insert=”模板所在文件名称::模板名称”>其他内容
</div>
②把模板替换当前标签
<div th:replace=”模板所在文件名称::模板名称”>其他内容
</div>
③模板标签中的内容添加到当前标签中
<div th:include=”模板所在文件名称::模板名称”>
其他内容
</div>
3)模板引用的语法
①:模板所在文件名称::模板名称
②:~{模板所在文件名称::模板名称}
4)模板作为函数形式使用
<div th:fragment="funtpl(one,two)"><p th:text="'hello' + ${one} +'-' + ${two}"> </p>
</div>
th:insert ,th:replace 使用 funtpl 模板,可以传入值
<div th:replace="frag/footer::funtpl(one='张三',two='李四')">我是参数模板
</div>
示例:
引用其它模板中的fragment
控制器
@RequestMapping("frag")
public String main(Model model) {model.addAttribute("name", "hello");return "frag/main";
}
在resources/frag目录下,创建frag.html,main.html。并且在main.html中引用frag.html中定义的fragment。
frag.html
<!DOCTYPE html>
<!--<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">-->
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><!--定义模板--><div th:fragment="t-header">页面头部</div><!--定义模板--><div th:fragment="t-footer">页面尾部</div><!--定义模板--><div th:fragment="funTpl(one,two)">hello,[[${one}]],[[${two}]]如果有传数据的话: [[${name}]]</div></body>
</html>
main.html
<!DOCTYPE html>
<!--<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">-->
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><!-- 引用模板的第一种语法 --><div th:insert="frag/frag::t-header"></div>主页<!-- 引用模板的第二种语法 --><div th:insert="~{frag/frag::t-footer}"></div><!-- 引用带传参的函数模板 --><div th:insert="~{frag/frag::funTpl('zzhua','zj')}"></div><div th:insert="~{frag/frag::funTpl(${name},'zj')}"></div><div th:insert="~{frag/frag::funTpl(one='zzhua',two='zj')}"></div><div th:insert="~{frag/frag::funTpl(two='zj',one='zzhua')}"></div><!--如下写,都会报错 开始--><div th:insert="~{frag/frag::funTpl(one='zj',unknow='xxx')}"></div><div th:insert="~{frag/frag::funTpl(one='zj')}"></div><div th:insert="~{frag/frag::funTpl(two='zzhua')}"></div><!--如下写,都会报错 结束--></body>
</html>
测试
引用当前模板中的fragment
控制器
@RequestMapping("self")
public String self() {return "frag/self";
}
self.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div th:fragment="tpl">公用模板</div><div th:replace="::tpl">引用当前页面中定义的模板</div><div th:replace="~{::tpl}">引用当前页面中定义的模板</div></body>
</html>
测试
使用id引用dom
控制器
@RequestMapping("id")
public String id() {return "frag/id";
}
id.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p id="tpl">公共段落</p><!--使用id引用当前页面的dom--><div th:replace="::#tpl">1</div> <!--replace将引入的模板替换掉当前的标签--><div th:replace="~{::#tpl}">2</div><div th:insert="::#tpl">3</div> <!--insert直接将引入的模板插入到当前的标签中--><div th:insert="~{::#tpl}">4</div><div th:include="::#tpl">3</div> <!--include是将引入的模板外层标签去除,然后再插入--><div th:include="~{::#tpl}">4</div><!--使用id引用其它页面的fragment和dom--><div th:insert="frag/self::tpl"></div><div th:insert="frag/self::#tpl2"></div></body>
</html>
self.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div th:fragment="tpl">公用模板</div><!--使用其它模板可以使用id来引用这个dom--><p id="tpl2">self段落</p><div th:replace="::tpl">引用当前页面中定义的模板</div><div th:replace="~{::tpl}">引用当前页面中定义的模板</div></body>
</html>
渲染模板
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p id="tpl">公共段落</p><p id="tpl">公共段落</p><p id="tpl">公共段落</p><div><p id="tpl">公共段落</p></div><div><p id="tpl">公共段落</p></div><div>公共段落</div><div>公共段落</div><div><div>公用模板</div></div><div><p id="tpl2">self段落</p></div></body>
</html>
3)删除模板
th:remove=”删除范围值”
1)all:删除包含标签及其所有⼦项
2)body:不删除包含标签,但删除所有的⼦项
3)tag:删除包含标签,但不要删除其⼦项
4)all-but-first:删除第一个子项以外的其它所有子项
5)none:什么都不做。该值对于动态计算有⽤。null 也会被视为 none
示例
控制器
@RequestMapping("rem")
public String rem() {return "frag/rem";
}
rem.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>准备开始删除内容</p><div th:remove="all">指定all删除选项<p>Hello<span>我是span</span></p></div><p>指定删除的是body</p><div th:remove="body">指定body<p>hello body</p></div><p>指定tag删除范围值</p><div th:remove="tag">tag范围值<p>hello</p></div><br/><p>指定all-but-first</p><div th:remove="all-but-first"><p>第一个段落</p><p>第二个段落</p><p>第三个段落</p></div></body>
</html>
渲染模板
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>准备开始删除内容</p><p>指定删除的是body</p><div></div><p>指定tag删除范围值</p>tag范围值<p>hello</p><br/><p>指定all-but-first</p><div><p>第一个段落</p></div></body>
</html>
4)动态指定fragment
控制器
@RequestMapping("dynamic")
public String dynamic(Model model) {model.addAttribute("tplname", "menu");model.addAttribute("fragname", "menuItem");return "frag/dynamic";
}
dynamic.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><!--把整个页面都插入进来了--><div th:insert="frag/menu"></div>--<div th:insert="frag/menu::menuItem"></div>--[[${tplname}]]--<div th:insert="frag/menu::${fragname}"> </div>--<div th:insert="~{frag/menu::${fragname}}"> </div>--<!--以下错误: 只能动态指定fragment, 不能动态指定模板文件路径<div th:insert="~{frag/${tplname}::menuItem}"></div>-->
</body>
</html>
menu.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>菜单1234<div th:fragment="menuItem">菜单fragment</div>
</body>
</html>
渲染模板
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>菜单1234<div>菜单fragment</div>
</body>
</html>
</div>--<div><div>菜单fragment</div></div>--menu--<div><div>菜单fragment</div></div>--<div><div>菜单fragment</div></div>--<!--以下错误: 只能动态指定fragment, 不能动态指定模板文件路径--><!--<div th:insert="~{frag/${tplname}::menuItem}"></div>--></body>
</html>
5. 内联表达式 [[…]]
需要在 thymleaf 表达式写到标签体中,而不是标签内,可以使用内联语法
内联语法
[[…]] 或 [(…)] 内联表达式,任何在 th:text 或 th:utext 属性中使⽤的表达式都可以出现在 [[…]] 或 [(…)] 中使用。
[[…]] 等价于 th:text; [(…)] 等价于 th:utext
示例
控制器
@GetMapping("/body/inline")
public String doInline(Model model){List<MyStudent> students = new ArrayList<>();MyStudent s1 = new MyStudent(1001,"刘备",28);MyStudent s2 = new MyStudent(1002,"关羽",26);MyStudent s3 = new MyStudent(1003,"张飞",24);students.add(s1);students.add(s2);students.add(s3);model.addAttribute("stulist",students);model.addAttribute("name","三国演义");model.addAttribute("info","我爱<b>中国</b>");return "inline";
}
inline.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title><script type="text/javascript" th:inline="javascript">var jsname = [[${name}]]console.log("name===" + jsname); /*name===三国演义*/var stus = [[${stulist}]] /*i=0,name=刘备,age=28inline:13 i=1,name=关羽,age=26inline:13 i=2,name=张飞,age=24*/for (var i = 0; i < stus.length; i++) {var stu = stus[i];console.log("i=" + i + ",name=" + stu.name + ",age=" + stu.age);}</script>
</head>
<body>[[${stulist}]]<p>常用的方式</p><p th:text="${name}">常用的方式获取数据</p><br/><p>使用内联inline的方式</p><p>内联获取数据:[[${name}]]</p>[[${name}]]<br/><p th:utext="${info}">传统的方式utext</p><br/><p>内联方式使用utext: [(${info})]</p>[[${info}]][(${info})]<br/><p>禁用内联</p><p th:inline="none">[[我是原样输出的数据]]</p><p th:inline="none">[(我是原样输出的数据2)]</p></body>
</html>
渲染结果
渲染
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script type="text/javascript">var jsname = "\u4E09\u56FD\u6F14\u4E49"console.log("name===" + jsname);var stus = [{"id":1001,"name":"\u5218\u5907","age":28},{"id":1002,"name":"\u5173\u7FBD","age":26},{"id":1003,"name":"\u5F20\u98DE","age":24}]for (var i = 0; i < stus.length; i++) {var stu = stus[i];console.log("i=" + i + ",name=" + stu.name + ",age=" + stu.age);}</script>
</head>
<body>[MyStudent{id=1001, name='刘备', age=28}, MyStudent{id=1002, name='关羽', age=26}, MyStudent{id=1003, name='张飞', age=24}]<p>常用的方式</p><p>三国演义</p><br/><p>使用内联inline的方式</p><p>内联获取数据:三国演义</p>三国演义<br/><p>我爱<b>中国</b></p><br/><p>内联方式使用utext: 我爱<b>中国</b></p>我爱<b>中国</b>我爱<b>中国</b><br/><p>禁用内联</p><p>[[我是原样输出的数据]]</p><p>[(我是原样输出的数据2)]</p></body>
</html>
6. th:with 局部变量
th:with=”变量名 1=值 1,变量名 2=值 2” ,定义的变量只在当前标签内有效。
示例
控制器
@GetMapping("var")
public String useVar(Model model){model.addAttribute("age",20);return "frag/var";
}
var.html
<! DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title></head>
<body><div th:with="name= 'zhangsan'"><p th:text="${name}"></p>[[${name}]]</div><div th:with="id=1001, name='lisi' , myage=${age},age=6"><p th:text="${id}"></p><p th:text="${name}"></p><p th:text="${myage}" ></p><p th:text="${age}" ></p></div></body>
</html>
渲染模板
7. 工具类对象
官网地址:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-b-expression-utility-objects
#execInfo
模板信息
常用方法
${#execInfo.templateName} 模板名称
${#execInfo.templateMode} 模板的处理模式
#uris
处理 url/uri 编码解码
常用方法
${#uris.escapePath(uri)} //编码码
${#uris.escapePath(uri, encoding)} //指定编码转码
${#uris.unescapePath(uri)} //解码
${#uris.unescapePath(uri, encoding)} //指定编码解码
#dates
java.util.Date 对象的实⽤程序⽅法,可以操作数组,set,list。
常用方法
${#dates.format(date, ‘dd/MMM/yyyy HH:mm’)}
${#dates.arrayFormat(datesArray, ‘dd/MMM/yyyy HH:mm’)}
${#dates.listFormat(datesList, ‘dd/MMM/yyyy HH:mm’)}
${#dates.setFormat(datesSet, ‘dd/MMM/yyyy HH:mm’)}
#numbers
数字对象的实⽤程序⽅法
常用方法
${#numbers.formatInteger(num,size)}:num 表示被格式的数字,size 表示整数位最少保留几位
#strings
String ⼯具类,就是字符串工具类
常用方法
{#strings.toUpperCase(name)} 大写
${#strings.toLowerCase(name)} 小写
${#strings.arrayJoin(namesArray,‘,’) 连接,合并
${#strings.arraySplit(namesStr,‘,’)} 分隔
${#strings.indexOf(name,frag)} 查找
${#strings.substring(name,3,5)} 取子串
${#strings.contains(name,‘ez’)} 是否有子串
${#strings.isEmpty(name)} 空判断
#Arrays
常用方法
${#arrays.toArray(object)}
${#arrays.toStringArray(object)}
${#arrays.toIntegerArray(object)}
${#arrays.toLongArray(object)}
${#arrays.toDoubleArray(object)}
${#arrays.toFloatArray(object)}
${#arrays.toBooleanArray(object)}
${#arrays.length(array)}
${#arrays.isEmpty(array)}
${#arrays.contains(array, element)}
#Lists
常用方法
${#lists.toList(object)}
${#lists.size(list)}
${#lists.isEmpty(list)}
${#lists.contains(list, element)}
${#lists.containsAll(list, elements)}
${#lists.sort(list)}
${#lists.sort(list, comparator)}
#Maps
常用方法
${#maps.size(map)}
${#maps.isEmpty(map)}
${#maps.containsKey(map, key)}
${#maps.containsAllKeys(map, keys)}
${#maps.containsValue(map, value)}
${#maps.containsAllValues(map, value)}
#Sets
常用方法
${#sets.toSet(object)}
${#sets.size(set)}
${#sets.isEmpty(set)}
${#sets.contains(set, element)}
${#sets.containsAll(set, elements)}
示例
控制器
@GetMapping("utils")
public String toolsObject(Model model) {model.addAttribute("mydate",new Date());model.addAttribute("price",89.35);model.addAttribute("myname","zhangsan");return "frag/utils";
}
模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body th:with="myurl='http://localhost:8080/myweb/hello.jsp?name=张三'">模板名称: <p th:text="${#execInfo.templateName}"></p>模板模式: <p th:text="${#execInfo.templateMode}"></p><br/><div th:with="espath=${#uris.escapePath(myurl)}"><p>编码: [[${espath}]]</p><p>解码: [[${#uris.unescapePath(espath)}]]</p></div><br/>原始日期: <p th:text="${mydate}"></p><p th:text="${#dates.format(mydate,'yyyy-MM-dd HH:mm:ss')}"></p><br/>原始价格: <p th:text="${price}"></p><p th:text="'1:' + ${#numbers.formatInteger(price,0)}"></p><p th:text="'2:' +${#numbers.formatInteger(price,3)}"></p><p th:text="'3:' +${#numbers.formatInteger(price,4)}"></p><p th:text="'4:' +${#numbers.formatDecimal(price,2,1)}"></p><p th:text="'5:' +${#numbers.formatDecimal(price,1,1)}"></p><p th:text="'6:' +${#numbers.formatDecimal(price,0,1)}"></p><br/><p>字符串: [[${myname}]]</p><p th:if="${#strings.isEmpty(myname)}">myname 不是 null</p><p th:text="${#strings.substring(myname,0,2)}"></p><p th:text="${#strings.indexOf(myname,'san')}"></p><p th:text="${#strings.toUpperCase(myname)}"></p></body>
</html>
渲染模板
模板名称:
frag/utils模板模式:
HTML编码: http://localhost:8080/myweb/hello.jsp%3Fname=%E5%BC%A0%E4%B8%89解码: http://localhost:8080/myweb/hello.jsp?name=张三原始日期:
Sun Jul 04 09:09:19 CST 20212021-07-04 09:09:19原始价格:
89.351:892:0893:00894:89.35:89.36:89.3字符串: zhangsanzh5ZHANGSAN
8. 内置对象
#ctx
IContext或者IWebContext的实现类(由环境决定),
常用方法
/** ======================================================================* See javadoc API for class org.thymeleaf.context.IContext* ======================================================================*/
${#ctx.locale}
${#ctx.variableNames}/** ======================================================================* See javadoc API for class org.thymeleaf.context.IWebContext* ======================================================================*/
${#ctx.request}
${#ctx.response}
${#ctx.session}
${#ctx.servletContext}
#locale
当前请求的java.util.Locale对象
${#locale}
#request
当前请求的javax.servlet.http.HttpServletRequest对象
常用方法
${#request.getAttribute(‘foo’)}
${#request.getParameter(‘foo’)}
${#request.getContextPath()}
${#request.getRequestName()}
#session
当前请求的javax.servlet.http.HttpServletRequest对象
常用方法
${#session.getAttribute(‘foo’)}
${#session.id}
${#session.lastAccessedTime}
#servletContext
当前请求的javax.servlet.ServletContext对象
常用方法
${#servletContext.getAttribute(‘foo’)}
${#servletContext.contextPath}
示例
控制器
@GetMapping("nestedObject")
public String nestedObject(Model model, HttpSession httpSession, HttpServletRequest request) {model.addAttribute("modelAttr", "我是 model中的值");request.setAttribute("requestAttr", "我是request中的值");httpSession.setAttribute("sessionAttr", "我是 session 中的值");httpSession.getServletContext().setAttribute("contextAttr", "我是context中的值");return "frag/nestedObject";
}
nestObject.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>#request:请求对象,访问javax.servlet.http.HttpServletRequest 对象</p><p>contextPath: [[${#request.getContextPath()}]]</p><p th:text="${#request.getParameter('name')}">参数 name 的值</p><p th:text="${#request.getAttribute('requestAttr')}">request 作用域</p><p th:text="${#request.getAttribute('modelAttr')}">request 获取model中的数据</p><br/><p>#session : 直接访问与当前请求关联的javax.servlet.http.HttpSession 对象</p><p th:text="${#session.getAttribute('sessionAttr')}">session 作用域</p><p th:text="${#session.getId()}">id</p><br/><p>#servletContext : 直接访问与当前请求关联的javax.servlet.ServletContext 对象</p><p th:text="${#servletContext.getAttribute('contextAttr')}"></p><p th:text="${#servletContext.getServerInfo()}"></p><br/><p th:text="${#ctx.getVariableNames()}"></p><p th:text="${#ctx.getRequest().getAttribute('modelAttr')}"></p><p th:text="${#ctx.getRequest().getAttribute('requestAttr')}"></p><p th:text="${#ctx.getSession().getAttribute('sessionAttr')}"></p><p th:text="${#ctx.getServletContext().getAttribute('contextAttr')}"></p>[[${#locale}]]</body>
</html>
渲染模板(访问:http://localhost:8080/nestedObject?name=zzhua)
#request:请求对象,访问javax.servlet.http.HttpServletRequest 对象contextPath:zzhua我是request中的值我是 model中的值#session : 直接访问与当前请求关联的javax.servlet.http.HttpSession 对象我是 session 中的值EE038A9A08F078896EC8C45E69F4EE91#servletContext : 直接访问与当前请求关联的javax.servlet.ServletContext 对象我是context中的值Apache Tomcat/9.0.24[org.springframework.web.context.request.async.WebAsyncManager.WEB_ASYNC_MANAGER, org.springframework.web.servlet.HandlerMapping.bestMatchingHandler, hiddenHttpMethodFilter.FILTERED, org.springframework.web.servlet.DispatcherServlet.CONTEXT, thymeleaf::EvaluationContext, requestAttr, org.springframework.web.servlet.resource.ResourceUrlProvider, modelAttr, org.springframework.web.servlet.View.selectedContentType, characterEncodingFilter.FILTERED, thymeleafRequestContext, org.springframework.web.servlet.DispatcherServlet.THEME_SOURCE, springMacroRequestContext, org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER, formContentFilter.FILTERED, org.springframework.web.servlet.HandlerMapping.bestMatchingPattern, requestContextFilter.FILTERED, org.springframework.web.servlet.DispatcherServlet.OUTPUT_FLASH_MAP, org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping, org.springframework.web.servlet.DispatcherServlet.FLASH_MAP_MANAGER, org.springframework.web.servlet.HandlerMapping.uriTemplateVariables, springRequestContext, org.springframework.core.convert.ConversionService, org.springframework.web.servlet.DispatcherServlet.THEME_RESOLVER]我是 model中的值我是request中的值我是 session 中的值我是context中的值zh_CN
9. 快捷对象
在web环境下使用thymeleaf,可以使用一些快捷对象去访问param请求参数、session属性、application属性,使用它们并不需要使用#
param
用于访问请求参数
/** ============================================================================* See javadoc API for class org.thymeleaf.context.WebRequestParamsVariablesMap* ============================================================================*/${param.foo} // Retrieves a String[] with the values of request parameter 'foo'
${param.size()}
${param.isEmpty()}
${param.containsKey('foo')}
session
用于访问session属性
/** ======================================================================* See javadoc API for class org.thymeleaf.context.WebSessionVariablesMap* ======================================================================*/${session.foo} // Retrieves the session atttribute 'foo'
${session.size()}
${session.isEmpty()}
${session.containsKey('foo')}
application
用于访问servletContext属性
/** =============================================================================* See javadoc API for class org.thymeleaf.context.WebServletContextVariablesMap* =============================================================================*/${application.foo} // Retrieves the ServletContext atttribute 'foo'
${application.size()}
${application.isEmpty()}
${application.containsKey('foo')}
...
示例
控制器
@GetMapping("shortcut")
public String shortcut(Model model, HttpSession httpSession, HttpServletRequest request) {model.addAttribute("modelAttr", "我是 model中的值");request.setAttribute("requestAttr", "我是request中的值");httpSession.setAttribute("sessionAttr", "我是 session 中的值");httpSession.getServletContext().setAttribute("contextAttr", "我是context中的值");return "frag/shortcut";
}
shortcut.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>[[${param.name}]][[${session.sessionAttr}]][[${application.contextAttr}]]<br/>=========================<br/>[[${param}]][[${session}]][[${application}]]<br/>=========================<br/><!--存放在session中的数据不能直接这样去拿,只有request或者model中的数据可以直接这样去拿-->[[${sessionAttr}]]</body>
</html>
渲染模板