SpringBoot 教程详解 项目演示 资源整合 个人总结 狂神笔记(上)

文章目录

学习索引

在这里插入图片描述
扎实的基础是为了更容易看懂底层源码,熟练框架使用可以让开发的使用更加简约,

一、SpringBoot 简介

1.回顾 Spring

什么是Spring

  • Spring是一个开源框架,2003 年兴起的一个轻量级的Java 开发框架,作者:Rod Johnson 。
  • Spring是为了解决企业级应用开发的复杂性而创建的,简化开发

Spring是如何简化Java开发的:

为了降低Java开发的复杂性,Spring采用了以下4种关键策略:

  1. 基于POJO的轻量级和最小侵入性编程,所有东西都是bean;
  2. 通过IOC,依赖注入(DI)和面向接口实现松耦合;
  3. 基于切面(AOP)和惯例进行声明式编程;
  4. 通过切面和模版减少样式代码,比如,RedisTemplate,xxxTemplate;

2.SpringBoot 简介

发展历史

什么是SpringBoot呢,就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置, you can “just run”,能迅速的开发web应用,几行代码开发一个http接口。

随着 Spring 不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。Spring Boot 正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用 Spring 、更容易的集成各种常用的中间件、开源软件;

Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。Spring Boot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。

简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。

Spring Boot 出生名门,从一开始就站在一个比较高的起点,又经过这几年的发展,生态足够完善,Spring Boot 已经当之无愧成为 Java 领域最热门的技术。

SpringBoot 特点

Spring Boot的主要优点:

  • 是一个脚手架,而非框架
  • 为所有Spring开发者更快的入门
  • 开箱即用,提供各种默认配置来简化项目配置
  • 内嵌式容器简化Web项目
  • 没有冗余代码生成和XML配置的要求

为什么要约定大于配置:

  • 框架、脚手架之所以能简化开发,因为这些工具在底层帮助我们做了大量的工作,不按照工具规范使用,也就无法自动实现大量工作

3.微服务

什么是微服务:

  • 微服务是一种架构风格,他要求我们在开发一个应用的时候,这个应用必须创建构成一系列小服务的组合,可以通过http的方法进行相互沟通

单体架构:

  • 我们将一个应用中的所有服务都封装在一个应用中
  • 无论什么系统,都要将数据库访问、web访问,等各个功能放到一个war包内

单体架构优缺点:

  • 优点是,易于开发和测试,方便部署,需要扩展时,只需将war复制多分,放在多个服务器上,再负载均衡即可
  • 缺点是,即使需改一个小地方,整个服务都要重新打包、部署,尤其是大型应用,必须要做好分工维护、协同工作,不可能将所有内容都整合在一个应用中

微服务架构:

  • 把每个功能模块独立出来,各个独立的模块动态组合,

微服务架构优点:

  • 节省调用资源
  • 每个功能模块服务都是一个可以替换的,可以独立升级的软件代码

如何构建微服务:

微服务这种庞大的系统架构给运维和部署带来了很大的难度,因此,spring为我们带来了构建大型分布式微服务的全套、全流程产品

  • 构建一个个独立的微服务引用单元,可以使用springboot,帮我们快速构建一个应用
  • 大型分布式网络服务的调用,我们使用springcloud
  • 在分布式中间,进行流式数据计算,我们使用spring cloud data flow
  • spring为我们提供了从开始构建应用到大型分布式因公全流程方案

在这里插入图片描述
在这里插入图片描述

二、快速创建 SpringBoot 项目

项目环境

jdk 1.8 ,maven 3.6.1,springboot最新版,IDEA

项目创建方式

springboot项目的搭建可以手动,也可以自动,通常我们选择联网的方式快速在线搭建springboot项目

官网搭建:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

项目参数根据自己情况来定,选择war包,添加一个 spring web 依赖,springboot会自动生成相关配置

generate生成包,下载到本地,解压缩,用idea加载项目即可,

进入项目,此时项目结构还没有被idea识别,右键pom.xml,将其作为maven项目导入
在这里插入图片描述
idea会自动识别项目结构,并下载相关依赖
在这里插入图片描述
IDEA联网搭建:

删除这个项目,直接在IDEA中联网搭建,创建项目,选择

在这里插入图片描述
下一步,根据自己喜好填写项目信息
在这里插入图片描述
添加依赖,我们可以先添加一个spring web
在这里插入图片描述
确定创建项目,首次创建springboot需要下载很多依赖,耐心等待
在这里插入图片描述
项目联系阶段,我们可以先将不用的文件删除,保持项目干净整洁
在这里插入图片描述
在这里插入图片描述
通常我们直接使用IDEA联网创建

项目结构

在这里插入图片描述
springboot默认创建一些文件,供我们快速使用

  • application是项目主程序,启动入口,不可以删除
  • application.properties是springboot核心配置文件,后续我们可以将其替换为yaml
  • test目录下为测试程序,不要改动他的包结构

启动application main方法,即启动项目
在这里插入图片描述
从控制台我们可以看到启动信息,springboot内嵌了tomcat,端口号8080,访问测试一下
在这里插入图片描述
空项目,所以返回了一个error page

我们以后所创建的所有程序及包结构都要与application同级目录或同级目录的子目录下,否则项目无法正常运行,因为springboot启动时要扫描目录,这个目录就是appllication所在的目录,比如,

在这里插入图片描述
添加一个HelloController,返回一个字符串,重启项目,访问测试

@RestController
public class HelloController {
   
    @RequestMapping("/hello")
    public String hello() {
   
        return "hello springboot";
    }
}

在这里插入图片描述
这样就与spring的开发方式接轨了,

用springboot构建项目,我们甚至都没有配置web.xml,applicationContext.xml,就成功启动了项目,并访问测试,因为springboot在底层实现了自动装配

简要分析

主启动类:

appication主启动程序有一个注解SpringBootApplication,进入查看源码
在这里插入图片描述
注解中包含了@Component,说明application主启动类本身就是spring的一个组件,

pom.xml初始默认的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.swy</groupId>
    <artifactId>springboot-01-helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>springboot-01-helloworld</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  • parent标签,说明我们这个项目还有一个父项目,叫spring-boot-starter-parent,是个远程在线的项目,用来控制版本与打包内容
  • dependencies依赖标签,其中,spring-boot-starter-web 用于实现http接口,包含了springmvc,使用tomcat作为嵌入式容器,test用于单元测试
  • build构建配置部分,默认使用 spring-boot-maven-plugin ,配合 spring-boot-starter-parent 就可以将springboot打包成jar包直接运行
    build标签自动添加了打包插件,要想打包并启动项目,这个插件不可缺少

通过观察,我们发现我么在创建项目时,自动添加的依赖都以 spring-boot-starter 开头,我们通过springboot添加的依赖都是以spring-boot-starter开头的,且没有版本号,因为springboot同一帮我们选择好了

当然我们也可以自己在maven仓库上搜索所需的依赖坐标,添加进来,一般我们都使用springboot提供的依赖,如果无法下载或失效,我们就自己添加带版本号的完整依赖

项目打包

如何打包:双击install即可打包
在这里插入图片描述
打包成功
在这里插入图片描述
target目录下生成 jar/war 包,一个jar包就是一个独立的程序,我们可以单独将 jar 包提取出来,通过命令行java -jar运行,它已经可以不依赖IDEA,独立的在JDK环境中运行

如果打包失败,可能是代码出现异常,也可能是依赖失效、冲突,亦或是旧的jar/war残留影响,需要具体问题具体分析调整,只有打包成功,项目才可以说可以启动

这种独立的模块化结构,也为下一步微服务做好了准备

补充分析

pom.xml配置中,依赖 spring-boot-starter 叫做启动器,如果我们创建项目没有spring web时,可能会有这个单独的依赖,如果添加了spring web依赖,spring-boot-starter就会添加在web依赖中
在这里插入图片描述
springboot的启动配置几乎都在properties或yaml中进行,springboot默认使用了properties,空配置

修改端口号:properties中添加server.port=8080,默认就是端口8080,许多配置基本上都有提示,减少错误率,加快配置速度
在这里插入图片描述

修改 banner

上网搜索springboot banner,搜索喜欢的字符排版,拷贝,

在resources目录下新建banner.txt,粘贴上述字符排版,重启即可

三、SpringBoot 原理详解

1.SpringBoot 自动装配

pom.xml

pom.xml 中,parent标签spring-boot-starter-parent可以点进入查看父级,里面的parent标签 spring-boot-dependencies可以继续点进去查看父级,
在这里插入图片描述
在这里插入图片描述
最终我们看到,在spring-boot-dependencies这个依赖中,我们看到,这个pom.xml中包含了绝大部分的依赖坐标,其中,properties标签控制着各个依赖的版本,这些版本号将随着官方的更新动态更新
在这里插入图片描述
dependencyManagement标签包括了各种依赖坐标,并引入properties属性中的版本号,拼成完整依赖坐标
在这里插入图片描述
这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心;

以后我们导入依赖默认是不需要写版本;但是如果导入的包没有在依赖中管理着就需要手动配置版本了;

回到项目 pom.xml 中,

自动配置:

pom.xml:

  • spring-boot-dependencies,核心依赖在父工程里
  • 我们在写或引入springboot依赖的时候,不需要指定版本,因为父工程中有版本仓库,
启动器

启动器:没有启动器,项目将无法启动

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

有了spring-boot-starter启动器,我们在其名字后面加上各种场景、依赖名字,就会帮我们自动导入该环境的所有依赖,比如

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

启动器:

  • 通俗讲,就是springboot的启动场景
  • springboot会将所有的功能场景,都变成一个个启动器
  • 我们需要使用什么功能,只需找到对应的启动器即可,spring-boot-starter-名字

官网文档中,维护者大量的启动器
在这里插入图片描述

主程序
@SpringBootApplication
public class Springboot01HelloworldApplication {
   
    public static void main(String[] args) {
   
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }
}

@SpringBootApplication标注了该类是springboot的一个应用,run方法是个静态方法,通过反射加载当前类对象,进行启动

下面,我们深入分析@SpringBootApplication注解,其中@Target @Retention @Documented @Inherited四个元注解不在解释,分析每个层级的重点注解

@SpringBootApplication:最外层

@SpringBootConfiguration
	@Configuration:说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件
		@Component:这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用
		
@EnableAutoConfiguration:见名知意, 告诉SpringBoot开启自动配置功能,这样自动配置才能生效,以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置
	@AutoConfigurationPackage:表示自动配置包
		@Import({Registrar.class}):Spring底层注解, 给容器中导入一个组件导入选择器,Registrar中包含了元数据meta,包名packagename
	@Import({AutoConfigurationImportSelector.class}):给容器导入组件自动配置,包注册,AutoConfigurationImportSelector中有环境,资源加载器,选择组件,有方法getCandidateConfigurations可以获取所有配置,进入方法内,可以看到获取候选的配置
		
@ComponentScan(...):用于包扫描,它对应XML配置中的元素,自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中

里面的注解各种操作,其实就是为了让@SpringBootApplication标注的启动类可以将所有资源导入

其中 getCandidateConfigurations方法获取候选配置,方法里涉及到了 META-INF/spring.factories ,这是自动配置的核心文件,在依赖包中可以找到
在这里插入图片描述
打开可以发现,里面有各个情况下的配置对应的全限定类名

我们根据源头打开spring.factories , 看到了很多自动配置的文件;这就是自动配置根源所在!
在这里插入图片描述

  • Initializers:初始化
  • Application Listeners:应用监听
  • Auto Configuration Import Listeners
  • Auto Configuration Import Filters
  • Auto Configure
  • Failure analyzers
  • Template availability providers

我们在上面的自动配置类随便找一个打开看看,比如 :WebMvcAutoConfiguration,

可以看到这些一个个的都是JavaConfig配置类,而且都注入了一些Bean,可以找一些自己认识的类,看着熟悉一下!

所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。

每个类中,都有对应的Java代码进行配置

结论:

  • SpringBoot所有的自动配置,都是在启动时扫描并加载,
  • 所有的自动配置类都在spring.factories中,但是不一定生效,
  • 要判断条件是否成立,即,导入了对应的start,就有对应的启动器,有了启动器,我们的自动装配就会生效,就会配置成功
  1. springboot在启动的时候,从类路径下/META-INF/spring.factories 获取指定的值
  2. 将这些自动配置的类导入容器,自动配置就会生效,帮助我们进行自动配置
  3. 以前我们需要自动配置的东西,现在springboot帮我们做了
  4. 整合javaEE,解决方案、自动配置的东西,都在 spring-boot-autoconfigure-2.x.x.jar 这个包下
  5. 这个jar包会把所有需要导入的组件,以类名的方式返回(spring.factories),这些组件就会被添加到容器
  6. 容器中会出现很多的xxxAutoConfiguration的类,就是这些类,给容器导入了这个场景需要的所有组件,并自动配置,@Configuration,JavaConfig(可以自己点进去查看源码)
  7. 有了自动配置类,免去了我们手动编写配置文件的工作

2.SpringBoot 启动原理

最初以为就是运行了一个main方法,没想到却开启了一个服务

@SpringBootApplication
public class Springboot01HelloworldApplication {
   
    public static void main(String[] args) {
   
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }
}

SpringApplication.run分析

分析该方法主要分两部分,一部分是SpringApplication的实例化,二是run方法的执行;

SpringApplication

这个类主要做了以下四件事情:

  1. 推断应用的类型是普通的项目还是Java Web项目(通过导入依赖判断)
  2. 查找并加载所有可用初始化器 , 设置到initializers属性中
  3. 找出所有的应用程序监听器,设置到listeners属性中
  4. 推断并设置main方法的定义类,找到运行的主类,这里就是 Springboot01HelloworldApplication.class

查看 SpringApplication 构造器

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

在这里插入图片描述
run方法的详细过程,也可以上网搜索

关于SpringBoot 的理解:

  • 自动装配
  • run方法,

3.SpringBoot 配置文件

概念

SpringBoot使用一个全局的配置文件在resources中, 配置文件名称是固定的,application.properties 或 application.yaml,

官方推荐使用 application.yaml,因此,通常我们创建新项目后,都会删除默认的application.properties,重新创建 application.yaml

编写 springboot 的配置文件时,我们可以看到有大量的提示可以帮助我们快速生成

application.properties

  • 语法结构 :key=value

application.yml

  • 语法结构 :key:空格 value

配置文件的作用 :

  • 其实就是在修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;

比如,我们配置tomcat启动默认端口号,

application.properties

server.port=8090

application.yml,

server:
  port: 8090

注意,yaml的配置结构有缩进,有空格,格式不对就会失效

我们可以在配置yaml时,可以写成server.port的方式,利用idea自动功能,生成标准结构
在这里插入图片描述

yaml 概述

YAML是 “YAML Ain’t a Markup Language” (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)

配置文件后缀可以写 yaml 也可以写成 yml

这种语言以数据作为中心,而不是以标记语言为重点!

以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比下yaml和xml

传统xml配置

<server>
    <port>8081<port>
</server>

yaml配置:

server:
  port: 8081

说明:语法要求严格!

  1. 空格不能省略
  2. 以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
  3. 属性和值的大小写都是十分敏感的。

yaml 可以保存复杂的数据结构,这是 properties 无法比拟的

字面量:普通的值 [ 数字,布尔值,字符串 ]
k: v

注意:

“ ” 双引号,不会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思;

比如 :name: “kuang \n shen” 输出 :kuang 换行 shen

‘’ 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出

比如 :name: ‘kuang \n shen’ 输出 :kuang \n shen

对象、Map(键值对)

#对象、Map格式
k: 
    v1:
    v2:

在下一行来写对象的属性和值得关系,注意缩进;比如:


student:
    name: qinjiang
    age: 3

也可以写成行内写法

student: {
   name: qinjiang,age: 3}
数组( List、set )

用 - 值表示数组中的一个元素,比如:


pets:
 - cat
 - dog
 - pig

行内写法

pets: [cat,dog,pig]

小结:

  • yaml 可以保存复杂数据结构,使用 缩进写法或行内写法,properties只能使用键值对保存简单数据
  • yaml 缩进是分层级的,不同的属性有固定的层级,不要随意缩进
  • yaml 中,每个层级上,同一个属性写一次就好,子级只需往下缩进即可
yaml 功能

yaml 文件更强大的地方在于,他可以给我们的实体类直接注入匹配值

创建实体类

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog {
   
    private String name;
    private Integer age;
}
@Component
@AllArgsConstructor
@NoArgsConstructor
public class Person {
   
    private String name;
    private Integer age;
    private Boolean isHappy;
    private Date birth;
    private Map<String,Object> map;
    private List<Object> list;
    private Dog dog;
}

之前,我们可以使用 spring 注解 @Value(“属性值”) 来给属性赋值,但是每一个都加注解赋值很麻烦

现在,我们使用 yaml 赋值属性

修改 application.xml

person:
  name: swy
  age: 18
  isHappy: true
  birth: 2020/04/08
  map:
    k1: v1
    k2: v2
  list:
    - code
    - music
    - girl
  dog:
    name: huahua
    age: 5

在实体类上,添加注解 @ConfigurationProperties,用前缀指定添加的是哪个属性

这个注解可能会产生提示,他表示如果我们加这个注解,但没有响应的属性配置,就会报错,如果添加了,可以忽略不管
在这里插入图片描述

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "person")
public class Person {
   
    private String name;
    private Integer age;
    private Boolean isHappy;
    private Date birth;
    private Map<String,Object> map;
    private List<Object> list;
    private Dog dog;
}

启动测试类,测试,注意,这个测试类需要满足官方规范(包结构、注解)才能生效,如果手动添加需要注意

@SpringBootTest
class Springboot01HelloworldApplicationTests {
   
    @Autowired
    private Person person;
    @Test
    void contextLoads() {
   
        System.out.println(person);
    }
}

在这里插入图片描述
如何解决爆红问题,

根据提示点击
在这里插入图片描述
根据跳转页面信息,添加以下依赖,即可

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

注意:

  • yaml 配置属性时,属性名要与实体属性一致,
  • 不要有多余的空格
properties 配置

官方推荐使用yaml配置,当然,也可以使用 properties配置

properties配置文件在写中文的时候,会有乱码 , 我们需要去IDEA中设置编码格式为UTF-8;

settings–>FileEncodings 中配置;

使用举例:

添加配置文件,person.properties

name=swy
age=18
sex=男

在实体类上添加注解,指定配置文件路径,并且必须在指定的属性上加注解@Value和spel表达式

@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@PropertySource(value = "classpath:person.properties")
public class Person {
   
    @Value("${name}")
    private String name;
    private Integer age;
    private Boolean isHappy;
    private Date birth;
    private Map<String,Object> map;
    private List<Object> list;
    private Dog dog;
}

在这里插入图片描述

扩展 spel 表达式

spel表达式比较灵活,可以在很多处使用,比如,yaml 配置,

重新将配置文件切换为 yaml ,添加 spel 表达式

person:
  name: swy${
   random.uuid}
  age: ${
   random.int}
  isHappy: true
  birth: 2020/04/08
  map:
    k1: v1
    k2: v2
  list:
    - code
    - music
    - girl
  dog:
    name: huahua
    age: 5

注入到实体类上,看效果
在这里插入图片描述
spel 表达式功能比较多,可以在很多处使用,可以自行上网查询,

可以写在 yaml 中,这也说明了 yaml 的功能强大

小结对比

在这里插入图片描述

  1. @ConfigurationProperties只需要写一次即可 , @Value则需要每个字段都添加
  2. 松散绑定:这个什么意思呢? 比如我的yml中写的last-name,这个和lastName是一样的, - 后面跟着的字母默认是大写的。这就是松散绑定。可以测试一下
  3. JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性
  4. 复杂类型封装,yml中可以封装对象 , 使用value就不支持

结论:

  • 配置yml和配置properties都可以获取到值 , 强烈推荐 yml;
  • 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;
  • 如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties,不要犹豫!
JSR303 校验

Springboot 中可以用 @Validated 来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。

用法:

  • 在类上加注解 @Validated 开启校验,在具体的属性上加相应注解指定校验规则

我们这里来写个注解让我们的name只能支持Email格式;

@Component //注册bean
@ConfigurationProperties(prefix = "person")
@Validated  //数据校验
public class Person {
   
    @Email(message="邮箱格式错误") //name必须是邮箱格式
    private String name;
}

如果我们给name注入的属性不是email格式就会报错
在这里插入图片描述

有了这一层校验,当我们在实际业务中注入的属性不符合校验规则时,就会自动报异常,这比我们手动去写代码校验串格式要方便很多

尤其是在接收前端数据时,使用起来非常方便

JSR303 校验提供了很多种校验规则

@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;

空检查
@Null       验证对象是否为null
@NotNull    验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank   检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty   检查约束元素是否为NULL或者是EMPTY.
    
Booelan检查
@AssertTrue     验证 Boolean 对象是否为 true  
@AssertFalse    验证 Boolean 对象是否为 false  
    
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  
@Length(min=, max=) string is between min and max included.

日期检查
@Past       验证 Date 和 Calendar 对象是否在当前时间之前  
@Future     验证 Date 和 Calendar 对象是否在当前时间之后  
@Pattern    验证 String 对象是否符合正则表达式的规则,

.......等等
除此以外,我们还可以自定义一些数据校验规则

其中,有了 @Pattern 正则判断,基本上等同于可以对任何数据进行校验了

多环境配置
配置文件存放路径

springboot 配置文件默认在 resources目录下,此外,还可以放在以下目录中,

1. file:./config/
2. file:./
3. classpath:/config/
4. classpath:/  这个路径,就是我们创建项目默认的配置文件存放位置

springboot 启动会扫描以上位置的 properties 或者 yml 文件作为Spring boot的默认配置文件,注意,不论放在那里,名字都必须是 application

file 指项目根路径,classpath指类路径,也就是java或resources路径下,

通过测试,我们发现,核心配置文件在这些目录的加载优先级为:1>2>3>4

多环境配置文件 properties

我们可以在目录中配置多个环境(比如,开发、测试、生产)的配置文件,

通过命令行的方式或者 spring.profile.active 选择启动哪套配置,比如
在这里插入图片描述
默认启动,当然是使用 application.properties 配置,优先级最高

我们在 application.properties 中添加配置,选择激活哪个环境,比如选择dev环境

spring.profiles.active=dev
多环境配置 yml

yml 更加强大,在一个配置文件中就可以实现多文档模块的功能

yml 使用 ---分隔多文档环境,我们可以理解为这就是多个不同的配置文件,集中放在一起,使用---分隔开,

使用 spring.profiles 分别给不同模块起名字,使用 spring.profiles.active 选择使用哪个配置启动,比如,

server:
  port: 8081
spring:
  profiles: dev
---
server:
  port: 8082
spring:
  profiles: test
---
server:
  port: 8083
spring:
  profiles:
    active: pro

在这里插入图片描述
当然,当配置非常多的时候,内容过多,不好查找,也是会配置多个配置文件的,实际工作灵活使用

注意:

  • 相同情况下,porperties配置的优先级高于yml配置
    如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!

扩展:

指定位置加载配置文件

我们还可以通过spring.config.location来改变默认的配置文件位置

项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;这种情况,一般是后期运维做的多,相同配置,外部指定的配置文件优先级最高

java -jar spring-boot-config.jar --spring.config.location=F:/application.properties
自动配置深入理解

首先从 @SpringBootApplication 进入,一直找到 @Import(AutoConfigurationImportSelector.class) 进入,

其中 getCandidateConfigurations方法中有 SpringFactoriesLoader,进入
在这里插入图片描述
我们可以看到 spring.factories 的位置信息

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

这也就是 spring-boot-autoconfigure 依赖包下的 spring.factories 文件,
在这里插入图片描述
打开,可以看到很多的类,所有 xxxAutoConfiguration 都是自动配置类

自动配置类

而我们可以在 application 上配置的信息,和 spring.factories 目录中的配置类 xxxAutoConfiguration 有很大关联

我们以 HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

分析其代码信息


//表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件;
@Configuration 

//启动指定类的ConfigurationProperties功能;
  //进入这个HttpProperties查看,将配置文件中对应的值和HttpProperties绑定起来;
  //并把HttpProperties加入到ioc容器中
@EnableConfigurationProperties({
   HttpProperties.class}) 

//Spring底层@Conditional注解
  //根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效;
  //这里的意思就是判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(
    type = Type.SERVLET
)

//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
@ConditionalOnClass({
   CharacterEncodingFilter.class})

//判断配置文件中是否存在某个配置:spring.http.encoding.enabled;
  //如果不存在,判断也是成立的
  //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
@ConditionalOnProperty(
    prefix = "spring.http.encoding",
    value = {
   "enabled"},
    matchIfMissing = true
)

public class HttpEncodingAutoConfiguration {
   
    //他已经和SpringBoot的配置文件映射了
    private final Encoding properties;
    //只有一个有参构造器的情况下,参数的值就会从容器中拿
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
   
        this.properties = properties.getEncoding();
    }
    
    //给容器中添加一个组件,这个组件的某些值需要从properties中获取
    @Bean
    @ConditionalOnMissingBean //判断容器没有这个组件?
    public CharacterEncodingFilter characterEncodingFilter() {
   
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
        return filter;
    }
    //......
}

这里的信息决定了我们可以在 application 配置文件中,添加的相关配置信息可以写什么内容,比如

进入到 serverProperties.class 中可以看到,

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)

在这里插入图片描述

好,那么,我们在 application 配置文件中就可以写 server.xxx.xxx

在这里插入图片描述

  • 所以,有些时候我们使用的一些配置信息会失效,或者即将失效,因为这里的配置类更新了新的规范
  • 当我们想配置哪方面的相关信息的时候,也可以自己到响应的配置类中去查找

一句话总结 :根据当前不同的条件判断,决定这个配置类是否生效!

  • 一但这个配置类生效;这个配置类就会给容器中添加各种组件;
  • 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
  • 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
  • 配置文件能配置什么就可以参照某个功能对应的这个属性类

这就是自动装配的原理!

精髓

  1. SpringBoot启动会加载大量的自动配置类
  2. 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
  3. 我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
  4. 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;

xxxxAutoConfigurartion:自动配置类;给容器中添加组件

xxxxProperties:封装配置文件中相关属性;

@Conditional

了解完自动装配的原理后,我们来关注一个细节问题,自动配置类必须在一定的条件下才能生效;

@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

在这里插入图片描述
那么多的自动配置类,必须在一定的条件下才能生效;也就是说,我们加载了这么多的配置类,但不是所有的都生效了。

我们怎么知道哪些自动配置类生效?

我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;

在 application.properties 中添加

#开启springboot的调试类
debug=true

或者 yml 添加

debug: true

Positive matches:(自动配置类启用的:正匹配)开启生效了

Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)没有生效的

Unconditional classes: (没有条件的类)

在这里插入图片描述
我们也可以通过这种方法,测试导入一个依赖,究竟都有哪些配置生效了

遇到不认识的配置,我们可以点进去,找到 xxxxProperties,进而反推 factories 中配置的 xxxxAutoConfigurartion,分析 xxxxAutoConfigurartion源码,判断其配置信息

出现爆红说明没有依赖,那么我们再通过 spring-boot-starter 启动器,添加响应的依赖使其生效,这是学习方法

SpringBoot 整合资源

6/7/8/9

四、SpringBoot Web开发

1.概述

创建 springboot web 项目,我们要充分利用其自动装配的特点

使用SpringBoot的步骤:

  1. 创建一个SpringBoot应用,选择我们需要的模块,SpringBoot就会默认将我们的需要的模块自动配置好
  2. 手动在配置文件中配置部分配置项目就可以运行起来了
  3. 专注编写业务代码,不需要考虑以前那样一大堆的配置了。

思考:

  • springboot 到底帮助我们配置了什么?我们能不能修改?能修改哪些配置?能不能扩展

重点关注:

  • 向容器中自动配置组件 :*** Autoconfiguration
  • 自动配置类,封装配置文件的内容:***Properties

要解决的问题:

  1. 静态资源导入问题
  2. 首页的确定
  3. 摒弃了 jsp 页面,我们改用模板引擎。这里以 Thymeleaf 为例
  4. 装配、扩展 SpringMVC、视图解析器等
  5. 增删改查
  6. 拦截器
  7. 国际化
项目准备

创建SpringBoot项目,依然打 jar 包
在这里插入图片描述

暂时添加web模块依赖,其他的需要的时候再添加
在这里插入图片描述
创建项目后,删掉多余的文件,保持界面干净,添加常用包结构,注意放在主启动类所在的包路径下
在这里插入图片描述

添加controller

@RestController
public class HelloController {
   
    @GetMapping("/hello")
    public String hello() {
   
        return "hello springboot!";
    }
}

访问测试:http://localhost:8080/hello
在这里插入图片描述
访问正常,说明基本项目创建成功

2.静态资源导入

思考:

  • 之前我们创建 spring web 应用打 war 包,resources下会有一个webapp,我们以前都是将所有的页面导在这里面的;
  • 现在我们创建 springboot,打 jar 包,这种方式SpringBoot同样可以写页面,但是SpringBoot对于静态资源放置的位置,是有规定的;

创建项目之初,resources目录默认有两个文件夹,static存放静态资源,template存放模板,
在这里插入图片描述
具体该如何使用,利用前面所学知识,我们查看源码 WebMvcAutoConfiguration

在源码中找到 WebMvcAutoConfigurationAdapter 这是静态资源适配器,里面有一个方法叫 addResourceHandlers ,这是添加资源处理器,我们来分析它(新版本代码略有不同,但含义都一样)

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
   
    if (!this.resourceProperties.isAddMappings()) {
   
        // 已禁用默认资源处理
        logger.debug("Default resource handling disabled");
        return;
    }
    // 缓存控制
    Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
    // webjars 配置
    if (!registry.you("/webjars/**")) {
   
        customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
                                             .addResourceLocations("classpath:/META-INF/resources/webjars/")
                                             .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
    // 静态资源配置
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
   
        customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
                                             .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
                                             .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
}
  1. 第一个 if 判断,表示如果我们使用自动配置,那么默认配置就失效
webjars
  1. 第二个 if 判断,表示,如果有 webjars ,那么就到 "classpath:/META-INF/resources/webjars/"路径下找资源;

什么是 webjars ,相当于将web静态资源以jar包方式引入,在webjars官网中,我们可以发现,主流的web资源都有maven坐标,

官网:https://www.webjars.org
在这里插入图片描述
比如,我们在pom中引入jquery依赖,

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.6.0</version>
</dependency>

那么在项目依赖库中我们就可以看到相关依赖,Webjars本质就是以jar包的方式引入我们的静态资源
在这里插入图片描述
"classpath:/META-INF/resources/webjars/"路径指向的也就是这里,这样就是通过webjars的方式添加了相关静态资源

通过webjars网站引入的静态资源都符合这种结构,可以引入使用

我们只需访问 /webjars/**目录,就会映射到 classpath:/META-INF/resources/webjars/目录下,我们启动测试一下,

比如访问,根据我们的目录结构,我们访问:http://localhost:8080/webjars/jquery/3.6.0/jquery.js

在这里插入图片描述

WebProperties 默认位置
  1. 第三个 if 判断位置,this.resourceProperties.getStaticLocations()表示从这里获取静态资源,我们进入查看,可以找到 WebMvcProperties类中有private String staticPathPattern = "/**";

这就表示在 /** 当前目录可以找到静态资源,加上

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
    "classpath:/META-INF/resources/",
				"classpath:/resources/", "classpath:/static/", "classpath:/public/" };

一共五个位置,都支持自动找到对应的静态资源

也就是访问 localhost:8080/ 添加后面的这几个位置路径下的文件名,就可以找到静态资源

其中

  • "classpath:/META-INF/resources/"对应webjars目录
  • "classpath:/static/"已经默认存在
  • "classpath:/resources/" "classpath:/public/"默认没有,我们也可以在resources目录下再创建 resources 和 public
  • classpath根目录下也能被直接访问

举例,我们在 static 目录下创建 hello.html,访问:http://localhost:8080/hello.html
在这里插入图片描述

当然,这个几个目录也有访问优先级,我们可以使用同名文件,分别放在这个目录下,测试优先级

resources(我们自己创建的)> static > public

通常,public存放公共资源比如js,static存放图片,resources存放上传文件upload,实际情况看个人需求

自定义位置
  1. 回到第一个 if 判断位置上,如果我们自定义了静态资源位置,那么以上默认位置就会失效

比如,我们在 application.properties 中配置了

spring.resources.static-locations=classpath:/coding/,classpath:/kuang/

那么其他默认位置都失效,只有将静态资源存放在配置目录下,才可以被访问,

当然,通常我们不自定义,用默认位置就足够了

小结

在springboot中,我们默认使用以下方式处理静态资源

  • webjars 映射 localhost:8080/webjars/
  • public,static,/**,resources 映射了 localhost:8080/

优先级:

  • resource > static > public

自定义:

  • 一旦配置,默认就会失效,改用自定义配置,不常使用

了解新技术规则一定要学会读官网文档,读源码,而不是依赖老师讲解,这样才能提高更快

3.首页定制

还是查看 WebMvcAutoConfiguration 源码,其中 WelcomePageHandlerMapping 表示欢迎页面的处理映射

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
   
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
    return welc
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值