第5 章Spring Boot 的Web 开发
学习目的与要求
本章首先介绍SpringBoot的Web开发支持,然后介绍Thymeleaf视图模板引擎技术,最
后介绍SpringBoot的Web开发技术(JSON 数据交互、文件的上传与下载、异常统一处理以
及对JSP的支持)。通过本章的学习,读者应该掌握SpringBoot的Web开发技术。
本章主要内容
● Thymeleaf模板引擎
● 使用SpringBoot处理JSON 数据
● SpringBoot中文件的上传与下载
● SpringBoot的异常处理
● SpringBoot对JSP的支持
Web开发是一种基于B/S(即浏览器/服务器)架构的应用软件开发技术,分为前端(用户
接口)和后端(业务逻辑和数据)。前端的可视化及用户交互由浏览器实现,即以浏览器作为客
户端,实现客户与服务器远程的数据交互。SpringBoot的Web开发内容主要包括内嵌Servlet
容器和SpringMVC。
5.1 SpringBoot的Web开发支持
SpringBoot提供了spring-boot-starter-web依赖模块,该依赖模块包含SpringBoot预定
义的Web开发常用依赖包,为Web开发者提供内嵌的Servlet容器(Tomcat)以及Spring
MVC的依赖。如果开发者希望开发SpringBoot的Web应用程序,可以在SpringBoot项目
的pom.xml文件中添加如下依赖配置:
org.springframework.boot
spring-boot-starter-web
SpringBoot将自动关联Web开发的相关依赖,如Tomcat、spring-webmvc等,进而对
Web开发提供支持,并实现相关技术的自动配置。
另外,开发者也可以使用IDEA 集成开发工具快速创建SpringInitializr,在NewProject
对话框中添加SpringBoot的Web依赖。
5.2 Thymeleaf模板引擎
在SpringBoot的Web应用中,建议开发者使用HTML开发动态页面。SpringBoot提
供了许多模板引擎,主要包括FreeMarker、Groovy、Thymeleaf、Velocity和Mustache。因为
Thymeleaf提供了完美的Spring MVC 支持,所以在SpringBoot的Web应用中推荐使用
Thymeleaf作为模板引擎。
第5 章 Spring Boot 的Web 开发
93
Thymeleaf是一个Java类库,是一个XML/XHTML/HTML5的模板引擎,能够处理
HTML、XML、JavaScript以及CSS,可以作为MVC Web应用的View层显示数据。
.5.2.1 Spring Boot 的Thymeleaf 支持
在SpringBoot1.X版本中,spring-boot-starter-thymeleaf依赖包含了spring-boot-starter-web
模块。但是,在Spring5 中,WebFlux 的出现对于Web 应用的解决方案不再唯一,所以
spring-boot-starter-thymeleaf依赖不再包含spring-boot-starter-web模块,需要开发者自己选
择spring-boot-starter-web模块依赖。下面通过一个实例讲解如何创建基于Thymeleaf模板
引擎的SpringBootWeb应用ch5_1。
【例5-1】 创建基于Thymeleaf模板引擎的SpringBootWeb应用ch5_1。
其具体实现步骤如下。
. 创建基于Thymeleaf模板引擎的SpringBootWeb应用ch5_1
图5.1 基于Thymeleaf模板引擎的
SpringBootWeb应用ch5_1
在IDEA 中选择File→New→Project命令,打开
NewProject对话框;在NewProject对话框中选择和输
入相关信息,然后单击Next按钮,打开新的界面;在新的
界面中选择Thymeleaf、Lombok和Spring Web依赖,单
击Create按钮,即可创建ch5_1应用。
. 打开项目目录
打开已经创建的基于Thymeleaf模板引擎的Spring
BootWeb应用ch5_1,如图5.1所示。
Thymeleaf模板默认将JS脚本、CSS样式、图片等静
态文件放置在src/main/resources/static目录下,将视图
页面放在src/main/resources/templates目录下。
. 设置Web应用ch5_1的上下文路径
在ch5_1应用的application.properties文件中配置
如下内容:
server.servlet.context-path=/ch5_1
. 创建控制器类
创建一个名为com.ch.ch5_1.controller的包,并在该包中创建控制器类TestThymeleafController,
具体代码如下:
package com.ch.ch5_1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class TestThymeleafController {
@GetMapping("/")
public String test(){
//根据Thymeleaf 模板,默认返回src/main/resources/templates/index.html
return "index";
}
}
94
. 新建index.html页面
在src/main/resources/templates目录下新建index.html页面,代码如下:
Insert title here
测试Spring Boot 的Thymeleaf 支持
. 运行
首先运行Ch51Application主类,然后访问“http://localhost:8080/ch5_1/”,运行结果如
图5.2所示。
图5.2 例5-1的运行结果
.5.2.2 Thymeleaf 的基础语法
. 引入Thymeleaf
首先将View层页面文件的HTML标签修改如下:
然后在View层页面文件的其他标签中使用th:*动态处理页面,示例代码如下:
其中,${aBook.picture}获得数据对象aBook的picture属性。
. 输出内容
使用th:text和th:utext(不对文本转义,正常输出)将文本内容输出到所在标签的body
中。如果在国际化资源文件messages_en_US.properties中有消息文本“test.myText=
TestInternationalMessage”,那么在页面中可以使用如下两种方式获得
消息文本:
. 基本表达式
1)变量表达式:${…}
变量表达式用于访问容器上下文环境中的变量,示例代码如下:
2)选择变量表达式:*{…}
选择变量表达式计算的是选定的对象(th:object属性绑定的对象),示例代码如下:
第5 章 Spring Boot 的Web 开发
95
name:
surname:
nationality:
3)信息表达式:#{…}
信息表达式一般用于显示页面静态文本,将可能需要根据需求整体变动的静态文本放在
properties文件中以便维护(如国际化),通常与th:text属性一起使用。示例代码如下:
. 引入URL
Thymeleaf模板通过@{…}表达式引入URL,示例代码如下:
去看看
去清华
大学出版社
. 访问WebContext对象中的属性
Thymeleaf模板通过一些专门的表达式从模板的WebContext获取请求参数、请求、会话
和应用程序中的属性,具体如下。
● ${xxx}:返回存储在Thymeleaf模板上下文中的变量xxx或请求request作用域中
的属性xxx。
● ${param.xxx}:返回一个名为xxx的请求参数(可能是多个值)。
● ${session.xxx}:返回一个名为xxx的HttpSession作用域中的属性。
● ${application.xxx}:返回一个名为xxx的全局ServletContext上下文作用域中的
属性。
与EL表达式一样,使用${xxx}获得变量值,使用${对象变量名.属性名}获取JavaBean
属性值。需要注意的是,${}表达式只能在th标签内部有效。
. 运算符
在Thymeleaf模板的表达式中可以使用+、-、*、/、%等各种算术运算符,也可以使用>、
<、<=、>=、==、!=等各种逻辑运算符。示例代码如下:
…
. 条件判断
1)if和unless
只有在th:if条件成立时才显示标签内容;th:unless与th:if相反,只有在条件不成立时
才显示标签内容。示例代码如下:
成功
成功
96
2)switch语句
Thymeleaf模板也支持多路选择switch语句结构,默认属性default可用“*”表示。示例
代码如下:
User is an administrator
User is a teacher
User is a student
. 循环
1)基本循环
Thymeleaf模板使用th:each="obj,iterStat:${objList}"标签进行迭代循环,迭代对象可
以是java.util.List、java.util.Map或数组等。示例代码如下:
2)循环状态的使用
在th:each标签中可以使用循环状态变量,该变量有如下属性。
● index:当前迭代对象的index(从0开始计数)。
● count:当前迭代对象的index(从1开始计数)。
● size:迭代对象的大小。
● current:当前迭代变量。
● even/odd:布尔值,当前循环是否为偶数/奇数(从0开始计数)。
● first:布尔值,当前循环是否为第一个。
● last:布尔值,当前循环是否为最后一个。
使用循环状态变量的示例代码如下:
第5 章 Spring Boot 的Web 开发
97
. 内置对象
在实际Web项目开发中经常传递列表、日期等数据,所以Thymeleaf模板提供了很多内
置对象,可以通过# 直接访问。这些内置对象一般都以s结尾,如dates、lists、numbers、
strings等。Thymeleaf模板通过${#…}表达式访问内置对象,常见的内置对象如下。
● #dates:日期格式化的内置对象,操作的方法是java.util.Date类的方法。
● #calendars:类似于#dates,但操作的方法是java.util.Calendar类的方法。
● #numbers:数字格式化的内置对象。
● #strings:字符串格式化的内置对象,操作的方法参照java.lang.String。
● #objects:参照java.lang.Object。
● #bools:判断boolean类型的内置对象。
● #arrays:数组操作的内置对象。
● #lists:列表操作的内置对象,参照java.util.List。
● #sets:Set操作的内置对象,参照java.util.Set。
● #maps:Map操作的内置对象,参照java.util.Map。
● #aggregates:创建数组或集合的聚合的内置对象。
● #messages:在变量表达式内部获取外部消息的内置对象。
例如,有如下控制器方法:
@GetMapping("/testObject")
public String testObject(Model model) {
//系统时间new Date()
model.addAttribute("nowTime", new Date());
//系统日历对象
model.addAttribute("nowCalendar", Calendar.getInstance());
//创建BigDecimal 对象
BigDecimal money = new BigDecimal(2019.613);
model.addAttribute("myMoney", money);
//字符串
String tsts = "Test strings";
model.addAttribute("str", tsts);
//boolean 类型
boolean b = false;
model.addAttribute("bool", b);
//数组(这里不能使用int 定义数组)
Integer aint[]= {1,2,3,4,5};
model.addAttribute("mya", aint);
//List 列表1
List nameList1 = new ArrayList();
nameList1.add("陈恒1");
nameList1.add("陈恒3");
nameList1.add("陈恒2");
model.addAttribute("myList1", nameList1);
//Set 集合
Set st = new HashSet();
st.add("set1");
98
st.add("set2");
model.addAttribute("mySet", st);
//Map 集合
Map map = new HashMap();
map.put("key1", "value1");
map.put("key2", "value2");
model.addAttribute("myMap", map);
//List 列表2
List nameList2 = new ArrayList();
nameList2.add("陈恒6");
nameList2.add("陈恒5");
nameList2.add("陈恒4");
model.addAttribute("myList2", nameList2);
return "showObject";
}
那么,可以在src/main/resources/templates/showObject.html视图页面文件中使用内置
对象操作数据。showObject.html的代码如下:
Insert title here
格式化控制器传递过来的系统时间nowTime:
创建一个日期对象:
格式化控制器传递过来的系统日历nowCalendar:
格式化控制器传递过来的BigDecimal 对象myMoney:
计算控制器传递过来的字符串str 的长度:
返回对象,当控制器传递过来的BigDecimal 对象myMoney 为空时返回默认值9999:
判断boolean 数据是否为false:
判断数组mya 中是否包含元素5:
排序列表myList1 的数据:
判断集合mySet 中是否包含元素set2:
判断myMap 中是否包含key1 关键字:
第5 章 Spring Boot 的Web 开发
99
将数组mya 中的元素求和:
将数组mya 中的元素求平均:
如果未找到消息,则返回默认消息(如“??msgKey_zh_CN??”):
.5.2.3 Thymeleaf 的常用属性
通过5.2.2节的学习,发现Thymeleaf语法都是通过在HTML页面的标签中添加th:xxx
关键字来实现模板套用,且其属性与HTML 页面标签基本类似。Thymeleaf的常用属性
如下。.
th:action
th:action用于定义后台控制器路径,类似
.th:each
th:each用于集合对象的遍历,功能类似JSTL标签。示例代码如下:
.th:field
th:field用于表单参数的绑定,通常与th:object一起使用。示例代码如下:
.th:href
th:href用于定义超链接,类似标签的href属性。其value形式为@{/logout}。示例
代码如下:
.th:id
th:id用于div的id声明,类似HTML标签中的id属性。示例代码如下:
.th:if
th:if用于条件判断,如果为否,则标签不显示。示例代码如下:
…do something…
扫一扫
视频讲解
100
.th:fragment
th:fragment用于声明定义该属性的div为模板片段,常用于头文件、尾文件的引入,通常
与th:include、th:replace一起使用。
例如,在ch5_1应用的src/main/resources/templates目录下声明模板片段文件footer.
html,代码如下:
Insert title here
主体内容
.清华大学出版社
那么,可以在ch5_1应用的src/main/resources/templates/index.html文件中引入模板片
段,代码如下:
Insert title here
测试Spring Boot 的Thymeleaf 支持
引入主体内容模板片段:
引入版权所有模板片段:
.th:object
th:object用于表单数据对象的绑定,将表单绑定到后台controller的一个JavaBean参
数,通常与th:field一起使用。下面通过一个实例讲解表单提交及数据绑定的实现过程。
【例5-2】 表单提交及数据绑定的实现过程。
其具体实现步骤如下。
1)创建实体类
在Web应用ch5_1的src/main/java目录下创建com.ch.ch5_1.model包,并在该包中创
建实体类LoginBean,代码如下:
package com.ch.ch5_1.model;
import lombok.Data;
@Data
第5 章 Spring Boot 的Web 开发
101
public class LoginBean {
String uname;
String urole;
}
2)创建控制器类
在Web应用ch5_1的com.ch.ch5_1.controller包中创建控制器类LoginController,代码
如下:
package com.ch.ch5_1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.ch.ch5_1.model.LoginBean;
@Controller
public class LoginController {
@GetMapping("/toLogin")
public String toLogin(Model model) {
/*loginBean 与login.html 页面中的th:object="${loginBean}"相同*/
model.addAttribute("loginBean", new LoginBean());
return "login";
}
@PostMapping("/login")
public String greetingSubmit(@ModelAttribute LoginBean loginBean) {
/*@ModelAttribute LoginBean loginBean 接收login.html 页面中的表单数据,并将
loginBean 对象保存到model 中返回给result.html 页面显示。*/
System.out.println("测试提交的数据: " + loginBean.getUname());
return "result";
}
}
3)创建页面表示层
在Web应用ch5_1 的src/main/resources/templates目录下创建页面login.html和
result.html。
login.html页面的代码如下:
Insert title here
Form