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">&lt;!&ndash;如过为null则不显示&ndash;&gt;-->
<!--遍历出的元素,要遍历的数据--><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">&lt;!&ndash;如果为null则不显示&ndash;&gt;--><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} &gt; 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全解相关推荐

  1. 一般将来时语法课教案_「英语语法」一般过去时用法技巧全解

    大家好,我是教课蚪英语的张老师,今天我们来学习英语语法100讲的第一课,一般过去时! 一.首先我们了解一下什么是一般过去时? 英语语法 1. 概念: 描述过去的状态或过去的动作. 在英语中,非现在的以 ...

  2. atca背板_ATCA介绍全解.ppt

    ATCA介绍全解 ATCA - 概述Advanced Telecommunications Computing Architecture 高性能计算机和网络通信设备的要求: 1) 足够强的数据处理能力 ...

  3. 生成对抗网络gan原理_中国首个“芯片大学”即将落地;生成对抗网络(GAN)的数学原理全解...

    开发者社区技术周刊又和大家见面了,萌妹子主播为您带来第三期"开发者技术联播".让我们一起听听,过去一周有哪些值得我们开发者关注的重要新闻吧. 中国首个芯片大学,南京集成电路大学即将 ...

  4. Java IO编程全解(五)——AIO编程

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7794151.html 前面讲到:Java IO编程全解(四)--NIO编程 NIO2.0引入了新的异步通道的 ...

  5. Sql Server函数全解三数据类型转换函数和文本图像函数

    原文:Sql Server函数全解<三>数据类型转换函数和文本图像函数 一:数据类型转换函数 在同时处理不同数据类型的值时,SQL Server一般会自动进行隐士类型转换.对于数据类型相近 ...

  6. html5相关介绍ppt,html5介绍全解.ppt

    html5介绍全解 渐变 (Gradients) 线性渐变: background: linear-gradient(to right, red, orange, yellow, green, blu ...

  7. 语义分割中的深度学习方法全解:从FCN、SegNet到各版本DeepLab

    语义分割中的深度学习方法全解:从FCN.SegNet到各版本DeepLab 原文:https://www.sohu.com/a/155907339_610300 图像语义分割就是机器自动从图像中分割出 ...

  8. 人工操作阶段计算机是如何工作的,第一章计算机基础概述全解.ppt

    第一章计算机基础概述全解 1.2.3 汉字编码 汉字的编码 国标码:中文内码之一,汉字信息交换的标准编码.国标码是不可能在计算机内部直接采用.于是, 汉字的机内码采用变形国标码 . 国标码:作为转换为 ...

  9. python100个必背知识-python编程面试中必考的知识点,数据类型全解,笔记超全面...

    原标题:python编程面试中必考的知识点,数据类型全解,笔记超全面 python作为一门高级编程语言,它的定位是优雅.明确和简单.阅读Python编写的代码感觉像在阅读英语一样,这让使用者可以专注于 ...

最新文章

  1. System.Runtime.InteropServices.Marshal.GetTypeFromCLSID(System.Guid) 问题解决方法
  2. firefox html5 canvas,html5 Canvas
  3. 空跑Python程序
  4. 2015年各银行无抵押信用贷款利率及额度是多少?
  5. linux lvm 简介之二 扩充空间
  6. mysql 'performance_schema'.'session_variables' 问题处理
  7. [华为机试练习题]37.合唱队
  8. 用人话解释比特币原理
  9. 设置php语言,PHP语言之php-fpm 基本设置与启动
  10. linux下用到的软件
  11. 修改hosts文件屏蔽广告原理及实现
  12. 编写一个程序对Largest函数进行测试,找出一组数据的最大值
  13. 企业抖音号怎么运营矩阵?运营有何技巧?
  14. 机场生产运行数据统计指标-第二篇-航班类
  15. MATLAB基本操作及概念
  16. 如何进入游戏行业成为一个程序员
  17. 威纶通触摸屏模板,直接打开就可以用
  18. 简单操作 Cookie 注册登录
  19. win7环境下如何关闭IIS7服务
  20. Linux学习-28-用户间切换相关命令

热门文章

  1. (纯故事)我简单写几篇,就这一次
  2. 普通人在互联网上赚钱,这几个道理必须要了解一下
  3. 【C++解题报告】阿克曼(Ackmann)函数
  4. 洛谷B2144 阿克曼(Ackmann)函数
  5. ipv4如何访问ipv6的地址
  6. pytorch_nicp编译
  7. RuntimeError: NCCL error in:torch/lib/c10d/ProcessGroupNCCL.cpp:514, invalid usage, NCCL version 踩坑
  8. WIN10 2004 打印机无法共享的设置办法
  9. Oracle EBS R12 AP模块主要表结构整理
  10. Milking Order(拓扑+二分+优先队列)