视图
页面视图
ModelAndView
是 Spring MVC 中的一个类,用于封装模型数据和视图信息,以便将数据传递给视图模板并渲染页面。它结合了模型数据(Model)和视图信息(View),是 Spring MVC 控制器返回值的一种常见形式。
ModelAndView
的基本用法
ModelAndView
包含两部分:
- 模型(Model):用于存储传递给视图的数据,通常是一个
Map
,键是属性名,值是属性值。 - 视图(View):用于指定视图的名称或视图解析器的逻辑名称。
示例代码
以下是一个简单的控制器方法,使用 ModelAndView
返回视图和模型数据:
java
复制
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HomeController {
@GetMapping("/")
public ModelAndView home() {
// 创建 ModelAndView 对象
ModelAndView modelAndView = new ModelAndView();
// 添加模型数据
modelAndView.addObject("message", "Hello, Spring MVC!");
modelAndView.addObject("timestamp", new java.util.Date());
// 设置视图名称
modelAndView.setViewName("index");
return modelAndView;
}
}
在这个例子中:
modelAndView.addObject("message", "Hello, Spring MVC!");
将一个名为message
的属性添加到模型中,值为"Hello, Spring MVC!"
。modelAndView.setViewName("index");
指定了视图的名称为index
,Spring MVC 会根据视图解析器的配置找到对应的视图文件(例如index.html
或index.jsp
)。
- 视图解析器
为了使 ModelAndView
能够正确解析视图名称,你需要配置一个视图解析器。Spring Boot 默认使用 Thymeleaf 作为视图模板引擎,但你也可以配置其他视图解析器,如 JSP 或 Freemarker。
默认的 Thymeleaf 视图解析器
如果你使用的是 Thymeleaf,默认情况下,视图文件应该放在 src/main/resources/templates
目录下。例如,index.html
文件的内容可能如下:
HTML
预览
复制
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1 th:text="${message}"></h1>
<p>当前时间:<span th:text="${timestamp}"></span></p>
</body>
</html>
json视图
- 与之前的一样
。。。
Thymeleaf技术
Thymeleaf 是一个表现层的模板引擎, 一般被使用在 Web 环境中,它可以处理 HTML, XML、 JS 等文档,简单来说,它可以将 JSP 作为 Java Web 应用的表现层,有能力展示与处理数据。Thyme leaf 可以让表现层的界面节点与程序逻辑被共享,这样的设计, 可以让界面设计人员、业务人员与技术人员都参与到项目开发
中。这样,同一个模板文件,既可以使用浏览器直接打开,也可以放到服务器中用来显示数据,并且样式之间基本上不会存在差异,因此界面设计人员与程序设计人员可以使用同一个模板文件,来查看静态与动态数据的效果。
Thymeleaf 作为视图展示模型数据,用于和用户交互操作。JSP 的代替技术。比较适合做管理系统,是一种易于学习,掌握的。我们通过几个示例掌握 Thymeleaf 基础应用
Thymeleaf 是一种现代的模板引擎,用于在 Java 应用程序中生成 HTML、XML、JS、CSS 等内容。它支持服务器端模板渲染,同时也可以在浏览器中直接预览模板。以下是一些常见的 Thymeleaf 用法:
变量表达式
语法:
th:text="${...}"
或th:object="${...}"
。用途:从模型中获取变量值并显示到页面上。
示例:
HTML
预览
复制
<p th:text="${message}"></p>
package com.example.demo1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @Author: yanyu666_508200729@qq.com
* @Date 2025/6/4 0:03
* @description: Thymeleaf表达式
*/
@Controller
public class Demo1 {
@GetMapping("/demo1")
public String getDemo1(Model model){
model.addAttribute("name","yanyu");
model.addAttribute("addr","东莞");
return "demo1";
}
}
Thymeleaf的命名空间
- 注意
在使用 Thymeleaf 时,xmlns:th="http://www.thymeleaf.org"
是一个非常重要的声明,它用于定义 Thymeleaf 的命名空间。这个声明是必要的,因为它告诉浏览器和模板引擎如何解析和处理模板中的 Thymeleaf 属性。
是否可以省略?
不可以省略。如果不声明 xmlns:th
,浏览器和模板引擎将无法识别 Thymeleaf 的属性(如 th:text
、th:each
等),从而导致模板无法正确解析和渲染。
在上面的案例中,虽然没有报错,最好也不要去省略
示例
以下是一个完整的 HTML 模板示例,展示了如何正确声明 xmlns:th
:
HTML
预览
复制
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf Example</title>
</head>
<body>
<h1 th:text="${message}">Default Message</h1>
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">Name</th>
<th th:text="#{msgs.headers.price}">Price</th>
</tr>
</thead>
<tbody>
<tr th:each="prod: ${allProducts}">
<td th:text="${prod.name}">Oranges</td>
<td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
</tr>
</tbody>
</table>
</body>
</html>
解释
xmlns:th="http://www.thymeleaf.org"
:声明 Thymeleaf 的命名空间。th:text="${message}"
:Thymeleaf 属性,用于动态显示变量message
的值。th:each="prod: ${allProducts}"
:Thymeleaf 属性,用于遍历集合allProducts
。
如果省略会怎样?
如果不声明 xmlns:th
,浏览器会将 th:text
、th:each
等属性视为普通的 HTML 属性,而不是 Thymeleaf 的动态属性。这将导致模板无法正确解析和渲染,例如:
HTML
预览
复制
<!DOCTYPE html>
<html>
<head>
<title>Thymeleaf Example</title>
</head>
<body>
<h1 th:text="${message}">Default Message</h1>
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">Name</th>
<th th:text="#{msgs.headers.price}">Price</th>
</tr>
</thead>
<tbody>
<tr th:each="prod: ${allProducts}">
<td th:text="${prod.name}">Oranges</td>
<td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
</tr>
</tbody>
</table>
</body>
</html>
在这种情况下,页面上会直接显示 th:text="${message}"
等属性,而不是动态内容。
总结
xmlns:th="http://www.thymeleaf.org"
是必须的,它确保 Thymeleaf 属性能够被正确解析和处理。省略这个声明会导致模板无法正确渲染动态内容。
链接表达式
语法:
th:href="@{...}"
或th:src="@{...}"
。用途:生成动态链接或资源路径。
示例:
HTML
预览
复制
<a th:href="@{http://www.baidu.com}">连接到百度</a> <br/> <img th:src="@{/images/logo.png}" alt="Logo">
<!DOCTYPE html>
<html lang="en" xmlns:text="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>读取表达式</title>
</head>
<body>
<div th:text="${name}"></div>
<div th:text="${addr}"></div>
<!--连接到网址-->
<a th:href="@{http://www.baidu.com}">百度</a>
<br>
<a th:href="@{demo2.html}">连接本地资源(无参数)</a>
</body>
</html>
- 连接互联网资源
- 连接本地资源
无参数
package com.example.demo1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @Author: yanyu666_508200729@qq.com
* @Date 2025/6/4 0:03
* @description: Thymeleaf表达式
*/
@Controller
public class Demo1 {
@GetMapping("/demo1")
public String getDemo1(Model model){
model.addAttribute("name","yanyu");
model.addAttribute("addr","东莞");
return "demo1";
}
@GetMapping("/link")
public String getDemo2(Model model,String name,String age){
model.addAttribute("name",name);
model.addAttribute("age",age);
return "demo2";
}
}
有参数
<!DOCTYPE html>
<html lang="en" xmlns:text="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>读取表达式</title>
</head>
<body>
<div th:text="${name}"></div>
<div th:text="${addr}"></div>
<!--连接到网址-->
<a th:href="@{http://www.baidu.com}">百度</a>
<br>
<!--不传递参数-->
<a th:href="@{/link}">连接本地资源(无参数)</a>
<!--传递参数 参数名字 与 对应的控制器一致-->
<a th:href="@{/link(name=烟雨,age=20)}">连接本地资源(有参数)</a>
</body>
</html>
package com.example.demo1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @Author: yanyu666_508200729@qq.com
* @Date 2025/6/4 0:03
* @description: Thymeleaf表达式
*/
@Controller
public class Demo1 {
@GetMapping("/demo1")
public String getDemo1(Model model){
model.addAttribute("name","yanyu");
model.addAttribute("addr","东莞");
return "demo1";
}
@GetMapping("/link")
public String getDemo2(Model model,String name,String age){
model.addAttribute("name",name);
model.addAttribute("age",age);
return "demo2";
}
}
条件表达式
if/unless:根据条件判断是否渲染某个元素。
语法:
th:if="${...}"
或th:unless="${...}"
。示例:
HTML
预览
复制
来自于 模型的 对象,进行判断,不为空,才会执行
<div th:if="${user != null}"> <p>Welcome, <span th:text="${user.name}"></span>!</p> </div> <div th:unless="${user != null}"> <p>Please log in.</p> </div>
th:each
th:each
是 Thymeleaf 中用于循环遍历集合(如列表、数组等)的表达式。它允许你对集合中的每个元素进行迭代,并在每次迭代中生成相应的 HTML 元素。以下是对 th:each
的详细介绍,包括其语法、用法和一些高级特性。
基本语法
HTML
预览
复制
<div th:each="variable : ${collection}">
<!-- 循环体 -->
</div>
variable
:每次迭代时,当前元素的变量名。${collection}
:需要遍历的集合对象(如List
、Set
、数组等)。
基本用法
假设你有一个用户列表 List<User>
,每个用户有 name
和 email
属性,你可以使用 th:each
来遍历并显示每个用户的信息。
示例代码
HTML
预览
复制
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.name}"></td>
<td th:text="${user.email}"></td>
</tr>
</tbody>
</table>
输出结果
如果 users
集合中有以下数据:
java
复制
[
{name="Alice", email="alice@example.com"},
{name="Bob", email="bob@example.com"}
]
生成的 HTML 将是:
HTML
预览
复制
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>alice@example.com</td>
</tr>
<tr>
<td>Bob</td>
<td>bob@example.com</td>
</tr>
</tbody>
</table>
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<a href="/demo1">表达式</a>
<br>
<a href="/demo2">遍历集合</a>
</body>
</html>
package com.example.demo1.vo;
import java.util.Objects;
/**
* @Author: yanyu666_508200729@qq.com
* @Date 2025/6/4 0:55
* @description:
*/
public class User {
String name;
String age;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name) && Objects.equals(age, user.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public User(String name, String age) {
this.name = name;
this.age = age;
}
public User() {
}
}
package com.example.demo1.controller;
import com.example.demo1.vo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
/**
* @Author: yanyu666_508200729@qq.com
* @Date 2025/6/4 0:28
* @description:
*/
@Controller
public class Demo2 {
@GetMapping("/demo2")
public String getDemo2(Model model){
/*Arrays.asList 是 Java 中的一个非常实用的方法,用于将数组快速转换
为一个固定大小的 List。它属于 java.util.Arrays 类,通常用于创建一个
简单的列表,而无需显式地初始化一个 ArrayList 或其他类型的 List。
* */
List<User> users = Arrays.asList(
new User("yanyu1","20"),
new User("yanyu2","22")
);
model.addAttribute("users",users);
// 将 集合添加到模型
return "user";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<table border="1px">
<tr>
<td>姓名</td>
<td>年龄</td>
</tr>
<tr th:each="user:${users}">
<!-- 以读取变量的形式读取集合
拿到实体类的对象后,读取实体类的属性
-->
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
</tr>
</table>
</body>
</html>