配置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>