配置application.properties,指定模板路径:

spring.thymeleaf.prefix=classpath:/templates/

使用模版引擎,语法优雅易懂,OGNL、SpringEL,遵循Web标准,支持HTML5.

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.3'
  • 创建模版,默认目录是 resources/templates,在此目录中创建对应的子目录和模板,留意css和js的引入规范。
<!DOCTYPE html>  
<html lang="en" xmlns:th="http://www.thymeleaf.org">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1">  
    <!--注意,引入规范,css按照如下格式引入,留意th:href-->  
    <link rel="stylesheet" type="text/css" media="all" th:href="@{/css/bootstrap.min.css}"/>  
    <title>超群测试111222333</title>  
</head>  
<body>  
<div class="container">  
    <div class="row">  
        <h3 th:text="${testModel1.title}">默认标题</h3>  
        <select class="form-select" id="selectCityId">  
            <option th:each="item : ${testModel1.list1}" th:value="${item.id}" th:text="${item.name}"  
                    th:selected="${item.id eq testModel1.selected}">  
            </option>  
        </select>  
    </div>  
  
</div>  
  
<!--注意引入规范,js按照如下格式引入,注意th:src-->  
<script type="text/javascript" th:src="@{/bootstrap/bootstrap.bundle.min.js}"></script>  
<script type="text/javascript" th:src="@{/bootstrap/bootstrap.min.js}"></script>  
<script type="text/javascript" th:src="@{/popper/popper.min.js}"></script>  
<script type="text/javascript" th:src="@{/js/jquery-3.7.1.min.js}"></script>  
<script type="text/javascript" th:src="@{/js/test.js}"></script>  
</body>  
</html>
  • 然后在 Controller 里面创建对应的方法,返回值类型是 ModelAndView,Model里面存储页面渲染所需要的数据。然后页面上使用标签来读取这个Model里面的数据。
@GetMapping("/")  
public ModelAndView testModelAndView(Model model) {  
    model.addAttribute("title", "Test Model");  
    // 返回List
    List list1 = new ArrayList();  
    list1.add(new City1(1, "Changchun"));  
    list1.add(new City1(2, "Jilin"));  
    list1.add(new City1(3,"SiPing"));  
  
    model.addAttribute("list1", list1);  
    // 返回单一属性。
    model.addAttribute("selected", 3);  
  
    return new ModelAndView("test/report", "testModel1", model);  
}
  • 修改启动,这里需要打开限制,添加css和js的路径,继承WebMvcConfigurationSupport,重写addResourceHandlers方法,将两个新的路径加进去。
@SpringBootApplication  
public class DemoApplication extends WebMvcConfigurationSupport {  
  
    public static void main(String[] args) {  
       SpringApplication.run(DemoApplication.class, args);  
    }  
  
    @Override  
    protected void addResourceHandlers(ResourceHandlerRegistry registry){  
       registry.addResourceHandler("/css/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/static/css/");  
       registry.addResourceHandler("/js/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/static/js/");  
       super.addResourceHandlers(registry);  
    }  
}

0.1. 第一种写法

<!DOCTYPE html>  
<!--引入命名空间-->  
<html lang="en" xmlns:th="http://www.thymeleaf.org">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
<!--使用th:text标签-->  
<p th:text="#{home.welcome}">取到值会替换掉这里的内容</p>  
</body>  
</html>

0.2. 第二种写法

不用引入命名空间的方式

<p data-th-text="...">取到值会替换掉这里的内容</p>  

0.3. 标准方言

变量表达式: <p th:text="${param}">取变量的值</p> 消息表达式: <p th:text="#{param}">取值</p> 文本外部化,国际化,i18n文件,键值对。 选择表达式:*{} 链接表达式:<a th:href="@{}" 分段表达式: 字面量:

算数操作:+ - * / %

<div th:with="isEven=(${prodStat.count} % 2 == 0)">

比较和等价:

条件运算符:

没有操作:

设置属性值:

boolean属性:

迭代器: 迭代器的状态变量:index, count, size, current, even/odd(奇数偶数), first, last

条件语句: th:if, th:unless,

0.4. 模版布局

页面上通用的部分

内联:

th:text 会被转义

0.5. 表达式的基本对象

#ctx: 上下文对象,

0.6. th:href

th:href 标签里面的内容会替换掉默认的href的内容。 使用的是相对路径,访问当前Controller的Action

<a href="/user/index" th:href="@{/user/index}">用户管理</a>
<a th:href="${'form' + user.id}" th:text="${user.name}"></a>

0.7. th:fragment

定义片段,以供其他地方重复使用。

<div th:fragment="header">  
    <h1>Header</h1>  
    <a href="/user/index">用户管理</a>  
</div>

0.8. th:replace

引入定义好的片段。

<div th:replace="~{fragments/header :: header}"></div>

0.9. th:each

<tr th:each="user : ${users}">  
    <td th:text="${user.name}"></td>  
    <td th:text="${user.age}"></td>  
    <td th:text="${user.gender}"></td>  
</tr>

0.10. th:object

Controller方法将对象存储在model里面,页面上直接绑定该对象的值。

@GetMapping("/form")  
public ModelAndView form(Model model) {  
    model.addAttribute("company", new Company());  
    return new ModelAndView("company/form", "model", model);  
}
<form th:action="@{/company/save}" th:method="post" th:object="${company}">  
    <input type="hidden" th:value="${company.id}" name="id"/>  
    <div class="row g-3 align-items-center mb-3">  
        <label for="name" class="col-md-1 col-form-label col-form-label-sm">企业名称</label>  
        <div class="col-md-3">  
            <input type="text" id="name" class="form-control form-control-sm" name="name"  
                   aria-label="name"  
                   aria-describedby="name">  
        </div>  
        <div class="col-md-8">  
            <span id="nameHelpInline" class="form-text text-small">  
               请输入企业名称  
            </span>  
        </div>  
    </div>  
  
    <div class="row g-3 align-items-center mb-3">  
        <label for="address"  
               class="col-md-1 col-form-label col-form-label-sm">企业地址</label>  
        <div class="col-md-3">  
            <input type="text" id="address" class="form-control form-control-sm" name="address"  
                   aria-label="address"  
                   aria-describedby="address">  
        </div>  
        <div class="col-md-8">  
            <span id="addressHelpInline" class="form-text text-small">  
               请输入企业详细地址  
            </span>  
        </div>  
    </div>  
  
    <div class="row g-3 align-items-center mb-3">  
        <label for="type1" class="col-md-1 col-form-label col-form-label-sm">类型1</label>  
        <div class="col-md-3">  
            <input type="text" id="type1" class="form-control form-control-sm" name="type1"  
                   aria-label="type1"  
                   aria-describedby="type1">  
        </div>  
        <div class="col-md-8">  
            <span id="type1HelpInline" class="form-text text-small">  
               请输入企业类型1,如:大型企业,中型企业,小型企业。  
            </span>  
        </div>  
    </div>  
  
    <div class="row ">  
        <div class="col-md-4 text-center">  
            <button type="submit" class="btn btn-sm btn-primary">保存</button>  
        </div>  
    </div>  
  
</form>