文章目录
- 一、Spring Boot框架概述
- 二、Spring Boot基本配置
- 三、Spring Boot项目访问静态资源
- 四、Spring Boot整合Thymeleaf
- 五、Spring Boot集成Bootstrap
- 六、Thymeleaf访问模型里的数据
一、Spring Boot框架概述
- Spring Boot官网:https://spring.io/projects/spring-boot
- 当前Spring Boot GA (General Availability)版是2.7.0,当然有了Spring Boot 3.0.0快照版
(一)由Spring到Spring Boot
- 关于Spring框架,可以参看本博《玩一玩Spring框架》
- Spring Framework在成为Java生态的“事实标准”之后,虽然很长时间内热度不减,但是后来没有再推出过任何激动人心的新功能,反而是开发者在处理日益增长的业务需求和管理Spring的配置、依赖和应用部署等方面不断面临新的挑战。特别是RESTful、微服务等概念的流行,以及互联网快速迭代的开发模式的兴起,使开发者们愈发希望可以拥有更敏捷、更高效的开发框架,同时开发者对服务器(或容器)的要求也更加倾向于轻量级。
- 在这种需求的驱动之下,开发者
Mike Youngstrom
于2012
年在Spring官方的GitHub上提出了一个ID为SPR-9888
的需求,他的需求代表了当时Spring Framework使用者的心声,他的需求如下:“如果开发者完全遵循Spring规范构建程序,则这样的程序与原生的Servlet规范差别是非常大的,同时这也让此类程序对Servlet容器的要求大大降低。因此,如果Spring Framework能够提供一个无需直接与Servlet容器交互的框架,那么将会大大地简化开发者的工作”。 - 在此需求被提交给Spring官方一年之后,Spring Framework的开发者
Phil Webb
于2013
年8
月在GitHub上,代表官方正式对该需求做出了回复“我们将会创建一个名为Spring Boot的新项目来解决这些问题”,同时还给出了一个介绍Spring Boot项目的博客,这是Spring Boot第一次出现在大众视野中。 - 早期版本的Spring专注于
XML配置
,开发一个程序需要配置各种XML配置文件
。为了简化开发,在Spring 2.x版本开始引入少量的注解
,由于支持的注解不是很多且功能尚不完善,所以只能辅助使用。- 随着实际生产中敏捷开发的需要,以及Spring注解的大量出现和功能改进,到了Spring 4.x版本基本可以脱离XML配置文件进行项目开发,多数开发者也逐渐感受到了基于注解
开发的便利,因此,在Spring中使用注解开发逐渐占据了主流地位。与此同时,Pivotal
团队在原有Spring框架的基础上通过注解的方式进一步简化了Spring框架的使用,并基于Spring框架开发了全新的Spring Boot框架。 - 我们需要明确SpringBoot并非要取代Spring Framework,它与传统的Spring Framework分别是事物的一体两面。Spring Boot的真正目标是帮助开发者减少传统Spring应用所需的配置文件和复杂的依赖关系,进而加快应用迭代的速度。
- 回顾《利用SSM框架实现用户登录功能》开发Spring应用的方法,开发者不仅要正确地引用Spring Framework的模块及版本,还要集成第三方依赖的兼容性,否则会导致应用无法启动或者发生严重的错误。除了依赖问题,传统Spring应用的另外一个烦恼是——大量烦琐的配置文件,虽然从JDK 1.5之后注解(Annotation)式编程被广泛采用,但是在实际项目中,没有配置文件的Spring项目是非常罕见的。因而在Spring Framework发展了十年以后,框架本身的复杂度加上各种业务逻辑交杂在一起,开发者不得不花费大量精力和时间去管理这些配置文件,想要对应用进行一次版本升级更是难上加难,需要大量的回归测试和兼容性测试。在这样的情形下,如果开发团队中程序员对Spring Framework的掌握程度参差不齐,那么维持一个简洁优雅的项目会变得非常困难,并且对新手而言,Spring Framework的学习过程也是相当曲折的。
- 基于此,Spring Boot为了帮助开发者更加快速地开发各式应用,其设计思想是尽量使用最佳实践和默认配置来自动化装配Spring应用中的各类Bean,从而避免大量的重复性代码和配置文件。 更通俗地讲,有很多业界专家知道如何能尽量发挥Spring Framework的优点,同时规避其短处,这些专家的经验被称为最佳实践。对新手而言,能够直接利用这些最佳实践不仅可以避免犯下各种低级错误,还可以节省开发成本。
- 因此,Spring官方开发者直接将各种最佳实践全部打包进Spring Boot,它以一种自动配置的形式注入应用中,并针对各种依赖的版本管理,设计了全新的
Spring Boot Starter
框架,各个厂商可以基于Spring Boot Starter
规范开发自己的Starter
组件,将新的功能模块集成到Spring Boot。此外,Spring Boot还提供了内置的轻量级应用服务器,通过以上创新设计,基于Spring应用的绝大部分基础问题都已经被Spring Boot解决了。 - 这些全新的特性,让Spring Boot一经推出就立即风靡整个Spring生态圈,也让沉寂许久的Spring开发生态再次喧嚣起来。各种主流开源软件也开始提供自己的Starter,方便开发者适配Spring Boot,更多架构师在设计系统之初就将Spring Boot作为首选,同时还开始将旧项目逐步迁移到Spring Boot上。一时间,Spring又回到了舞台的中央。
(二)Spring Boot的设计理念
- Spring Boot的设计者在设计之初就一直奉行一个原则:
约定大于配置(Convention OverConfiguration)
,但作为Spring Boot的用户,应当如何理解这项原则?究其根源,Spring Boot的开发者在研究了大量Spring应用之后,得出一个惊人的结论:大部分Spring项目的配置都是非常相似的,利用这种相似性,Spring Boot的设计者从中总结出规律并将其定义为Spring应用的默认配置,将其固化在Spring Boot框架中,再利用自动配置(Auto Configuration) 技术将默认配置注入应用。 - 这种设计理念,对于刚开始接触Spring Boot的开发者会略有不适,更有甚者,在第一次运行Spring Boot项目时,完全无法理解其工作原理。可是一旦明白了“约定大于配置”的设计理念,就会理解其工作原理。
- 以
MyBatis
为例,如果某个Spring Boot
应用采用MyBatis
框架作为数据访问层,那么在项目启动阶段,Spring Boot
框架一旦扫描到该项目的classpath中包含MyBatis
相关的类,就会自动将MyBatis
相关的配置加载到Spring
容器中,进而应用可以使用MyBatis
来操作数据库。作为对比,在传统的Spring项目中,无论是使用XML还是以Bean的形式定义,MyBatis
都必须逐一进行显式配置,否则该项目是无法使用MyBatis
的(准确来说是无法启动的)。 - 再举一个简单例子,如果我们要在传统的
MyBatis
配置中配置数据库连接池,那么我们必须在xml
文件中显式定义连接池,而Spring Boot
应用会为MyBatis
自动配置一个HikariCP
连接池(Hikari
是一款非常强大,高效,并且号称“史上最快连接池”。由于其性能方面比较好,并且在Spring Boot 2.0之后,采用的默认数据库连接池就是Hikari
,在引用parents
后不用专门再添加依赖。性能方面的比较:hikariCP>druid>tomcat-jdbc>dbcp>c3p0
。hikariCP
的高性能得益于最大限度的避免锁竞争。) - 尽管Spring Boot大大减少了项目的配置工作,但作为开发者不要轻易被表象所迷惑,了解Spring Boot背后的工作原理才是正确的学习方向。
(三)Spring Boot的核心功能
1、易于使用的依赖管理Starter
(1)Starter概述
- 在学习Spring Boot使用细节之前,先简单回顾一下Java项目构建方式的历史变迁。最早的Java项目在编译和运行期都需要显式地指定classpath,并以这种方式来管理项目所依赖的jar包和class文件。当时主流的构建工具是
ant
,但ant只能执行编译和构建相关的任务,没有专门管理项目依赖的工具,这也是后来人们发明依赖管理工具Maven
和Gradle
的原因(本讲案例采用Maven3.6+
)。Maven出现之后,创建Java项目的第一步就是利用Maven Archetype
插件创建项目。Spring Boot在Maven Archetype
基础之上更进一步,通过Spring Initializr
就可以很方便地创建出一个Spring Boot项目。 - 要创建Spring Boot项目,需要先了解
Spring Boot Starter
,Starter
提供了一种简单易用的解决方案,帮助Spring Boot新手克服各种主流软件集成时的版本兼容问题。 Starter
可以让开发者更方便、快捷地使用某种技术,无需花费大量精力管理依赖关系和版本冲突问题,因为在Starter
中,所有依赖项已经被预先定义在pom.xml
文件中,开发者只需引用Starter
,该技术所需的依赖会自动添加到项目中。
(2)Starter引入演示
- 在项目中要使用Redis,开发者只需引入一个相应的Starter依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.0</version>
</dependency>
- 添加上述
Starter
后,项目引入了哪些依赖
- 由上图可见Redis的Starter主要定义了两个直接依赖
spring-data-redis和lettuce-core
,spring-data-redis
是Spring对Redis操作的封装,lettuce
是Redis客户端的Java实现(取代最初的Jedis
)。通过这样的方式,所有与Redis相关的lib都会被自动添加到项目中,开发者再也不需要一个个单独地引入依赖关系,执行引入一个Starter即可。当然Starter要真正在运行期发挥功效,是需要使用自动配置技术的。Starter还会管理后续的版本升级,如无特殊情况,只需升级Starter的版本便可获得所有依赖组件的升级效果。 - 为了更好地管理Starter依赖项,建议读者在Spring Boot项目的pom.xml文件中指定继承Spring Boot parent,Spring Boot parent的pom.xml文件中指定了经过兼容测试的Starter组件版本。
(3)Spring Boot项目结构
- 除依赖管理外,一个符合Spring Boot标准的项目要遵循某些约定(比如配置文件的位置和文件名),典型的Spring Boot项目结构如下图所示。
- 项目根目录下的pom.xml文件定义了该项目的依赖和主体结构,
DemoApplication
是该项目的运行启动类,application.properties
是项目的默认配置文件。 - 在实际项目中,我们很少会采用人工的方式创建项目或引入依赖项,大多是通过
Spring Initializr
创建新项目。
(4)Spring Boot Starter的特性
- 一个针对市面上成熟的规范和开源软件的小型pom项目
- 一组可以被复用的依赖的最佳实践和默认配置
- 一种全新的Spring应用开发和依赖管理的方式
(5)Spring Boot允许自定义Starter
- Spring Boot官方提供了很多主流的Starter,官方约定的命名方式是
spring-boot-starter-*
。Spring Boot允许自定义Starter,用户自定义的Starter的命名方式是thirdpartyproject-spring-boot-starter
(将公司或组织的名称放到前面),所有官方提供的Starter都可以通过Spring官方文档查询获得。
2、约定大于配置的Auto Configuration
3、优雅灵活的配置管理Properties
4、简洁明了的管理工具Acuator
5、方便快捷的内置容器Embedded Container
(四)Spring Boot的应用场景
- Spring Boot框架本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用,并且在开发过程中大量使用“
约定优先配置
”(Convention over Configuration)的思想来摆脱Spring框架中各种复杂的手动配置,同时衍生出了Java Config(取代传统XML配置文件的Java配置类)这种优秀的配置方式。也就是说,Spring Boot并不是替代Spring框架的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具,同时Spring Boot还集成了大量常用的第三方库配置(例如Jackson、JDBC、Redis、Mail等)。使用Spring Boot开发程序时,几乎是开箱即用(out-of-the-box),大部分的Spring Boot应用都只需少量的配置,这一特性更能促使开发者专注于业务逻辑的实现。 - 随着近几年微服务开发的需求和火爆,怎样快速、简便地构建一个准生产环境的Spring应用也是摆在开发者面前的一个难题,而Spring Boot框架的出现恰好完美地解决了这些问题,同时内部还简化了许多常用的第三方库配置,使得微服务开发更加便利。
二、Spring Boot基本配置
(一)创建Spring Boot项目
- 利用
Spring Initializr
创建Spring Boot
项目
- 配置项目基本信息
- 添加相关依赖
- 设置项目名称与保存位置
- 单击【Finish】按钮,完成项目初始化
1、项目入口类 - SpringBootDemoApplication
- 包含一个主方法作为入口类的入口方法
- 利用SpringApplication类的静态方法
run()
启动入口类实例,可以接收命令行参数
2、了解核心注解 - @SpringBootApplication
- @SpringBootApplication是Spring Boot的核心注解,是一个组合注解。
- 查看@SpringBootApplication的源代码
3、设置exclude属性值,关闭特定的自动配置
-
关闭数据源自动配置
-
查看数据源自动配置类 - DataSourceAutoConfiguration
(二)添加控制器与路由函数
- 直接在入口类上面添加
@Controller
注解,然后定义路由函数index()
(三)启动项目,查看结果
-
启动项目
-
访问
http://localhost:8080
-
添加路由函数
welcome()
,通过model
参数向前端模板页面传递数据
-
在
templates
里创建welcome.html
,跟路由函数welcome()
里的逻辑视图名welcome
相对应
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>Welcome</title>
<head>
<body>
<h3><span th:text="${message}">亲爱的朋友,欢迎访问Spring Boot世界~</span></h3>
</body>
</html>
- 说明:
<span>
元素的内容是静态数据,客户端打开页面看到的数据
- 启动项目,模板页面利用
th:text="${message}
看到后端控制器通过model
传递过来的数据
(四)定制与关闭启动标语
1、创建标语文件
- 在
resources
目录下创建banner.txt
文件(如果是其它文件名,将会被系统忽略)
2、生成艺术字符
- 通过http://patorjk.com/software/taag网站生成字符
3、更新标语文件
- 将网站生成的艺术字符复制到
banner.txt
文件里
4、启动项目,查看结果
- 你会看到自己的大名以及单位
5、关闭启动标语
- 修改入口程序代码,关闭标语功能
- 启动应用,查看效果
- 大家可以看到,启动标语消失无踪了
- 注释掉设置标语模式语句,恢复启动标语
(五)配置应用属性文件
1、修改服务器的端口号
- 在
application.properties
文件里设置服务器端口号为8888
2、启动应用,查看控制台输出信息
- 可以看到,Tomcat服务器初始化的端口变成了
8888
3、启动浏览器,访问资源
- 访问
http://localhost:8888/welcome
- 在
application.properties
文件里注释掉修改服务器端口号的语句,于是服务器端口号恢复成默认的8080
。
- 启动浏览器,访问
http://localhost:8080
4、采用yaml格式的应用属性文件
- 将
application.properties
重命名application.yaml
- 配置属性的写法有点不同,是一种层次结构
- 注意:属性冒号后面必须有空格与属性值分开
(六)允许使用XML配置Spring
1、创建用户实体类
- 在
net.huawei.boot.bean
包里创建User
类
package net.huawei.boot.bean;
import java.util.Date;
/**
* 功能:用户实体类
* 作者:华卫
* 日期:2022年06月08日
*/
public class User {
private int id;
private String username;
private String password;
private String telephone;
private Date registerTime;
private int popedom;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public Date getRegisterTime() {
return registerTime;
}
public void setRegisterTime(Date registerTime) {
this.registerTime = registerTime;
}
public int getPopedom() {
return popedom;
}
public void setPopedom(int popedom) {
this.popedom = popedom;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", telephone='" + telephone + '\'' +
", registerTime=" + registerTime +
", popedom=" + popedom +
'}';
}
}
2、创建Spring配置文件
- 在
resources
目录里创建spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="sdf" class="java.text.SimpleDateFormat">
<constructor-arg value="yyyy-MM-dd hh:mm:ss"/>
</bean>
<bean id="date" factory-bean="sdf" factory-method="parse">
<constructor-arg value="2021-12-25 09:30:30"/>
</bean>
<bean id="user" class="net.huawei.boot.bean.User">
<property name="id" value="2022001"/>
<property name="username" value="Mike"/>
<property name="password" value="903213"/>
<property name="telephone" value="18934563800"/>
<property name="registerTime" ref="date"/>
<property name="popedom" value="1" />
</bean>
</beans>
3、入口类导入Spring配置文件
- 添加注解
ImportResource("")
4、使用Spring配置文件里创建的Bean
- 自动装配用户Bean
- 在路由函数
index()
里使用用户Bean
5、启动应用,查看结果
- 访问
http://localhost:8080
- 课堂练习:在
welcome.html
页面以表格形式显示用户信息
编号 | 姓名 | 密码 | 手机 | 注册时间 | 权限 |
---|---|---|---|---|---|
2022001 | Mike | 903213 | 18934563800 | 2021-12-25 09:30:30 | 1 |
- 其实,也可以创建
Spring MVC
配置类,在里面定义内部资源视图解析器。
三、Spring Boot项目访问静态资源
- 静态资源(css、images、scripts)都放在
resources\static
目录里。下面以图片为例说明静态资源的访问。
(一)准备图片资源
- 在
static
里创建images
目录,拷贝一张图片 -bear.png
(二)在入口类里访问图片资源
- 修改路由函数
index()
,访问图片资源
- Spring Boot静态资源目录的自动配置在哪里可以查看呢?
- 查看
WebProperties
类
- 由此可见,访问静态资源
/static/images/bear.png
,在Java代码里只需要写虚拟路径images/bear.png
。
(三)启动应用,查看结果
- 访问
http://localhost:8080
四、Spring Boot整合Thymeleaf
(一)Spring Boot支持的视图技术
- Spring Boot框架为
简化
项目的整体开发,对一些常用的视图技术实现了整合支持,并主要推荐整合模板引擎技术来实现前端页面的动态化
内容。 - Spring Boot可整合的模板引擎技术
- FreeMarker
- Groovy
- Thymeleaf
- Mustache
……
(二)Thymeleaf基本语法
- 相关语法 ,请学习《thymeleaf_3.0.5_中文参考手册.pdf》 提取码:fqpu
1、Thymeleaf常用标签
th:标签 | 说明 |
---|---|
th:insert |
页面片段包含(类似JSP中的include标签) |
th:replace |
页面片段包含(类似JSP中的include标签) |
th:each |
元素遍历(类似JSP中的c:forEach标签) |
th:if |
条件判断,如果为真 |
th:unless |
条件判断,如果为假 |
th:switch |
条件判断,进行选择性匹配 |
th:case |
条件判断,进行选择性匹配 |
th:object |
变量声明 |
th:with |
变量声明 |
th:attr |
通用属性修改 |
th:attrprepend |
通用属性修改,将计算结果追加前缀到现有属性值 |
th:attrappend |
通用属性修改,将计算结果追加后缀到现有属性值 |
th:value |
属性值修改,指定标签属性值 |
th:href |
用于设定链接地址 |
th:src |
用于设定链接地址 |
th:text |
用于指定标签显示的文本内容 |
th:utext |
用于指定标签显示的文本内容,对特殊标签不转义 |
th:fragment |
声明片段 |
th:remove |
移除片段 |
2、Thymeleaf主要语法
说明 | 表达式语法 | 作用 |
---|---|---|
变量表达式 | ${...} |
获取上下文中的变量值 |
选择变量表达式 | *{...} |
用于从被选定对象获取属性值 |
消息表达式 | #{...} |
用于Thymeleaf模板页面国际化内容的动态替换和展示 |
链接URL表达式 | @{...} |
用于页面跳转或者资源的引入 |
片段表达式 | ~{...} |
用来标记一个片段模板,并根据需要移动或传递给其他模板 |
3、Thymeleaf内置对象
#ctx
:上下文对象#vars
:上下文变量#locale
:上下文区域设置#request
:(仅限Web Context)HttpServletRequest对象#response
:(仅限Web Context)HttpServletResponse对象#session
:(仅限Web Context)HttpSession对象#servletContext
:(仅限Web Context)ServletContext对象
4、Thymeleaf模板基本配置
- 在Spring Boot项目中使用Thymeleaf模板,必须保证引入Thymeleaf依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 在全局配置文件中配置Thymeleaf模板的一些参数。如设置模板缓存、模板编码、模板样式、指定模板页面存放路径、指定模板页面名称的后缀
spring.thymeleaf.cache = true
spring.thymeleaf.encoding = UTF-8
spring.thymeleaf.mode = HTML5
spring.thymeleaf.prefix = classpath:/templates/
spring.thymeleaf.suffix = .html
- 关于Thymeleaf,可以参看博主两年前编写的《Thymeleaf模板引擎入门》
- 关于Bootstrap,可以参看博主两年前编写的《前端学习笔记:Bootstrap框架入门》
(三)实现简单登录页面
- Spring Boot先整合Thymeleaf,后面我们再整合Bootstrap
1、查看Thymeleaf起步依赖
2、在应用属性文件里配置Thymeleaf属性
- 我们可以根据实际需要修改Thymeleaf属性默认值
spring:
thymeleaf: # 配置百里香叶模板
cache: false # 默认值是true,开发阶段设置为false
encoding: utf-8 # 避免中文乱码
mode: HTML5 # 可以使用HTML4.0.1
prefix: classpath:/templates/ # 模板位置是可以修改
suffix: .html # 扩展名是可以修改
Thymeleaf
页面缓存设置,默认为true
,开发中方便调试应设置为false
,上线稳定后应保持默认true
。
3、创建登录控制器
- 在
net.huawei.boot.controller
包里创建LoginController
类,用于前端模板页面动态数据替换效果的测试
package net.huawei.boot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Calendar;
/**
* 功能:登录控制器
* 作者:华卫
* 日期:2022年06月10日
*/
@Controller
public class LoginController {
@GetMapping("/toLogin")
public String toLogin(Model model) {
// 通过model向前端模板页面传递数据
model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));
return "login"; // 逻辑视图名
}
}
4、创建模板页面,获取控制器传来的动态数据
- 在
templates
目录下创建模板页面login.html
- 在
<span>
标签中通过th:text
引入了后台动态传递过来的当前年份currentYear
。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<span th:text="${currentYear}">今年</span> -
<span th:text="${currentYear} + 1">明年</span>
</body>
</html>
- 静态访问模板页面
- 将显示默认值,而不会显示后台传来的动态数据
5、启动项目,查看结果
-
启动项目
-
在浏览器里访问
http://localhost:8080/toLogin
课堂练习:在模板页面显示用户实体信息
- 在登录控制器
toLogin()
方法里,创建用户对象,作为属性添加到模型里
- 修改模板页面
login.html
,提取控制器传递过来的用户实体
- 启动应用, 访问
http://localhost:8080/toLogin
- 修改登录页面,改变用户信息显示方式
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<span th:text="${currentYear}">今年</span> -
<span th:text="${currentYear} + 1">明年</span>
<hr>
编号:<span th:text="${user.id}"></span><br>
用户名:<span th:text="${user.username}"></span><br>
密码:<span th:text="${user.password}"></span><br>
手机:<span th:text="${user.telephone}"></span><br>
注册时间:<span th:text="${#calendars.format(user.registerTime)}"></span><br>
权限:<span th:text="${user.popedom}"></span>
</body>
</html>
- 启动应用,访问
http://localhost:8080/toLogin
五、Spring Boot集成Bootstrap
(一)Bootstrap官网
- 网址:https://getbootstrap.com/
- 目前Bootstrap版本 - V5.2
(二)集成Bootstrap-5.2.0
1、引用在线文档的方式
- 在模板文件中直接引用以下文件
<!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">
<title>用户登录</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>
<span th:text="${currentYear}">今年</span> -
<span th:text="${currentYear} + 1">明年</span>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
</body>
</html>
2、下载Bootstrap并引用的方式
- 下载网址:https://getbootstrap.com/docs/5.2/getting-started/download/
- 单击【Download】按钮
- 解压缩到当前目录
- 重命名
- 将
bootstrap-5.2.0
目录拷贝到项目的static
目录里
(三)添加jQuery到项目
- 在
static
里创建scripts
目录,拷贝jquery-3.5.1.min.js
到该目录
(四)编写登录页面
1、集成Bootstrap和jQuery
<!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">
<title>用户登录</title>
<link th:href="@{/bootstrap-5.2.0/css/bootstrap.css}" rel="stylesheet">
<javascript th:src="@{/bootstrap-5.2.0/js/bootstrap.bundle.js}"></javascript>
<javascript th:src="@{/scripts/jquery-3.5.1.min.js}"></javascript>
</head>
<body>
<span th:text="${currentYear}">今年</span> -
<span th:text="${currentYear} + 1">明年</span>
</body>
</html>
2、编写登录页面
- 登录页面
login.html
<!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">
<title>用户登录</title>
<link th:href="@{/bootstrap-5.2.0/css/bootstrap.css}" rel="stylesheet">
<javascript th:src="@{/bootstrap-5.2.0/js/bootstrap.bundle.js}"></javascript>
<javascript th:src="@{/scripts/jquery-3.5.1.min.js}"></javascript>
</head>
<body>
<div class="col-6 m-auto" style="margin-top:30px!important;">
<div class="text-center">
<span th:text="${currentYear}">今年</span> -
<span th:text="${currentYear} + 1">明年</span>
</div>
<div class="border border-info bg-light p-2" style="border-radius: 5px">
<form action="/login" method="post">
<h3 class="text-center">用户登录</h3>
<div class="mt-1">
<input type="text" id="username" name="username" class="form-control" placeholder="输入用户名" autofocus>
</div>
<div class="mt-1">
<input type="password" id="password" name="password" class="form-control" placeholder="输入密码">
</div>
<div class="checkbox text-center" style="height: 50px; position: relative">
<label style="position: absolute; top: 20%; bottom: 20%; margin-left: -10%">
<input class="form-check-input text-center" type="checkbox"> 记住我
</label>
</div>
<div class="d-grid">
<button class="btn btn-primary btn-block" id="login" type="submit">登录</button>
</div>
</form>
</div>
</div>
</body>
</html>
<div class="col-6 m-auto" style="margin-top:30px!important;">
分区占窗口一半宽度(水平方向按12个单位平分)、水平居中、顶边距30个像素<div class="border border-info bg-light p-2" style="border-radius: 5px">
设置边框(边框色、背景、内边距、圆角)<div class="mt-1">
设置上外边距为1个单位<h3 class="text-center">用户登录</h3>
设置文本居中显示<div class="d-grid">
,如果不设置,按钮就不会填满整行
3、启动项目,查看结果
- 访问
http://localhost:8080/toLogin
4、用户名和密码非空校验
- 文本框设置
required="required"
(五)控制器编写登录验证方法
1、查看表单action属性值
- 表单的
action="/login"
- 模型里的属性
currentYear
下面有红色波浪线,提示模板页面无法解析,怎么去掉呢?
2、在登录控制器添加路由函数
- 编写路由函数
login()
,请求路径为/login
@PostMapping("/login")
public String login(HttpServletRequest request, Model model) {
// 获取登录表单提交的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
// 判断用户是否登录成功(自行设置合法用户名与密码)
if (username.equals("howard") && password.equals("903213")) {
model.addAttribute("loginMsg", "恭喜,[" + username + "]登录成功~");
return "success"; // 逻辑视图名(映射到/templates/success.html)
} else {
model.addAttribute("loginMsg", "遗憾,[" + username + "]登录失败~");
return "failure"; // 逻辑视图名(映射到/templates/failure.html)
}
}
(六)编写登录成功与失败模板页面
1、编写登录成功页面
- 在
templates
目录里创建success.html
<!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">
<title>登录成功</title>
<link th:href="@{/bootstrap-5.2.0/css/bootstrap.css}" rel="stylesheet">
<javascript th:src="@{/bootstrap-5.2.0/js/bootstrap.bundle.js}"></javascript>
<javascript th:src="@{/scripts/jquery-3.5.1.min.js}"></javascript>
</head>
<body>
<div class="col-6 text-center m-auto border-info border p-3 bg-light" style="margin-top:50px!important;">
<!--/*@thymesVar id="loginMsg" type="java.lang.String"*/-->
<p th:text="${loginMsg}" class="text-success"></p>
</div>
</body>
</html>
2、编写登录失败页面
- 在
templates
目录里创建failure.html
<!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">
<title>登录失败</title>
<link th:href="@{/bootstrap-5.2.0/css/bootstrap.css}" rel="stylesheet">
<javascript th:src="@{/bootstrap-5.2.0/js/bootstrap.bundle.js}"></javascript>
<javascript th:src="@{/scripts/jquery-3.5.1.min.js}"></javascript>
</head>
<body>
<div class="col-6 text-center m-auto border-info border p-3 bg-light" style="margin-top:50px!important;">
<!--/*@thymesVar id="loginMsg" type="java.lang.String"*/-->
<p th:text="${loginMsg}" class="text-danger"></p>
</div>
</body>
</html>
(七)启动项目,测试效果
- 启动项目后,在浏览器里访问
http://localhost:8080/toLogin
- 输入正确的用户名和密码(howard : 903213)
- 输入其它用户名或密码
六、Thymeleaf访问模型里的数据
(一)页面访问Model里的实体数据
1、创建个人实体类 - Person
package net.hw.lesson09.bean;
/**
* 功能:个人实体类
* 作者:华卫
* 日期:2021年05月24日
*/
public class Person {
private int id;
private String name;
private String gender;
private int age;
private String telephone;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", telephone='" + telephone + '\'' +
'}';
}
}
2、在登录控制器里添加获取个人信息方法
3、创建显示个人信息的模板页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>个人信息</title>
<link th:href="@{/bootstrap-4.0.0/css/bootstrap.css}" rel="stylesheet">
<javascript th:src="@{/bootstrap-4.0.0/js/jquery-3.4.1.min.js}"></javascript>
<javascript th:src="@{/bootstrap-4.0.0/js/bootstrap.bundle.js}"></javascript>
<javascript th:src="@{/bootstrap-4.0.0/js/bootstrap.js}"></javascript>
</head>
<body>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">显示个人信息</h3>
</div>
<div class="panel-body">
编号:<span th:text="${person.id}">1</span><br/>
姓名:<span th:text="${person.name}">娃哈哈</span><br/>
性别:<span th:text="${person.gender}">男</span><br/>
年龄:<span th:text="${person.age}">20</span><br/>
电话:<span th:text="${person.telephone}">15878789056</span><br/>
</div>
</div>
</body>
</html>
3、启动应用,测试效果
- 启动应用
- 访问
http://localhost:8080/getPerson
- 问题:Bootstrap的面板样式没有起作用。
- 以在线方式导入Bootstrap 3,就可以看到面板效果
- 说明:Bootstrap从4.x开始,用Card替换了Panel
- 修改person.html,采用card组件
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>个人信息</title>
<link th:href="@{/bootstrap-4.0.0/css/bootstrap.css}" rel="stylesheet">
<javascript th:src="@{/bootstrap-4.0.0/js/jquery-3.4.1.min.js}"></javascript>
<javascript th:src="@{/bootstrap-4.0.0/js/bootstrap.bundle.js}"></javascript>
<javascript th:src="@{/bootstrap-4.0.0/js/bootstrap.js}"></javascript>
</head>
<body>
<div class="card">
<div class="card-header" style="background-color:royalblue">
<h4 class="card-title" style="color:white">显示个人信息</h4>
</div>
<div class="card-body">
编号:<span th:text="${person.id}">1</span><br/>
姓名:<span th:text="${person.name}">娃哈哈</span><br/>
性别:<span th:text="${person.gender}">男</span><br/>
年龄:<span th:text="${person.age}">20</span><br/>
电话:<span th:text="${person.telephone}">15878789056</span><br/>
</div>
<div class="card-footer">
信工院2021.05.24
</div>
</div>
</body>
</html>
- 启动应用,查看效果
(二)页面访问Model里的列表数据
1、创建商品实体类 - Product
package net.hw.lesson09.bean;
/**
* 功能:商品实体类
* 作者:华卫
* 日期:2021年05月24日
*/
public class Product {
private int id;
private String name;
private double price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
'}';
}
}
2、创建商品控制器 - ProductController
package net.hw.lesson09.controller;
import net.hw.lesson09.bean.Product;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.ArrayList;
import java.util.List;
/**
* 功能:商品控制器
* 作者:华卫
* 日期:2021年05月24日
*/
@Controller
public class ProductController {
@GetMapping("/getProducts")
public String getProducts(Model model) {
// 创建商品列表
List<Product> products = new ArrayList<>();
Product product = new Product();
product.setId(1);
product.setName("海尔电视机");
product.setPrice(2500);
products.add(product);
product = new Product();
product.setId(2);
product.setName("小米手机");
product.setPrice(2000);
products.add(product);
product = new Product();
product.setId(3);
product.setName("华为电脑");
product.setPrice(5000);
products.add(product);
// 将商品列表写入模型
model.addAttribute("products", products);
// 返回逻辑视图名
return "products";
}
}
3、创建显示商品信息页面 - products.html
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>商品信息</title>
<link th:href="@{/bootstrap-4.0.0/css/bootstrap.css}" rel="stylesheet">
<javascript th:src="@{/bootstrap-4.0.0/js/jquery-3.4.1.min.js}"></javascript>
<javascript th:src="@{/bootstrap-4.0.0/js/bootstrap.bundle.js}"></javascript>
<javascript th:src="@{/bootstrap-4.0.0/js/bootstrap.js}"></javascript>
</head>
<body>
<div class="card">
<div class="card-header" style="background-color:royalblue">
<h4 class="card-title" style="color:white">显示商品信息</h4>
</div>
<div class="card-body">
<ul class="list-group">
<li class="list-group-item" th:each="product:${products}">
编号:<span th:text="${product.id}">1</span><br/>
名称:<span th:text="${product.name}">洗衣机</span><br/>
单价:<span th:text="${product.price}">1000</span><br/>
</li>
</ul>
</div>
<div class="card-footer">
信工院2021.05.24
</div>
</div>
</body>
</html>
4、启动应用,查看效果
- 启动应用
- 访问
http://localhost:8080/getProducts
5、对模型里的数据进行判断
- 通过${not #lists.isEmpty(products)}表达式判断products是否为空。Thymeleaf支持>、<、>=、<=、==、!=作为比较条件,同时也支持SpringEL表达式语言用于条件中。
- 修改显示商品信息页面
- 修改商品控制器
- 启动应用,查看效果
(三)页面里JavaScript访问模型里的数据
1、显示个人信息页面
- 添加脚本,修改代码
- 启动应用,查看效果
- 通过 th:inline="javascript"添加到script标签,这样JavaScript即可访问model中属性。通过[[${属性}]]格式获得实际的值。
2、显示商品列表信息
- 添加脚本,修改代码
- 修改商品控制器
- 启动应用,查看效果
- 优化代码,采用循环结构显示商品列表