电商项目专题(八)-Thymeleaf模板引擎

1.概述

简单说,Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:

Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
Thymeleaf 开箱即用的特性。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

官方教程:
https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#what-is-thymeleaf

2.为什么是Thymeleaf

简单说, Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:

  • 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
  • 开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
  • 多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
  • 与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。

接下来,我们就通过入门案例来体会Thymeleaf的魅力:

3.HelloWorld

引入依赖:
只需加入thymeleaf-2.1.4.RELEASE.jar(http://www.thymeleaf.org/download.html)包,若用maven,则加入如下配置


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-thymeleafartifactId>
dependency>

SpringBoot会自动为Thymeleaf注册一个视图解析器:
电商项目专题(八)-Thymeleaf模板引擎_第1张图片编写控制器:

@Controller
public class HelloController {

	@RequestMapping(value = "/say")
	public String hello(Model model) {
		String name = "bruce";
		model.addAttribute("name", name);
		System.out.println(name);
		return "hello";
	}
}

视图页面:


<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>hellotitle>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
head>
<body>
	<p th:text="'Hello!, ' + ${name} + '!'">测试p>
body>
html>

测试:
访问地址:http://127.0.0.1:8082/brand/list
电商项目专题(八)-Thymeleaf模板引擎_第2张图片注意事项

可能会发现在默认配置,thymeleaf对.html的内容要求很严格,如,
如果少最后的标签封闭符号/,就会报错而转到错误页。也比如你在使用Vue.js这样的库,然后有

这样的html代码,也会被thymeleaf认为不符合要求而抛出错误。
因此,建议增加下面这段:

spring.thymeleaf.mode = LEGACYHTML5

spring.thymeleaf.mode的默认值是HTML5,其实是一个很严格的检查,改为LEGACYHTML5可以得到一个可能更友好亲切的格式要求。需要注意的是,LEGACYHTML5需要搭配一个额外的库NekoHTML才可用。

<dependency>  
       <groupId>net.sourceforge.nekohtmlgroupId>  
       <artifactId>nekohtmlartifactId>  
       <version>1.9.22version>  
dependency>  

4.Thymeleaf基础

4.1.创建HTML

由上文也可以知道需要在html中添加:


<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>hellotitle>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
head>
<body>
	<p th:text="'Hello!, ' + ${name} + '!'">测试p>
body>
html>

这样,下文才能正确使用th:*形式的标签!

4.2.获取变量值${…}

通过${…}进行取值,这点和ONGL表达式语法一致!


<p th:text="'Hello!, ' + ${name} + '!'">3333p>

选择变量表达式*{…}

<div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastianspan>.p>
    <p>Surname: <span th:text="*{lastName}">Pepperspan>.p> 
    <p>Nationality: Saturnspan>.p>
div> 
等价于
<div>
    <p>Name: <span th:text="${session.user.firstName}">Sebastianspan>.p> 
    <p>Surname: <span th:text="${session.user.lastName}">Pepperspan>.p> 
    <p>Nationality: <span th:text="${session.user.nationality}">Saturnspan>.p>
div>

至于p标签里面的原有的值只是为了给前端开发时做展示用的.这样的话很好的做到了前后端分离。
这也是Thymeleaf非常好的一个特性:在无网络的情况下也能运行,也就是完全可以前端先写出页面,模拟数据展现效果,后端人员再拿此模板修改即可!

4.3.链接表达式: @{…}

用来配合link src href使用的语法,类似的标签有:th:href和th:src


<a href="details.html"
	th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">viewa>


<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">viewa>

<a href="details.html"
	th:href="@{order/{orderId}/details(orderId=${o.id})}">Content路径,默认访问static下的order文件夹a>

4.4.文本替换

<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
或者下面的表达方式:(只能包含表达式变量,而不能有条件判断等!)
<span th:text="|Welcome to our application, ${user.name}!|">

4.5.运算符

数学运算

二元操作:+, - , * , / , %
一元操作: - (负)

逻辑运算

一元 : and or
二元 : !,not

比较运算(为避免转义尴尬,可以使用括号中的英文进行比较运算!)

比较:> , < , >= , <= ( gt , lt , ge , le )
等于:== , != ( eq , ne )

条件运算

If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)

4.6 条件

if/unless
使用th:if和th:unless属性进行条件判断,th:unless于th:if恰好相反,只有表达式中的条件不成立,才会显示其内容。

Logina>

switch

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administratorp>
  <p th:case="#{roles.manager}">User is a managerp>
  <p th:case="*">User is some other thingp>
div>

4.7.循环

th:each


<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>hellotitle>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
head>
<body>
	<table>
		<tr>
			<th>IDth>
			<th>NAMEth>
			<th>AGEth>
		tr>
		<tr th:each="emp : ${empList}">
			<td th:text="${emp.id}">1td>
			<td th:text="${emp.name}">td>
			<td th:text="${emp.age}">18td>
		tr>
	table>
body>
html>

后台:

@GetMapping(value = "/hello")
public String hello(Model model) {
        List<Emp> empList = new ArrayList<>();
        empList.add(new Emp(1, "校长", 24));
        empList.add(new Emp(2, "书记", 28));
        empList.add(new Emp(3, "小海", 25));
        model.addAttribute("empList", empList);
        return "hello";
}

效果:
电商项目专题(八)-Thymeleaf模板引擎_第3张图片
进阶

迭代对象可以是java.util.List,java.util.Map,数组等;

iterStat称作状态变量,属性有:
    index:当前迭代对象的index(从0开始计算)
    count: 当前迭代对象的index(从1开始计算)
    size:被迭代对象的大小
    current:当前迭代变量
    even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)
    first:布尔值,当前循环是否是第一个
    last:布尔值,当前循环是否是最后一个

<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>hellotitle>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
head>
<body>
	<ol>
		<li>List循环:
			<table border="1">
				<tr>
					<th>用户名th>
					<th>邮箱th>
					<th>管理员th>
					<th>状态变量:indexth>
					<th>状态变量:countth>
					<th>状态变量:sizeth>
					<th>状态变量:current.userNameth>
					<th>状态变量:eventh>
					<th>状态变量:oddth>
					<th>状态变量:firstth>
					<th>状态变量:lastth>
				tr>
				<tr th:each="user,userStat : ${list}">
					<td th:text="${user.userName}">Onionstd>
					<td th:text="${user.email}">[email protected]td>
					<td th:text="${user.isAdmin}">yestd>
					<th th:text="${userStat.index}">状态变量:indexth>
					<th th:text="${userStat.count}">状态变量:countth>
					<th th:text="${userStat.size}">状态变量:sizeth>
					<th th:text="${userStat.current.userName}">状态变量:currentth>
					<th th:text="${userStat.even}">状态变量:even****th>
					<th th:text="${userStat.odd}">状态变量:oddth>
					<th th:text="${userStat.first}">状态变量:firstth>
					<th th:text="${userStat.last}">状态变量:lastth>
				tr>
			table>
		li>
		<li>Map循环:
			<div th:each="mapS:${map}">
				<div th:text="${mapS}">div>
			div>
		li>
		<li>数组循环:
			<div th:each="arrayS:${arrays}">
				<div th:text="${arrayS}">div>
			div>
		li>
	ol>
body>
html>

4.8.内置对象Utilites

一般不推荐在前端进行这些处理,前端页面以减少逻辑为宜
日期处理

/*
 * Format date with the specified pattern
 * Also works with arrays, lists or sets
 */
${#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')}

/*
 * Create a date (java.util.Date) object for the current date and time
 */
${#dates.createNow()}

/*
 * Create a date (java.util.Date) object for the current date (time set to 00:00)
 */
${#dates.createToday()}

#dates

字符串处理

/*
 * Check whether a String is empty (or null). Performs a trim() operation before check
 * Also works with arrays, lists or sets
 */
${#strings.isEmpty(name)}
${#strings.arrayIsEmpty(nameArr)}
${#strings.listIsEmpty(nameList)}
${#strings.setIsEmpty(nameSet)}

/*
 * Check whether a String starts or ends with a fragment
 * Also works with arrays, lists or sets
 */
${#strings.startsWith(name,'Don')}                  // also array*, list* and set*
${#strings.endsWith(name,endingFragment)}           // also array*, list* and set*

/*
 * Compute length
 * Also works with arrays, lists or sets
 */
${#strings.length(str)}

参考手册:https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#appendix-b-expression-utility-objects

4.9.常用标签

电商项目专题(八)-Thymeleaf模板引擎_第4张图片

5.品牌列表展示

5.1.控制器

package com.yigou.manager.controller;

import com.yigou.item.pojo.Brand;
import com.yigou.manager.service.BrandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author bruceliu
 * @create 2019-09-13 16:48
 * @description
 */
@Controller
@RequestMapping("brand")
public class BrandController {

    @Autowired
    BrandService brandService;

    @RequestMapping("list")
    public String getBrands(Model model){
        List<Brand> brands = brandService.findBrands();
        // 放入模型
        model.addAttribute("brands",brands);
        // 返回模板名称(就是classpath:/templates/目录下的html文件名)
        return "brand";
    }
}

5.2.视图

<tbody>
	<tr th:each="brand:${brands}">
		<td><input  type="checkbox" >td>			                              
		<td th:text="${brand.id}">1td>
		<td th:text="${brand.name}">联想td>									     
		<td th:text="${brand.firstChar}">Ltd>		                                 
		<td class="text-center">                                           
		<button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#editModal" th:onclick="'getById('+${brand.id}+');'">修改button>  
		<button type="button" class="btn bg-olive btn-xs" data-toggle="modal" th:onclick="'deleteById('+${brand.id}+');'">删除button>                                         
		td>
	tr>
tbody>

5.3.页面展示

电商项目专题(八)-Thymeleaf模板引擎_第5张图片

你可能感兴趣的:(电商专题)