
thymeleaf 语法thymeleaf 是什么Thymeleaf 是一个现代的服务器端 Java 模板引擎既可以用于 Web 环境也能在独立环境中运行。它支持处理 HTML、XML、JavaScript、CSS 甚至纯文本文件。简单说 Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎它可以完全替代 JSP 。从代码层次上讲Thymeleaf是一个java 类库他是一个xml/xhtml/html5的模板引擎可以作为mvc的web应用的view层;Thymeleaf 的核心目标是提供一种优雅、易维护的模板创建方式。它采用自然模板的设计理念能够将业务逻辑巧妙地融入模板文件中而不会影响模板作为设计原型的功能。这样一来设计师和开发者之间的协作更加顺畅有效缩小了两个团队之间的鸿沟。Thymeleaf 从设计之初就严格遵循 Web 标准特别是 HTML5 规范让你可以创建完全符合标准的模板。为什么要使用Thymeleaf使用jsp的弊端项目目录结构繁琐页面不简洁jsp内置错误页面不能覆盖springboot默认的错误页面只能打成war不能打成jar内置的jetty服务器不支持jspThymeleaf的优点开箱即用它提供标准和spring标准两种方言可以直接套用模板实现JSTL、 OGNL表达式效果避免每天套模板、改jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块可以快速的实现表单绑定、属性编辑器、国际化等功能。有网无网的情况下模版页面都可以执行美工的页面拿来就可以用相对jsp减少了额外的标签页面也更加简洁。注意Spring-boot支持FreeMarker、Thymeleaf、jsp、veocity 。但是对freemarker和thymeleaf的支持最好不推荐使用jsp具体支持类型开箱即用Thymeleaf 支持六种不同的模板类型每种类型被称为一种模板模式1.html2.xml3.text4.JavaScript5.css6.raw有两种“标记”模板模式HTML 和 XML三种“文本”模板模式TEXT、JAVASCRIPT 和 CSS和一种“无操作”模板模式RAW。HTML 模板模式支持任何类型的 HTML 输入包括 HTML5、HTML 4 和 XHTML。系统不会进行验证或格式检查输出时会最大程度地保持模板的原始代码结构。XML 模板模式支持 XML 输入。使用此模式时代码必须格式良好比如不能有未关闭的标签、未引用的属性等。如果格式不正确解析器会抛出异常。需要注意的是系统不会执行 DTD 或 XML Schema 的验证。TEXT 模板模式支持使用特殊语法创建非标记类型的模板比如文本邮件或文档模板。值得注意的是HTML 或 XML 模板也可以按 TEXT 模式处理这时它们不会被当作标记解析所有标签、DOCTYPE、注释等都会被当作普通文本处理。JAVASCRIPT 模板模式支持在 Thymeleaf 应用中处理 JavaScript 文件。你可以像在 HTML 文件中一样在 JavaScript 文件中使用模型数据同时还能享受 JavaScript 专有的功能比如专门的转义处理或自然脚本。JAVASCRIPT 模板模式属于文本模式因此使用与 TEXT 模板模式相同的特殊语法。CSS 模板模式支持处理 Thymeleaf 应用中的 CSS 文件。和 JAVASCRIPT 模式一样CSS 模板模式也属于文本模式使用 TEXT 模板模式的特殊语法。RAW 模板模式完全不处理模板内容。它主要用于将原始资源如文件、URL 响应等直接插入到正在处理的模板中。比如你可以安全地在应用模板中包含外部的 HTML 资源即使这些资源包含 Thymeleaf 代码也不会被执行。具体用法环境配置① jar包依赖dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-thymeleaf/artifactId/dependency② 在application.properties中配置thymleafspring.thymeleaf.mode LEGACYHTML5这个配置不是必须的但是spring.thymeleaf.mode的默认值是HTML5 其实是一个很严格的检查改为LEGACYHTML5可以得到一个可能更友好亲切的格式要求。源码jar包部分源码ConfigurationProperties(prefixspring.thymeleaf)publicclassThymeleafProperties{privatestaticfinalCharsetDEFAULT_ENCODING;//规则前缀publicstaticfinalStringDEFAULT_PREFIXclasspath:/templates/;//规则后缀publicstaticfinalStringDEFAULT_SUFFIX.html;...}查看以上源码thymeleaf的自动配置了规则前缀和后缀所以只要我们把html页面放在calsspath:/templates/下thymeleaf就能自动渲染。示例Java controller层RequestMapping(/thymeleaf)publicStringthymeleaf(ModelMapmap){map.put(name,zhangsan);//往view视图传递的数据return/grammar/thymeleaf;//返回的view视图具体是返回前端页面url多为项目前端页面路径}这里的Java controller层属于页面控制器 基于springmvc容器搭建html view层url路径为templates/grammar/thymeleafh3条件表达式语法/h3div1.spanth:text${name}/spanbr2.spanth:text${name} ? ${name}学习好:李四体育好 /spanbr3.spanth:text${name} ? ${name}学习好/spanbr4.spanth:text${name2} ? 李四体育好 /spanbr/div解析后的代码h3条件表达式语法/h3div1.spanzhangsan/spanbr2.spanzhangsan学习好/spanbr3.spanzhangsan学习好/spanbr4.span/spanbr/div说明第2个表达式 name不为空时即是true则输出第一个值 zhangsan学习好 。第3个表达式 name不为空时即是true则输出第一个值 zhangsan学习好 。第4个表达式 name2不存在即是false则输出 ’ ‘即空。从第2与第4 可以看出 a? b 相当于 a? b:’’ 。效果分析数据传递整体流程分为 Controller 存值 → SpringMVC 域对象存储 → Thymeleaf 模板引擎解析渲染 → 输出静态 HTML 四步1. Controller 层ModelMap 存值数据封装阶段RequestMapping(/thymeleaf)publicStringthymeleaf(ModelMapmap){// 往ModelMap存入键值对keynamevaluezhangsanmap.put(name,zhangsan);// 返回逻辑视图名 /grammar/thymeleafreturn/grammar/thymeleaf;}1.1 ModelMap 底层本质ModelMap 实现了 Map、Model 接口底层就是一个HashMap作用临时存储要传给页面的数据。map.put(“name”, “zhangsan”)把 keyname值zhangsan存入内存 Map方法返回字符串 /grammar/thymeleaf 是逻辑视图名称交给 SpringMVC 视图解析器处理1.2 SpringMVC 视图解析流程控制器执行完毕把 ModelMap 里所有键值对全部拷贝到 Request 域对象HttpServletRequest视图解析器ThymeleafViewResolver拼接真实页面路径前缀templates/ /grammar/thymeleaf 后缀.html最终定位页面文件templates/grammar/thymeleaf.html把封装好数据的Request对象、原始 HTML 文件一并交给 Thymeleaf 模板引擎 解析2. Thymeleaf 模板引擎解析核心机制Thymeleaf 是服务端渲染模板在服务器 Java 程序内完成 HTML 替换再把纯静态 HTML 发给浏览器浏览器只接收最终渲染好的页面看不到th:*语法。2.1 域取值规则${key}${xxx}是 Thymeleaf 内置表达式语法从 Request 域、Model、Session 域按顺序查找 key 对应的值优先从当前 Request 域找 key找不到再去 Session 域都无则返回null你的代码中 map.put(“name”,“zhangsan”)同步到 Request 域所以 ${name} 能拿到zhangsan页面没有name2这个 key所以 ${name2} 取值结果为null。3. 渲染输出阶段服务器生成静态 HTML 返回浏览器Thymeleaf 遍历 HTML 所有th:*指令th:text是文本输出指令执行表达式、替换页面内容删除所有th:开头的属性浏览器不需要模板语法把处理完的纯静态 HTML 字符串通过 Http 响应返回前端浏览器所以浏览器拿到的最终源码里没有任何th:text只有替换后的纯文本就是你给出的解析后代码。完整数据流链路后端→前端全过程1.浏览器发起 GET 请求http://xxx/thymeleaf2.SpringMVC 分发请求匹配RequestMapping(“/thymeleaf”)进入 controller 方法3.Controller 封装数据map.put(“name”,“zhangsan”)存入 ModelMap4.SpringMVC 数据迁移ModelMap 数据复制到 HttpServletRequest 域5.视图解析器定位页面找到templates/grammar/thymeleaf.html6.Thymeleaf 引擎解析读取 Request 域数据解析${name}、三元表达式替换th:text对应位置文本移除全部 th 属性7.服务器返回静态 HTML渲染完成的纯 HTML 作为响应体发给浏览器浏览器展示页面只执行静态 HTML无任何模板语法残留补充关键知识点Model / ModelMap / ModelAndView 传值区别都是往页面传数据ModelMap你当前使用底层 Mapput(key,value)存值Model参数注入model.addAttribute(“name”,“zhangsan”)ModelAndView同时封装数据 视图名RequestMapping(/thymeleaf)publicModelAndViewthymeleaf(){ModelAndViewmvnewModelAndView(/grammar/thymeleaf);mv.addObject(name,zhangsan);returnmv;}三者底层最终都会把数据存入Request域Thymeleaf${key}都能读取常用语法 th属性html有的属性Thymeleaf基本都有而常用的属性大概有七八个。其中th属性执行的优先级从1~8数字越低优先级越高。th:text设置当前元素的文本内容相同功能的还有th:utext两者的区别在于前者不会转义html标签后者会。优先级不高order7th:value设置当前元素的value值类似修改指定属性的还有th:srcth:href。优先级不高order6th:each遍历循环元素和th:text或th:value一起使用。注意该属性修饰的标签位置详细往后看。优先级很高order2th:if条件判断类似的还有th:unlessth:switchth:case。优先级较高order3th:insert代码块引入类似的还有th:replaceth:include三者的区别较大若使用不恰当会破坏html结构常用于公共代码块提取的场景。优先级最高order1th:fragment定义代码块方便被th:insert引用。优先级最低order8th:object声明变量一般和*{}一起配合使用达到偷懒的效果。优先级一般order4th:attr修改任意属性实际开发中用的较少因为有丰富的其他th属性帮忙类似的还有th:attrappendth:attrprepend。优先级一般order5使用Thymeleaf属性需要注意点以下五点若要使用Thymeleaf语法首先要声明名称空间xmlns:thhttp://www.thymeleaf.org设置文本内容 th:text设置input的值 th:value循环输出 th:each条件判断 th:if插入代码块 th:insert定义代码块 th:fragment声明变量 th:objectth:each 的用法需要格外注意打个比方如果你要循环一个div中的p标签则th:each属性必须放在p标签上。若你将th:each属性放在div上则循环的是将整个div。变量表达式中提供了很多的内置方法该内置方法是用#开头请不要与#{}消息表达式弄混。th:insertth:replaceth:include 三种插入代码块的效果相似但区别很大。案例1.在controller中绑定数据ControllerpublicclassThController{RequestMapping(/success)publicStringsuccess(Modelmodel){//1.绑定一个字符串model.addAttribute(msg,this is a bString/b);model.addAttribute(msgUtext,this is a bString/b);//2.绑定一个pojo对象--先去创建一个EmpEmpempnewEmp(张三,20);model.addAttribute(emp,emp);//3.绑定一个listListlistnewArrayList();list.add(emp);list.add(newEmp(李四,20));list.add(newEmp(王五,20));model.addAttribute(emps,list);//4.绑定一个mapMapString,ObjectmapnewHashMap();map.put(Boss,newEmp(boss,30));model.addAttribute(map,map);//前缀classpath:/templates/ success 后缀.htmlreturnsuccess;}}2. 在html中使用thmeleaf语法获取数据2.1 先声明命名空间!DOCTYPEhtmlhtmllangenxmlns:thhttp://www.thymeleaf.orgheadmetacharsetUTF-8titleTitle/title/headbodyh1this is success.html/h1/body/html2.2 th:text和th:value...bodyh1this is success.html/h1!--th:text 设置当前元素的文本内容常用优先级不高--pth:text${msg}/ppth:utext${msgUtext}/p!--th:value 设置当前元素的value值常用优先级仅比th:text高--姓名inputtypetextth:value${emp.name}/年龄inputtypetextth:value${emp.age}//body...2.3 th:each...bodyh1this is success.html/h1!--th:each 遍历列表常用优先级很高仅此于代码块的插入遍历被修饰的元素--tableborder1pxth:width200pxtheadtrth编号/thth姓名/thth年龄/thth操作/th/tr/theadtbodytrth:eache:${emps}td编号/tdtdth:text${e.name}/tdtdth:text${e.age}/tdtd删除/修改/td/tr/tbodytbodytrth:eache,eState:${emps}tdth:text${eState.index1}/tdtdth:text${e.name}/tdtdth:text${e.age}/tdtd删除/修改/td/tr/tbody/table...说明:th:each“e,eState : ${emps}”其中e为循环的每一项eState是下标属性(可省略)eState属性包括index列表状态的序号从0开始 count列表状态的序号从1开始 size列表状态列表数据条数 current列表状态当前数据对象 even列表状态是否为奇数boolean类型 odd列表状态是否为偶数boolean类型 first列表状态是否为第一条boolean类型 last列表状态是否为最后一条boolean类型2.4 th:if!--th:if 条件判断类似的有th:switchth:case优先级仅次于th:each,-- p th:text${map.Boss.name} th:if${map.Boss.age gt 20}/p其中关系运算gtgreat than大于 gegreat equal大于等于 eqequal等于 ltless than小于 leless equal小于等于 nenot equal不等于是否为奇数boolean类型odd列表状态是否为偶数boolean类型first列表状态是否为第一条boolean类型last列表状态是否为最后一条boolean类型##### 2.4 th:if其中关系运算gtgreat than大于 gegreat equal大于等于 eqequal等于 ltless than小于 leless equal小于等于 nenot equal不等于