Thymeleaf全解
Thymeleaf
- Thymeleaf简介
- 入门
- freemarker与Thymeleaf的对比
- 配置
- 运行原理
- 展示数据
- 小案例----->>
- th 操作属性
- 标准表达式
- 条件表达式
- 数据访问方式
- 内置对象
- 可选参数
- Thymeleaf遍历信息
- 运算符
- 算数运算符
- 关系运算符
- 逻辑运算符
- 条件运算符
- 条件运算符
- 链接网址
- 模板
- 模板
- 定义和引用片段
- 模板引擎对比
Thymeleaf简介
Thymeleaf是一个现代的服务器端 Java 模板引擎,适用于 Web 和独立环境。
Thymeleaf 的主要目标是为您的开发工作流程带来优雅的自然模板— HTML 可以在浏览器中正确显示,也可以作为静态原型工作,从而在开发团队中实现更强的协作。
Thymeleaf 具有 Spring Framework 模块、大量与您最喜爱的工具集成,以及插入您自己的功能的能力,是现代 HTML5 JVM Web 开发的理想选择 — 尽管它可以做的还有很多。
更多描述请转官网
---------------------摘自官网描述--------------------
入门
入门就是先整一个Thymeleaf程序
参照freemarker的整合,这里将freemarker的启动器换成Thymeleaf
依赖的变动就这么一点;
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.6.2</version></dependency>
这里选择最新版本的依赖,如果出现一些其他问题,后面再去解决;
freemarker与Thymeleaf的对比
配置
详细官网配置请见spring官网
源码是这样写的:
public class GTVGApplication {...private final TemplateEngine templateEngine;...public GTVGApplication(final ServletContext servletContext) {super();ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);// HTML is the default mode, but we set it anyway for better understanding of codetemplateResolver.setTemplateMode(TemplateMode.HTML);// This will convert "home" to "/WEB-INF/templates/home.html"templateResolver.setPrefix("/WEB-INF/templates/");templateResolver.setSuffix(".html");// Template cache TTL=1h. If not set, entries would be cached until expelledtemplateResolver.setCacheTTLMs(Long.valueOf(3600000L));// Cache is set to true by default. Set to false if you want templates to// be automatically updated when modified.templateResolver.setCacheable(true);this.templateEngine = new TemplateEngine();this.templateEngine.setTemplateResolver(templateResolver);...}}
以上默认配置表示 thymeleaf使用UTF-8编码,
访问时前缀template,后缀为html,
即直接转发或重定向到这个文件即可;
直接访问这个文件不可以么?
还真不可以,这个跟freemarker一致,
Thymeleaf在Spring Boot项目中放入到resources/templates中。这个文件夹中的内容是无法通过浏览器URL直接访问的(和WEB-INF效果一样),所有Thymeleaf页面必须先走控制器。
运行原理
模板解析器
//模板解析器是实现来自 Thymeleaf API 的接口的对象,全限定名称为:org.thymeleaf.templateresolver.ITemplateResolver
public interface ITemplateResolver {.../** Templates are resolved by their name (or content) and also (optionally) their * owner template in case we are trying to resolve a fragment for another template.* Will return null if template cannot be handled by this template resolver.*/public TemplateResolution resolveTemplate(final IEngineConfiguration configuration,final String ownerTemplate, final String template,final Map<String, Object> templateResolutionAttributes);
}
为了处理数据,并适应国际化的需求,模板引擎在获得request,response,还需要获得请求来自的地区;
public class HomeController implements IGTVGController {public void process(final HttpServletRequest request, final HttpServletResponse response,final ServletContext servletContext, final ITemplateEngine templateEngine)throws Exception {WebContext ctx = new WebContext(request, response, servletContext, request.getLocale());templateEngine.process("home", ctx, response.getWriter());}}
准备好上下文对象后,现在我们可以告诉模板引擎使用上下文处理模板(按其名称),并将其传递给响应编写器,以便可以将响应写入它;
展示数据
友情提醒----在展示数据之前还需要引入一个命名空间
<html lang="en"xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
因为我们在表单中使用的这些非标准属性是 HTML5 规范所不允许的。
1,Thymeleaf中表达式必须依赖标签而不能单独使用
2,标准变量表达式一般在开始标签中,以 th开头
3,语法为: <tag th:***="${key}" ></tag>
4,表达式中可以通过${}
取出域中的值并放入标签的指定位置
5,${}在这里不能单独使用,必须在 th:后面的双引号里使用
小案例----->>
比如后端---->>
@Controller
public class ShowController {@RequestMapping("/goodsinfo")public String showInfo(Map<String,Object>map){map.put("goodsname","小鸡炖蘑菇");return "sample";}
}
前端:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>这道菜是<p>"${goodsname}"</p>
<input type="text" th:value=${goodsname}>
</body>
</html>
html文件中th并没有把规定标签,所以要引入th空间;
注:这里时idea自带的提示,官方建议是引入
xmlns:th="http://www.thymeleaf.org,
**data-th-语法是在 HTML5 中编写自定义属性的标准方法,该语法无需开发人员使用任何命名空间名称;
html源代码
@Controller
public class ShowController {@RequestMapping("/goodsinfo")public String showInfo(Map<String,Object>map){map.put("goodsname","小鸡炖蘑菇");map.put("username","wet");map.put("colorful","background-color: yellowgreen");return "sample";}
}
后端传过来的数据
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:color="http://www.w3.org/1999/xhtml"xmlns:style="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>Title</title><style type="text/css"></style>
</head>
<body>这道菜是<p>"${goodsname}"</p><br>
<input type="text" th:value=${goodsname}><br>
<span style:background-color:red th:text="${goodsname}"></span>
<span th:style="${colorful}" th:text="${goodsname}"></span>
<button th:text="${goodsname}"></button>
<input type="text" name="name" th:value="${username}"></body>
</html>
简单总结一下---->
Thymeleaf将后端的数据 用th:*来展现,且只能在前标签中才能生效;
基本书写格式----->>th:标签中属性名="${}"
如果为了更方便区分可以在属性前加 data-th-标签中属性名="$()"
这两种形式是完全等效的,自己习惯哪一种就用哪一种;
以上内容均为白话形式,如有不当之处,还请参阅
Thymeleaf官方文档
th 操作属性
namespace-------th可以操作的属性
只要是html能识别的标签中的属性基本就可以;
有一点不太友好的是----1999/xhtml的引入提示会没有提示;
案例—>>
前端传来一个Goods对象
@RequestMapping("/one")public ModelAndView showone(Map<String, Object> map) {Goods goodsById = goodsService.findGoodsById(2);System.out.println(goodsById);map.put("goods", goodsById);ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("sample3");return modelAndView;}}
<h1>菜单信息</h1>
id:<span th:text="${goods.id}"></span></br>
goodsName:<span th:text="${goods.goodsname}"></span></br>
price:<span th:text="${goods.price}"></span></br>
goodsDesc:<span th:text="${goods.goodsdesc}"></span></br>
当返回的信息属性带有null时,thymeleaf并不会报错而freemarker会报错;
那如果返回对象为null时----->>
报异常
所以----->>
<h1>菜单信息</h1>
<div th:if="${goods}!=null">判断是否为空
id:<span th:text="${goods.id}"></span></br>
goodsName:<span th:text="${goods.goodsname}"></span></br>
price:<span th:text="${goods.price}"></span></br>
goodsDesc:<span th:text="${goods.goodsdesc}"></span></br></div>
th:text
文本文本只是在单引号之间指定的字符串。它们可以包含任何字符,但您应该使用 对其中的任何单引号进行转义。’
Now you are looking at a template file.
<p>home.welcome=Welcome to our <b>fantastic</b> grocery store!</p>
<p th:utext="${username}">Welcome to our grocery store!</p>
<p th:text="${username}">Welcome to our grocery store!</p>
前端显示结果
当我们用了text时,会替换事先做好的内容;
数字文本
数字文字就是:数字。
<p>The year is <span th:text="2013">1492</span>.</p>
<p>In two years, it will be <span th:text="2013 + 2">1494</span>.</p>
布尔文本
true false
<div th:if="${user.isAdmin()} == false"> ...
在这个例子中,写在大括号外面,所以是ThymeLeaf照顾它。如果它写在大括号内,那将是OGNL / SpringEL引擎来负责处理,达到的效果是一样的
<div th:if="${user.isAdmin() == false}">
true 与 false 只能在if中使用;
空文本
还可以使用文本:null
<div th:if="${variable.something} == null">
文本标记
类似于html中的选择器
数字,布尔和空文本实际上是文本标记的特殊情况。
这些标记允许在标准表达式中进行一些简化。它们的工作方式与文本文本 () 完全相同,但它们只允许使用字母 ( 和 )、数字 ()、方括号 ( 和 )、点 ()、连字符 () 和下划线 ()。所以没有空格,没有逗号等
它不需要围绕它们的任何引号。因此,我们可以这样做:
<div th:class="content">...</div>
<span data-th-class="content">hello</span>
附加文本
文本,无论是文本还是计算变量或消息表达式的结果,都可以使用运算符轻松追加:+
<span th:text="'The name of the user is ' + ${user.name}">
文字替换
文本替换允许轻松格式化包含变量值的字符串
这些替换必须用竖线 () 包围,例如:|
<span th:text="|Welcome to our application, ${user.name}!|">
这相当于:
<span th:text="'Welcome to our application,' + ${user.name} + '!'">
例子
<span data-th-text="|Hello,${#dates.format(today)}|"></span><br><span data-th-text="|Hello,${#dates.format(today,'yyyy-MM-dd')}|"></span><span data-th-text="'Hello,'+${#dates.format(today,'yyyy-MM-dd')}"></span>
<br>
文本替换可以与其他类型的表达式结合使用:
<span th:text="${onevar} + ' ' + |${twovar}, ${threevar}|">
<span data-th-text="'Hello,'+${#dates.format(today,'yyyy-MM-dd')}+|world,${#dates.format(today,'yyyy-MM-dd')}|"></span>
<br>
在文本替换中只允许使用变量/消息表达式
设置属性值
<form action="subscribe.html"><fieldset><input type="text" name="email" /><input type="submit" value="Subscribe!" /></fieldset>
</form>
此模板开始时是y一个静态原型,而不是 Web 应用程序的模板,如果要实现动态交互,则需要给此表单添加action,
<form action="subscribe.html" th:attr="action=@{/subscribe}"><fieldset><input type="text" name="email" /><input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/></fieldset>
</form>
除了输入属性,更改设置它的标签的属性值要用到----th:attr
但是,如果我们想一次设置多个属性呢?XML 规则不允许您在标记中设置属性两次,因此将采用逗号分隔的赋值列表,
<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
给定所需的消息文件,这将输出:
<img src="/gtgv/images/gtvglogo.png" title="Logo de Good Thymes" alt="Logo de Good Thymes" />
但是实际上我们会用到类似于 th:text th:title等类似简单的方式来实现,除非在thymeleaf中没有,那么才应该考虑用这种方式;
在thyme中的标签属性---->>>为特定属性设置值
预置和附加属性
<input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />
<span type="button" value="thymeleaf" class="ith" th:classappend="tht">thymeleaf</span>
这种预置和附加标签之间的区别---->>
<span class="ith" th:classappend="tht">thymeleaf1</span>
<hr>
<br>
<span class="ith" th:attrappend="class=${'tht'}">thymeleaf2</span>
<br>
<hr>
<span th:attrappend="class=${'ith'+'tht'}">thymeleaf3</span><p th:styleappend="'color:#ccc'">thymeleaf4</p>
classappend用于向元素添加 CSS 类或样式片段,而不会覆盖现有属性;
attrappend用于添加属性,并不会覆盖哦原来的属性而是在后面追加
styleappend用于追css样式
这些属性会将其评估结果附加(后缀)或前缀(前缀)到现有属性值。
固定值布尔属性
HTML具有布尔属性的概念,这些属性没有值,并且一个属性的优先性意味着值是"真的"。在 XHTML 中,这些属性只取 1 个值,即它本身。
例如:checked
<input type="checkbox" name="option2" checked /> <!-- HTML -->
<input type="checkbox" name="option1" checked="checked" /> <!-- XHTML -->
标准方言包含允许您通过评估条件来设置这些属性的属性,因此,如果计算为 **true,**则该属性将设置为其固定值,如果计算为 false,则不会设置该属性:
<input type="checkbox" name="active" th:checked="${g.goodsname}" value="肥肠鱼"/>肥肠鱼
<input type="checkbox" name="active" th:checked="${false}" value="蒸熊掌"/>蒸熊掌
<hr>
<input type="checkbox" name="active" th:checked="${true}" />
<input type="checkbox" name="active" th:checked="${false}" />
标准表达式
Simple expressions:
Variable Expressions: ${...}
Selection Variable Expressions: *{...}
Message Expressions: #{...}
Link URL Expressions: @{...}
Fragment Expressions: ~{...}
Literals
Text literals: , ,…'one text''Another one!'
Number literals: , , , ,…0343.012.3
Boolean literals: , truefalse
Null literal: null
Literal tokens: , , ,…onesometextmain
Text operations:
String concatenation: +
Literal substitutions: |The name is ${name}|
Arithmetic operations:
Binary operators: , , , , +-*/%
Minus sign (unary operator): -
Boolean operations:
Binary operators: , andor
Boolean negation (unary operator): , !not
Comparisons and equality:
Comparators: , , , (, , , ><>=<=gtltgele)
Equality operators: , (, ==!=eqne)
Conditional operators:
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
Special tokens:
No-Operation: _
简单表达式:
变量表达式:${...}
选择变量表达式:*{...}
消息表达式:#{...}
链接网址表达式:@{...}
片段表达式:~{...}
文字
文本文本:,,...'one text''Another one!'
数字文字: , , , ,...0343.012.3
布尔文字: ,truefalse
空文本:null
文字标记: , , ,...onesometextmain
文本操作:
字符串串联:+
文字替换:|The name is ${name}|
算术运算:
二元运算符: , , , , ,+-*/%
减号(一元运算符):-
布尔运算:
二元运算符: ,andor
布尔否定(一元运算符):,!not
比较和平等:
比较器: , , , ( , , ,><>=<=gtltgele)
等运算符: , (,==!=eqne)
条件运算符:
如果-那么:(if) ? (then)
如果-然后-否则:(if) ? (then) : (else)
违约:(value) ?: (defaultvalue)
特殊代币:
无操作:_
所有这些功能都可以组合和嵌套:
条件表达式
<tr th:each="goods ,g: ${goodsInfo}" th:class="${g.odd}? 'odd'"><td th:text="${goods.id}">Onions</td><td th:text="${goods.goodsname}">2.41</td><td data-th-text="${goods.price}"></td><td th:text="${goods.price}>10? ${'九折'} : #{''}">yes</td><td><span th:text="${#lists.size(goodsInfo)}">评论--爆发虎</span> comment/s<a href="不跳了,直接返回json吧"th:href="@{/comments(GoodsId=${goods.id})}"th:if="${not #lists.isEmpty(goods.goodsname)}">view</a></td></tr>
后端—>
@ResponseBody@RequestMapping("/comments")public String comments(Integer GoodsId){Goods goodsById = goodsService.findGoodsById(GoodsId);return goodsById.getGoodsname();}
th:if 不仅会计算布尔条件。它的功能不至于此,它将按照以下规则计算指定的表达式—>>
If value is not null:
If value is a boolean and is .true
If value is a number and is non-zero
If value is a character and is non-zero
If value is a String and is not “false”, “off” or “no”
If value is not a boolean, a number, a character or a String.
(If value is null, th:if will evaluate to false).
反向属性th:unless,我们可以在前面的示例中使用该属性,而不是在OGNL表达式中使用:th:if th:unlessnot
<a href="comments.html"th:href="@{/comments(prodId=${prod.id})}"
th:unless="${#lists.isEmpty(prod.comments)}">view</a>
th:switch
还有一种方法可以使用Java中的开关结构的等效物有条件地显示内容:/属性集。th:switch 与th:case
<div th:switch="${user.role}"><p th:case="'admin'">User is an administrator</p><p th:case="#{roles.manager}">User is a manager</p>
</div>
请注意,只要将一个属性计算为 ,同一开关上下文中的所有其他属性的计算结果为 。th:case true th:case false
默认选项指定为 :th:case="*"
<div th:switch="${user.role}"><p th:case="'admin'">User is an administrator</p><p th:case="#{roles.manager}">User is a manager</p><p th:case="*">User is some other thing</p>
</div>
案例演示:
<tr th:each="goods ,g: ${goodsInfo}" th:class="${g.odd}? 'odd'"><td th:text="${goods.id}">Onions</td><td th:text="${goods.goodsname}">2.41</td><td data-th-text="${goods.price}"></td><td th:text="${goods.price}>10? ${'九折'} : #{''}">yes</td><td th:switch="${goods.goodsname}"><span th:case="酸菜鱼">招牌菜</span></td><td>如果菜名是酸菜鱼则显示招牌菜<span th:text="${#lists.size(goodsInfo)}">评论--爆发虎</span> comment/s<a href="comments.html"th:href="@{/comments(GoodsId=${goods.id})}"th:if="${not #lists.isEmpty(goods.goodsname)}">view</a></td>
数据访问方式
第一种----->>
${person.father.name}
第二种----->>
${person[‘father’][‘name’]}
第三种,如果是map映射
${person[father’].name}
还可以用
${personsArray[0].name}
还可以调用方法
${person.createCompleteName()}
${person.createCompleteNameWithSeparator(’-’)}
内置对象
#ctx: the context object. 上下文对象
#vars: the context variables. 上下文变量
#locale: the context locale. 位置
#request: (only in Web Contexts) the object.HttpServletRequest请求对象
#response: (only in Web Contexts) the object.HttpServletResponse响应对象
#session: (only in Web Contexts) the object.HttpSession session对象
#servletContext: (only in Web Contexts) the object.ServletContext ServletContext对象
这样就可以向jsp中那样,将信息存储在与域对象中然后在取出来,如果可以的话还可以在Thymeleaf中做一些数据处理
除了这些基本对象之外,Thymeleaf还将为我们提供一组实用程序对象,这些对象将帮助我们在表达式中执行常见任务。
#execInfo: information about the template being processed.
#messages: methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
#uris: methods for escaping parts of URLs/URIs
#conversions: methods for executing the configured conversion service (if any).
#dates: methods for java.util.Date objects: formatting, component extraction, etc.
#calendars: analogous to #dates, but for java.util.Calendar objects.
#numbers: methods for formatting numeric objects.
#strings: methods for String objects: contains, startsWith, prepending/appending, etc.
#objects: methods for objects in general.
#bools: methods for boolean evaluation.
#arrays: methods for arrays.
#lists: methods for lists.
#sets: methods for sets.
#maps: methods for maps.
#aggregates: methods for creating aggregates on arrays or collections.
#ids: methods for dealing with id attributes that might be repeated
一些常用的内置对象案例
<p data-th-text="${#lists.size(goodsInfo)}">
<p data-th-text="${#aggregates.avg(arrayDemo)}">
<p data-th-text="${#sets.isEmpty(set)}"><p data-th-text="${#messages.msg('hello')}">
<p data-th-text="${#calendars.format(today,'dd MM yyyy' )}">
<p data-th-text="${#uris.escapePath('www.baidu.com')}">
<p data-th-text="${#dates.create(1990,10,19)}">
<p data-th-text="${#dates.format(today,'yyyy,MM,dd')}">
<p data-th-text="${#dates.year(today)}">
<p data-th-text="${#dates.month(today)}">
<p data-th-text="${#dates.day(today)}"><p data-th-text="${#strings.startsWith('ABC','A')}"></p>
<p data-th-text="${#strings.endsWith('ABC','A')}"></p>
<p data-th-text="${#strings.isEmpty('ABC')}"></p>
<p data-th-text="${#strings.concat('ABC','D')}"/>
<p data-th-text="${#strings.contains('ABC','C')}"/>
<p data-th-text="${#strings.indexOf('ABC','C')}"/>
<p th:text="${#numbers.listFormatCurrency(arrayDemo)}"/><hr>
<p data-th-text="${#numbers.formatDecimal(1084.87,1,'COMMA',2,'POINT')}"/>
1表示整数位至少保持一位(如果不够则补0),COMMA表示, point表示 .
部分结果----->>
request:<br/>
<span th:text="${#httpServletRequest.getAttribute('msg')}"></span><br/>
<span th:text="${#request.getAttribute('msg')}"></span><br/>
<span th:text="${msg}"></span><br/>
session:<br/>
<span th:text="${#httpSession.getAttribute('msg')}"></span><br/>
<span th:text="${#session.getAttribute('msg')}"></span><br/>
<span th:text="${session.msg}"></span><br/>
application:<br/>
<span th:text="${#servletContext.getAttribute('msg')}"></span><br/>
<span th:text="${application.msg}"></span><br/>
可选参数
可选参数
Not only can variable expressions be written as ${...}, but also as *{...}.
两种方式----
1,${}
2,*{}
星号语法作用 于所选对象上的表达式,而不是整个上下文上的表达式。
如果没有选定的对象,${}和*{}的操作完全相同。
例如----->>官方给出的案例
<div th:object="${session.user}"><p>Name: <span th:text="*{firstName}">Sebastian</span>.</p><p>Surname: <span th:text="*{lastName}">Pepper</span>.</p><p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p></div>
上述等同于
<div><p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p><p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p><p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
</div>
实际运用---->>
<div th:object="${goods}">
<!--可以理解为在这个标签中定义了一个变量,就累兹于java中的 Person per= new Person("name",age) ,然后用一个变量来接收这个对象 Object obj=per;--><p>id: <span th:text="*{id}">Sebastian</span></p><!--这样就很自然的调用属性--><p>goodsname: <span th:text="*{goodsname}">Pepper</span>.</p><p>price: <span th:text="*{price}">Saturn</span>.</p><p>price: <span th:text="${#object.price}">Saturn</span>.</p><p>goodsdesc: <span th:text="*{goodsdesc}">Saturn</span>.</p><p>goodsdesc: <span th:text="${goods.goodsdesc}">Saturn</span>.</p></div><span><p>goodsdesc: <span th:text="*{goods.goodsdesc}">Saturn</span>.</p>
</span>
实际上如果没有定义th:object
那么*{}
与${}
达到的效果是一样的;
Thymeleaf遍历信息
list
<table id="GoodsTable" cellpadding="0px" cellspacing="0px"><tr><th>菜品编号</th><th>菜品名称</th><th>菜品价格</th><th>菜品描述</th></tr><tr th:each="goods:${goodsInfo}"><td th:text="${goods.id}"></td><td th:text="${goods.goodsname}"></td><td th:text="${goods.price}"></td><td th:text="${goods.goodsdesc}"></td></tr>>
</table>
直接取Map:
很多时候我们不存JavaBean而是将一些值放入Map中,再将Map存在Model中,我们就需要对Map取值,对于Map取值你可以${Map名['key']}
来进行取值。也可以通过 M a p 名 . k e y 取 值 , 当 然 你 也 可 以 使 用 ‘ {Map名.key}取值,当然你也可以使用` Map名.key取值,当然你也可以使用‘{map.get(‘key’)}`(java语法)来取值,完整代码如下:
<h2>Map</h2>
<table><tr><td>place:</td><td th:text="${map.get('place')}"></td></tr><tr><td>feeling:</td><td th:text="${map['feeling']}"></td></tr>
</table>
遍历Map:
如果说你想遍历Map获取它的key和value那也是可以的,这里就要使用和List相似的遍历方法,使用th:each="item:${Map名}"进行遍历,在下面只需使用item.key和item.value即可获得值。完整代码如下:
<h2>Map遍历</h2>
<table ><tr th:each="item:${map}"><td th:text="${item.key}"></td><td th:text="${item.value}"></td></tr>
</table>
案例—>>
@RequestMapping("/showA")public ModelAndView showA(Map<String, Object> map) {List<Goods> goods = goodsService.showGoods();ModelAndView modelAndView = new ModelAndView();Map <String,Goods> map1 = new HashMap<>(6);for (Goods g :goods) {map1.put(g.getId().toString(),g);}map.put("goodsMap",map1);modelAndView.setViewName("sample4");return modelAndView;}@RequestMapping("/removeGoods")public String removeGoods(Integer id){int i = goodsService.removeInfo(id);return "redirect:showA";}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>菜单</title><style type="text/css">#GoodsTable {width: 80%;border: 1px solid blue;margin: 0px auto;}#GoodsTable th, td {border: 1px solid green;text-align: center;}#GoodsTable1 {width: 80%;border: 1px solid blue;margin: 0px auto;}#GoodsTable1 th, td {border: 1px solid green;text-align: center;}.content{background-color: red;}</style>
</head>
<body><table id="GoodsTable1" cellpadding="0px" cellspacing="0px"><tr><th>键值</th><th>菜品编号</th><th>菜品名称</th><th>菜品价格</th><th>菜品描述</th><th>优惠信息</th><th>操作</th></tr><!-- <div th:if="${goodsInfo}!=null"><!–如过为null则不显示–>-->
<!--遍历出的元素,要遍历的数据--><tr th:each="goods,k:${goodsMap}"><td th:text="${goods.key}"><td th:text="${goods.value.id}"><td th:text="${goods.value.goodsname}"><td th:text="${goods.value.price}"><td th:text="${goods.value.goodsdesc}"><td th:text="(${goods.value.goodsname}=='炸花生米')?'今日特价':''"></td><td><a data-th-href="@{/removeGoods(id=${goods.value.id})}">删除</a></td></tr><!-- </div>--></table></body>
</html>
小结---->>
<tr th:each="遍历出的每个变量:${后端传入的数据名}">
示例中u为迭代遍历。
th:each="element,status:${listinfo}"
其中status表示迭代状态。1,index:当前迭代器的索引 从0开始
2,count:当前迭代对象的计数 从1开始
3,size:被迭代对象的长度
4,even/odd:布尔值,当前循环是否是偶数/奇数 从0开始
5,first:布尔值,当前循环的是否是第一条,如果是返回true否则返回false
6,last:布尔值,当前循环的是否是最后一条,如果是则返回true否则返回false
<table id="GoodsTable1" cellpadding="0px" cellspacing="0px"><tr><th>索引</th><th>序号</th><th>总数</th><th>偶数索引</th><th>基数索引</th><th>第一?</th><th>最后?</th><th>菜品编号</th><th>菜品名称</th><th>菜品价格</th><th>菜品描述</th><th>优惠信息</th></tr>
<!-- <div th:if="${goodsInfo}!=null"><!–如果为null则不显示–>--><tr th:each="goods,g:${goodsInfo}"><td th:text="${g.index}"><td th:text="${g.count}"><td th:text="${g.size}"><td th:text="${g.odd}"><td th:text="${g.even}"><td th:text="${g.first}"><td th:text="${g.last}"><td th:text="${goods.id}"></td><td th:text="${goods.goodsname}"></td><td th:text="${goods.price}"></td><td th:text="${goods.goodsdesc}"></td><td th:text="(${goods.goodsname}=='宫保鸡丁')?'今日特价':''" ></td></tr>
<!-- </div>--></table>
放上官方给出的案例—>>
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head><title>Good Thymes Virtual Grocery</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><link rel="stylesheet" type="text/css" media="all" href="../../../css/gtvg.css" th:href="@{/css/gtvg.css}" /></head><body><h1>Product list</h1><table><tr><th>NAME</th><th>PRICE</th><th>IN STOCK</th></tr><tr th:each="prod : ${prods}"><td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td></tr></table><p><a href="../home.html" th:href="@{/}">Return to home</a></p></body></html>
可以迭代的对象,
- 任何实现的对象java.util.Iterable
- 任何实现 的对象。java.util.Enumeration
- 任何实现的对象,其值将在迭代器返回时使用,而无需在内存中缓存所有值。
- 任何实现java.util.Iterator的对象。迭代映射时,迭代变量将属于 类 。java.util.Mapjava.util.Map.Entry
- 任何数组。
- 任何其他对象都将被视为包含对象本身的单值列表。
运算符
算数运算符
算数运算符
<p data-th-text="1+1">
<p data-th-text="10-1">
<p data-th-text="1*1">
<p data-th-text="1/1">
<p data-th-text="10%1">
某些算术运算也可用±*/%
<div th:with="isEven=(${prodStat.count} % 2 == 0)">
请注意,这些运算符也可以应用于 OGNL 变量表达式本身(在这种情况下,将由 OGNL 而不是 Thymeleaf 标准表达式引擎执行):
<div th:with="isEven=${prodStat.count % 2 == 0}">
请注意,其中一些运算符存在文本别名:div 即/ mod 即%
关系运算符
关系运算符
<p data-th-text="10>1">
<p data-th-text="10 gt 1">
<p data-th-text="1<0">
<p data-th-text="1 lt 0">
<p data-th-text="1 eq 1">
<p data-th-text="1==1">
略
XML 确定不应在属性值中使用 和 符号,因此应将它们替换为相应的符号
<div th:if="${prodStat.count} > 1">
<span th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')">更简单的替代方法可能是使用其中一些运算符存在的文本别名
逻辑运算符
**逻辑运算符**
<!--<p data-th-text="10>1 and 1==0">
<p data-th-text="10 gt 1 && 1==9">
<p data-th-text="1<0 || 2 gt 1">
<p data-th-text="1 lt 0 or 10 > 9 ">
<p data-th-text="1 lt 0 or 10 ge 9 ">-->**逻辑运算符**
<p data-th-if="10 > 1 and 1==0">2</p>
<p data-th-if="10 gt 1 and 1 eq 9">0</p>
<p data-th-if="1 < 0 or 2 gt 1">2</p>
<p data-th-if="1 lt 0 or 10 > 9 ">1</p>
<p data-th-if="1 lt 0 or 10 ge 9 ">1</p>
<div th:text="1>0 and 2<3"></div>
<div th:text="1>0 and 2>3"></div>
<div th:text="1>0 or 2<3"></div>
<div th:text="1>0 or 2>3"></div>
在最新版的thymeleaf中对&& 与 ||不太 友好,报错了
条件运算符
<div th:text="${1==1}?a:b"></div><td th:text="(${goods.goodsname}=='宫保鸡丁')?'今日特价':''" ></td>
注意:
像这种空的时候,字符串默认为’’,如果是其他数据则是null
条件运算符
条件表达式旨在仅计算两个表达式中的一个,具体取决于计算条件的结果(条件本身是另一个表达式)。
让我们看一个示例片段(引入另一个属性修饰符, ):th:class
<tr th:class="${row.even}? 'even' : 'odd'">...
</tr>
后端
map.put("ifU",true);
<span data-th-text="${ifU}?'hello':'你好'"></span>
<!--前端结果-->
hello
条件表达式也可以使用括号嵌套:
<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">...
</tr>
Else 表达式也可以省略,在这种情况下,如果条件为 false,则返回 null 值:
<tr th:class="${row.even}? 'alt'">...
</tr>
默认值—>>>
在freemarker中也有默认值的表达方式---->>>>
${!''}
而在thymeleaf中,默认表达式是一种不带 then 部分的特殊条件值。它等效于某些语言(如Groovy)中存在的Elvis运算符,允许您指定两个表达式:如果计算结果不为null,则使用第一个表达式,但如果计算结果为null,则使用第二个表达式。
例如---->>
<div th:object="${session.user}">...<p>Age: <span th:text="*{age}?: '(no age specified)'">27</span>.</p>
</div>
如您所见,运算符是 ,我们在这里使用它来指定名称的默认值(在本例中为文本值),仅当计算结果为 null 时。因此,这等效于:?
Thymeleaf全解相关推荐
- 一般将来时语法课教案_「英语语法」一般过去时用法技巧全解
大家好,我是教课蚪英语的张老师,今天我们来学习英语语法100讲的第一课,一般过去时! 一.首先我们了解一下什么是一般过去时? 英语语法 1. 概念: 描述过去的状态或过去的动作. 在英语中,非现在的以 ...
- atca背板_ATCA介绍全解.ppt
ATCA介绍全解 ATCA - 概述Advanced Telecommunications Computing Architecture 高性能计算机和网络通信设备的要求: 1) 足够强的数据处理能力 ...
- 生成对抗网络gan原理_中国首个“芯片大学”即将落地;生成对抗网络(GAN)的数学原理全解...
开发者社区技术周刊又和大家见面了,萌妹子主播为您带来第三期"开发者技术联播".让我们一起听听,过去一周有哪些值得我们开发者关注的重要新闻吧. 中国首个芯片大学,南京集成电路大学即将 ...
- Java IO编程全解(五)——AIO编程
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7794151.html 前面讲到:Java IO编程全解(四)--NIO编程 NIO2.0引入了新的异步通道的 ...
- Sql Server函数全解三数据类型转换函数和文本图像函数
原文:Sql Server函数全解<三>数据类型转换函数和文本图像函数 一:数据类型转换函数 在同时处理不同数据类型的值时,SQL Server一般会自动进行隐士类型转换.对于数据类型相近 ...
- html5相关介绍ppt,html5介绍全解.ppt
html5介绍全解 渐变 (Gradients) 线性渐变: background: linear-gradient(to right, red, orange, yellow, green, blu ...
- 语义分割中的深度学习方法全解:从FCN、SegNet到各版本DeepLab
语义分割中的深度学习方法全解:从FCN.SegNet到各版本DeepLab 原文:https://www.sohu.com/a/155907339_610300 图像语义分割就是机器自动从图像中分割出 ...
- 人工操作阶段计算机是如何工作的,第一章计算机基础概述全解.ppt
第一章计算机基础概述全解 1.2.3 汉字编码 汉字的编码 国标码:中文内码之一,汉字信息交换的标准编码.国标码是不可能在计算机内部直接采用.于是, 汉字的机内码采用变形国标码 . 国标码:作为转换为 ...
- python100个必背知识-python编程面试中必考的知识点,数据类型全解,笔记超全面...
原标题:python编程面试中必考的知识点,数据类型全解,笔记超全面 python作为一门高级编程语言,它的定位是优雅.明确和简单.阅读Python编写的代码感觉像在阅读英语一样,这让使用者可以专注于 ...
最新文章
- System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(System.Guid) 问题解决方法
- firefox html5 canvas,html5 Canvas
- 空跑Python程序
- 2015年各银行无抵押信用贷款利率及额度是多少?
- linux lvm 简介之二 扩充空间
- mysql 'performance_schema'.'session_variables' 问题处理
- [华为机试练习题]37.合唱队
- 用人话解释比特币原理
- 设置php语言,PHP语言之php-fpm 基本设置与启动
- linux下用到的软件
- 修改hosts文件屏蔽广告原理及实现
- 编写一个程序对Largest函数进行测试,找出一组数据的最大值
- 企业抖音号怎么运营矩阵?运营有何技巧?
- 机场生产运行数据统计指标-第二篇-航班类
- MATLAB基本操作及概念
- 如何进入游戏行业成为一个程序员
- 威纶通触摸屏模板,直接打开就可以用
- 简单操作 Cookie 注册登录
- win7环境下如何关闭IIS7服务
- Linux学习-28-用户间切换相关命令
热门文章
- (纯故事)我简单写几篇,就这一次
- 普通人在互联网上赚钱,这几个道理必须要了解一下
- 【C++解题报告】阿克曼(Ackmann)函数
- 洛谷B2144 阿克曼(Ackmann)函数
- ipv4如何访问ipv6的地址
- pytorch_nicp编译
- RuntimeError: NCCL error in:torch/lib/c10d/ProcessGroupNCCL.cpp:514, invalid usage, NCCL version 踩坑
- WIN10 2004 打印机无法共享的设置办法
- Oracle EBS R12 AP模块主要表结构整理
- Milking Order(拓扑+二分+优先队列)