玩一玩Spring Boot框架

文章目录

一、Spring Boot框架概述

(一)由Spring到Spring Boot

  • 关于Spring框架,可以参看本博《玩一玩Spring框架
  • Spring Framework在成为Java生态的“事实标准”之后,虽然很长时间内热度不减,但是后来没有再推出过任何激动人心的新功能,反而是开发者在处理日益增长的业务需求和管理Spring的配置、依赖和应用部署等方面不断面临新的挑战。特别是RESTful、微服务等概念的流行,以及互联网快速迭代的开发模式的兴起,使开发者们愈发希望可以拥有更敏捷、更高效的开发框架,同时开发者对服务器(或容器)的要求也更加倾向于轻量级。
  • 在这种需求的驱动之下,开发者Mike Youngstrom2012年在Spring官方的GitHub上提出了一个ID为SPR-9888的需求,他的需求代表了当时Spring Framework使用者的心声,他的需求如下:“如果开发者完全遵循Spring规范构建程序,则这样的程序与原生的Servlet规范差别是非常大的,同时这也让此类程序对Servlet容器的要求大大降低。因此,如果Spring Framework能够提供一个无需直接与Servlet容器交互的框架,那么将会大大地简化开发者的工作”。
  • 在此需求被提交给Spring官方一年之后,Spring Framework的开发者Phil Webb20138月在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>c3p0hikariCP的高性能得益于最大限度的避免锁竞争。)
  • 尽管Spring Boot大大减少了项目的配置工作,但作为开发者不要轻易被表象所迷惑,了解Spring Boot背后的工作原理才是正确的学习方向。

(三)Spring Boot的核心功能

在这里插入图片描述

1、易于使用的依赖管理Starter

(1)Starter概述

  • 在学习Spring Boot使用细节之前,先简单回顾一下Java项目构建方式的历史变迁。最早的Java项目在编译和运行期都需要显式地指定classpath,并以这种方式来管理项目所依赖的jar包和class文件。当时主流的构建工具是ant,但ant只能执行编译和构建相关的任务,没有专门管理项目依赖的工具,这也是后来人们发明依赖管理工具MavenGradle的原因(本讲案例采用Maven3.6+)。Maven出现之后,创建Java项目的第一步就是利用Maven Archetype插件创建项目。Spring Boot在Maven Archetype基础之上更进一步,通过Spring Initializr就可以很方便地创建出一个Spring Boot项目。
  • 要创建Spring Boot项目,需要先了解Spring Boot StarterStarter提供了一种简单易用的解决方案,帮助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-corespring-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、生成艺术字符

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可整合的模板引擎技术
  1. FreeMarker
  2. Groovy
  3. Thymeleaf
  4. Mustache
    ……

(二)Thymeleaf基本语法

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   

(三)实现简单登录页面

  • 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官网

(二)集成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并引用的方式

(三)添加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、显示商品列表信息

  • 添加脚本,修改代码
    在这里插入图片描述
  • 修改商品控制器
    在这里插入图片描述
  • 启动应用,查看效果
    在这里插入图片描述
  • 优化代码,采用循环结构显示商品列表
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/howard2005/article/details/125128440