Spring Boot整合Thymeleaf
Thymeleaf是目前较为流行的视图层技术,Spring Boot官方推荐使用Thymeleaf
Thymeleaf是一个支持原生HTML文件的Java模板,可以实现前后端分离的交互方式,即视图与业务数据分开响应,塔可以直接将服务端返回的数据生成HTML文件,同时也可以处理XML、JavaScript、CSS等格式。
Thymeleaf最大的特点是既可以直接在浏览器打开(静态方式),也可以结合服务端将业务数据填充到HTML之后动态生成的页面(动态方法),Spring Boot支持Thymeleaf,使用起来非常方便。
创建Maven工程,不需要创建Web工程
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
application.yml
spring:
thymeleaf:
prefix: classpath:/templates/ #模板路径
suffix: .html #模板后缀
servlet:
content-type: text/html #设置Content-type
encoding: UTF-8 #编码方式
mode: HTML5 #校验H5格式
cache: false #关闭缓存,在开发过程中可以立即看到页面修改结果
创建Handler
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/hello")
public class HelloHandler {
@GetMapping("/index")
public ModelAndView index(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("name","张三");
return modelAndView;
}
}
启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
HTML
<!DOCTYPE html>
<html lang="en">
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Index</h1>
<p th:text="${name}">Hello World</p>
</body>
</html>
如果需要加载后台返回的业务数据,则需要在HTML页面中使用Thymeleaf模板标签来完成。
需要引入模板标签
<html xmlns:th="http://www.thymeleaf.org">
通过特定的标签完成操作
<p th:text="${name}">Hello World</p>
Thymeleaf模板标签不同于JSTL,Thymeleaf模板标签是直接嵌入到HTML原生标签内部。
Thymeleaf的常用标签
- th:text
th:text用于文本的显示,将业务数据的值填充到HTML标签中。
- th:if
th:if用于条件判断,对业务数据的值进行判断,如果条件成立,则显示内容,否则不显示,具体使用如下
@GetMapping("/if")
public ModelAndView ifTest(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("score",90);
return modelAndView;
}
<p th:if="${score>=90}">优秀</p>
<p th:if="${score>90}">良好</p>
- th:unless
th:unless也用作条件判断,逻辑与th:if相反,如果条件不成立则显示,否则不显示
@GetMapping("/unless")
public ModelAndView unlessTest(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("score",90);
return modelAndView;
}
<!--unless-->
<p th:unless="${score>=90}">unless优秀</p>
<p th:unless="${score<90}">unless良好</p>
- th:switch th:case
th:switch th:case 两个结合起来使用,用作多条件等值判断,逻辑与Java中的switch case一致,当switch中的业务数据等于某个case时,就显示该case对应的内容
@GetMapping("/switch")
public ModelAndView switchTest(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("studentId",1);
return modelAndView;
}
<div th:switch="${studentId}">
<p th:case="1">张三</p>
<p th:case="2">李四</p>
<p th:case="3">王五</p>
</div>
- th:action
用来指定请求的URL,相当于form表单中的action属性
@GetMapping("/redirect/{url}")
public String redirect(@PathVariable("url") String url){
return url;
}
@PostMapping("/login")
@ResponseBody
public String login(){
return "login";
}
<form th:action="@{/hello/login}" method="post">
<input type="submit">
</form>
或
@GetMapping("/redirect/{url}")
public String redirect(@PathVariable("url") String url, Model model){
model.addAttribute("url","/hello/login");
return url;
}
@PostMapping("/login")
@ResponseBody
public String login(){
return "login";
}
<form th:action="${url}" method="post">
<input type="submit">
</form>
如果action的值直接写在HTML中,则需要使用@{},如果是从后端传来的数据则使用${}
- th:each
用来遍历集合
实体类
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class User {
private Integer id;
private String name;
}
Handler
@GetMapping("/each")
public ModelAndView each(){
List<User> list= Arrays.asList(
new User(1,"张三"),
new User(2,"李四"),
new User(3,"王五")
);
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("list",list);
return modelAndView;
}
<!--each-->
<table>
<tr>
<th>编号</th>
<th>姓名</th>
</tr>
<tr th:each="user:${list}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
</tr>
</table>
- th:value
用来给标签赋值
@GetMapping("/value")
public ModelAndView value(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("value","Spring Boot");
return modelAndView;
}
<!--value-->
<input type="text" th:value="${value}"/>
- th:src
用来引入静态资源,相当于HTML原生标签的img、script的src属性
图片,css,js,静态加载的HTML都需要放置在resources/static文件中
@GetMapping("/src")
public ModelAndView src(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("src","/1.png");
return modelAndView;
}
<!--src-->
<img th:src="${src}"/>
如果src的值是直接写在html中则
<img th:src="@{/1.png}"/>
- th:href
用作设置超链接的href
@GetMapping("/href")
public ModelAndView href(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("href","https://www.baidu.com");
return modelAndView;
}
<!--href-->
<a th:href="${href}">百度</a>
- th:selected
用作给HTML元素设置选中,条件成立则选中,否则不选中
@GetMapping("/select")
public ModelAndView select(){
List<User> list =Arrays.asList(
new User(1,"张三"),
new User(2,"李四"),
new User(3,"王五"));
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("list",list);
modelAndView.addObject("name","");
return modelAndView;
}
<select>
<option
th:each="user:${list}"
th:value="${user.id}"
th:text="${user.name}"
th:selected="${user.name==name}"
></option>
</select>
结合th:each来使用,首先遍历list集合动态创建option元素,根据每次遍历出的user.name与业务数据中的name是否相等来决定是否选择
- th:attr
给HTML标签的任意属性赋值
@GetMapping("/attr")
public ModelAndView attr(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("attr","Spring Boot");
return modelAndView;
}
<input th:attr="value=${attr}"/>
<input th:value="${attr}"/>
Thymeleaf对象
Thymeleaf支持直接访问Servlet Web原生资源,HttpServletRequest、HttpServletResponse、HttpSession、ServletContext
#request 获取HttpServletRequest对象
#response 获取HttpServletResponse对象
#session 获取HttpSession对象
#servletContext 获取ServletContext对象
例
@GetMapping("/servlet")
public String servlet(HttpServletRequest request){
request.setAttribute("value","request");
request.getSession().setAttribute("value","session");
request.getServletContext().setAttribute("value","servletContext");
return "test";
}
<!--servlet-->
<p th:text="${#request.getAttribute('value')}"/>
<p th:text="${#session.getAttribute('value')}"/>
<p th:text="${#servletContext.getAttribute('value')}"/>
<p th:text="${#response}"/>
Thymeleaf支持直接访问session,KaTeX parse error: Expected '}', got '#' at position 2: {#̲request.getAttr…{name}
例
@GetMapping("/servlet2")
public ModelAndView servlet2(HttpSession session){
session.setAttribute("name","李四");
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("name","张三");
return modelAndView;
}
<p th:text="${name}"></p>
<p th:text="${#request.getAttribute('name')}"></p>
<p th:text="${session.name}"></p>
<p th:text="${#session.getAttribute('name')}"></p>
Thymeleaf内置对象
- dates 日期格式化
- calendars 日期操作
- numbers 数字格式化
- strings 字符串格式化
- bools boolean
- arrays 数组内置对象
- list List集合内置对象
- sets Set集合内置对象
- maps Map集合内置对象
例
@GetMapping("/utility")
public ModelAndView utility(){
ModelAndView modelAndView=new ModelAndView();
modelAndView.setViewName("test");
modelAndView.addObject("date", new Date());
Calendar calendar=Calendar.getInstance();
calendar.set(2020,1,1);
modelAndView.addObject("calendar",calendar);
modelAndView.addObject("number",0.06);
modelAndView.addObject("string","Spring Boot");
modelAndView.addObject("array",Arrays.asList("张三","李四","王五"));
List<User> list=new ArrayList<>();
list.add(new User(1,"张三"));
list.add(new User(2,"李四"));
modelAndView.addObject("list",list);
Set<User> set=new HashSet<>();
set.add(new User(1,"张三"));
set.add(new User(2,"李四"));
modelAndView.addObject("set",set);
Map<Integer,User> map=new HashMap<>();
map.put(1,new User(1,"张三"));
map.put(2,new User(2,"李四"));
modelAndView.addObject("map",map);
return modelAndView;
}
date格式化:<span th:text="${#dates.format(date,'yyyy-MM-dd')}"></span><br>
当前日期:<span th:text="${#dates.createToday()}"></span><br>
当前时间:<span th:text="${#dates.createNow()}"></span><br>
Calendar格式化:<span th:text="${#calendars.format(calendar,'yyyy-MM-dd')}"></span>
number百分比格式化:<span th:text="${#numbers.formatPercent(number,2,2)}"></span><br>
name是否为空:<span th:text="${#strings.isEmpty(string)}"></span><br>
name长度:<span th:text="${#strings.length(string)}"></span><br>
name拼接:<span th:text="${#strings.concat('good',string)}"></span><br>
boolean是否为true:<span th:text="${#bools.isTrue(boolean)}"></span><br>
arrays的长度:<span th:text="${#arrays.length(array)}"></span><br>
arrays是否包含张三:<span th:text="${#arrays.contains(array,'张三')}"></span><br>
List是否为空:<span th:text="${#lists.isEmpty(list)}"></span><br>
Set是否为空:<span th:text="${#sets.isEmpty(set)}"></span><br>
Set的长度:<span th:text="${#sets.isEmpty(set)}"></span><br>
Map是否为空<span th:text="${#maps.isEmpty(map)}"></span><br>
Map的长度:<span th:text="${#maps.size(map)}"></span>