SpringBoot

发布于:2025-02-14 ⋅ 阅读:(31) ⋅ 点赞:(0)

SpringBoot


特性

  • SpringBoot 帮我们简单、快速地创建一个独立的、生产级别的 Spring 应用;

  • 大多数 SpringBoot 应用只需要编写少量配置即可快速整合 Spring 平台以及第三方技术

  • 特性:

    • 快速创建独立 Spring 应用

    • 直接嵌入Tomcat、Jetty or Undertow

    • 提供可选的 starter,简化应用整合

    • 按需自动配置 Spring 以及 第三方库

    • 提供生产级特性:如 监控指标、健康检查、外部化配置等

    • 无代码生成、无xml; 都是基于自动配置技术

  • 总结:

    • 简化开发,简化配置,简化整合,简化部署,简化监控,简化运维

场景启动器

导入相关的场景,拥有相关的功能。

以spring-boot-starter-web场景为例子,我们进入web场景内部一探究竟

在web场景内部我们可以看见,它引入了一个boot项目基础的场景(图片中使用绿色方框选中的),以及web场景所需要的其它场景依赖tomcat场景,json处理场景(图片中使用红色方框选中的),还有web场景依赖jar包导入(图片中使用黄色方框选中的)。以json场景为例,我们可以更进一步进入其中一探究竟。

在json场景内部我们又看见了相似的结构,依旧是基础场景依赖(图片中使用绿色方框选中的),相关jar包依赖(图片中使用黄色方框选中的)。

依赖管理

子工程导入相关依赖可以不用声明版本号,这是因为依赖的版本号全部是由父项目来进行统一管理的。在pom里面我们可以进入父工程看一看。

在父项目中我们并没有看见版本声明,所以我们直接进入父工程的父工程(爷工程)来一探究竟。

果不其然我们发现了大量的版本号的声明属性在这个工程里面被标识出来。由此可以看出子工程的所有导入了的场景版本的版本号全部都被父工程所管理,这也就是为什么子工程不需要标明版本号的原因。

自动配置

  • 默认的包扫描规则:SpringBoot只会扫描主程序所在的包及其下面的子包

  • 配置默认值:

    • 配置文件的所有配置项 是和 某个类的对象值进行一一绑定的。

    • 很多配置即使不写都有默认值,如:端口号,字符编码等

Common Application Properties :: Spring Boot

  • 按需加载自动配置:导入的场景会导入全量自动配置包,但并不是都生效

流程简介:

  • 核心流程总结:

    • 1: 导入 starter,就会导入autoconfigure 包在基础场景下(spring-boot-stater)。

    • 2: autoconfigure 包里面 有一个文件:

      META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,

      里面指定的所有启动要加载的自动配置类(使组件生效)

    • 3: @EnableAutoConfiguration 会自动的把上面文件里面写的所有自动配置类都导入进来。自动配置类xxxAutoConfiguration 是有条件注解进行按需加载,只有满足一定的条件才会加入到容器里面。

    • 4: xxxAutoConfiguration 给容器中导入一堆组件,组件都是从 xxxProperties 中提取属性值

    • 5: xxxProperties 又是和配置文件进行了绑定,其上面的注解@EnableConfigurationProperties会开启属性与配置文件的自动绑定,

  • 效果:导入starter、修改配置文件,就能修改底层行为。

属性绑定

将容器中任意组件的属性值和配置文件的配置项的值进行绑定

1、给容器中注册组件(@Component、@Bean)

2、使用 @ConfigurationProperties 声明组件和配置文件的哪些配置项进行绑定

@Component
@ConfigurationProperties(prefix = "dog")
@Data
public class DogProperties {
​
    private String name;
    private int age;
    private String gender;
}
dog:
  name: "旺财"
  age: 3
  gender: "男"

YAML文件

  • 大小写敏感

  • 键值对写法 k: v,使用空格分割k,v

  • 使用缩进表示层级关系

    • 缩进时不允许使用Tab键,只允许使用空格,换行

    • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

  • #表示注释,从这个字符一直到行尾,都会被解析器忽略。

  • Value支持的写法:

    • 对象:键值对的集合,如:映射(map)/ 哈希(hash) / 字典(dictionary)

    • 数组:一组按次序排列的值,如:序列(sequence) / 列表(list)

    • 字面量:单个的、不可再分的值,如:字符串、数字、bool、日期

Banner自定义启动横幅

在配置文件中声明Banner所在文件地址就可以使用该路径下的Banner,自己创建一个Banner存储文件以.txt结尾,在里面就可以进行横幅的自定义功能。启动项目就可以看见自定义的横幅图片。

 

日志系统

日志门面就是接口,导入相关接口后,具体实现就可以跟据个人爱好自己选择。

springboot默认使用SLF4J(Simple Logging Facade for Java)+LogBack底层实现了日志框架,可以直接进行使用。这些对应的pom文件都囊括在了spring-boot-stater基础场景里面。

日志门面 日志实现
①JCL(Jakarta Commons Longging)②SLF4J(Simple Logging Facade for Java)③jbss-logging ①Log4j②JUC(Java.util.logging)③Log4j2③LogBack

默认输出格式:

  • 时间和日期:毫秒级精度

  • 日志级别:ERROR, WARN, INFO, DEBUG, or TRACE.

  • 进程 ID

  • ---: 消息分割符

  • 线程名: 使用[]包含

  • Logger 名: 通常是产生日志的类名

  • 消息: 日志记录的内容

日志级别

日志级别由低到高ALL-->TRACE-->DEBUG--> INFO--> WARN-->ERROR-->FATAL-->OFF;控制台只会打印指定级别及以上级别的日志

  • ALL:打印所有日志

  • TRACE:追踪框架详细流程日志,一般不使用

  • DEBUG:开发调试细节日志

  • INFO:关键、感兴趣信息日志

  • WARN:警告但不是错误的信息日志,比如:版本过时

  • ERROR:业务错误日志,比如出现各种异常

  • FATAL:致命错误日志,比如jvm系统崩溃

  • OFF:关闭所有日志记录

不指定级别的所有类,都使用 root 指定的级别作为默认级别SpringBoot日志默认级别是 INFO级别

日志分组

#设置日志打印级别
​
#设置所有包下的日志打印级别
logging.level.root=debug
#设置指定包或类的日志打印级别
logging.level.com.atguigu.cloud.springmvc.LogTest=info
​
#自定义分组
logging.group.mygroup=com.atguigu.cloud.controller,com.atguigu.cloud.service,com.atguigu.cloud.mapper
#设置自定义分组的日志打印级别
logging.level.mygroup=debug

SpringBoot中有三个预定分组包

组名 范围
web org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans
sql org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

日志文件输出

#在当前项目所在的根文件夹下,生成一个指定文件名字的日志文件
logging.file.name=boot,log
#在指定的文件路径下生成一个spring.log的日志文件
logging.file.path=D://aaa.log
logging.file.name logging.file.path 实例 效果
未指定 未指定 仅控制台输出
指定 未指定 my.log 写入指定文件,可以加路径
未指定 指定 var/log 写入指定目录,文件名为spring.log
指定 指定 以logging.file.name为准

日志文件管理策略

①归档:每天的日志单独存到一个文档中。实现日志持久化,方便获取

②切割:当每个文件超过一定的存储大小时,超过存储大小的文件切割成另外一个文件

配置项 描述
logging.logback.rollingpolicy.file-name-pattern 日志的输出格式,日志存档的文件名格式默认值:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
logging.logback.rollingpolicy.clean-history-on-start 应用启动时是否清除以前存档;默认值:false
logging.logback.rollingpolicy.max-file-size 每个日志文件进行切割的最大大小;默认值:10MB
logging.logback.rollingpolicy.total-size-cap 日志文件被删除之前,可以容纳的最大大小(默认值:0B,表示可以一直存储)。设置1GB则磁盘存储超过 1GB 日志后就会删除旧日志文件
logging.logback.rollingpolicy.max-history 日志文件保存的最大天数;默认值:7

自定义日志配置

我们可以自己创建logback的xml文件进行一些有关配置的自定义实现,比如说在控制按照自定义的格式进行日志信息的打印,等。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 定义日志的根级别 -->
    <root level="INFO">
        <!-- 控制台日志输出 -->
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
            </encoder>
        </appender>
    </root>
​
    <!-- 定义日志文件输出 -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>logs/application.log</file>
        <append>true</append>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} ~~~~ %msg%n</pattern>
        </encoder>
    </appender>
​
    <!-- 定义日志级别 -->
    <logger name="com.example" level="DEBUG"/>
    <logger name="org.springframework" level="INFO"/>
    <logger name="org.hibernate" level="WARN"/>
​
    <!-- 将日志输出到控制台和文件 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

Profiles环境隔离

配置文件:

  • application-{profile}.properties 可以作为指定环境的配置文件,激活这个环境,配置就会生效。最终生效的所有配置是

    • application.properties:主配置文件,任意时候都生效

    • application-{profile}.properties:指定环境配置文件,激活指定环境生效

环境隔离能力:快速切换开发(dev)、测试(test)、生产环境(prod)

步骤:

  1. 标识环境:指定哪些组件、配置在哪个环境生效@Profile 标记组件生效环境。例如@Profile ("dev")标识该组件在dev开发环境下才会生效。

  2. 切换环境:这个环境对应的所有组件和配置就应该生效

    • 激活环境:

      • 配置文件:spring.profiles.active=dev

      • 命令行:java -jar demo.jar --spring.profiles.active=dev,prod

    • 环境包含:

      • spring.profiles.include[0]=common

      • spring.profiles.include[1]=local

    • 生效的配置 = 默认环境配置 + 激活的环境 + 包含的环境配置

  3. 项目里面这么用

    • 基础的配置mybatis、log、xxx:写到包含环境中

    • 需要动态切换变化的 db、redis:写到激活的环境中

  4. Profiles也可以进行分组激活:spring.profiles.group.groupname[0]=dev。给组中添加需要激活的配置成员,可以进行统一激活处理

注意:激活配置的优先级大于默认配置

外部化配置

在boot项目被打成jar包后可以放在不同的服务器上运行,但是想要修改其中的配置文件需要打开项目,对配置文件进行修改后,再又打成jar包运行,这样即耗时又费力。外部化配置有效解决的这个问题,你可以直接在项目所在的文件夹中直接声明配置文件,再在配置文件中对想要修改的配置进行覆盖重写。外部化配置文件中有一定的优先级策略,离项目越远的配置文件生效的优先级越高吗,这就是所谓的外部优先策略。当外部优先策略与激活优先策略发生冲突时要以激活优先策略为主。

单元测试进阶

@Test :表示方法是测试方法。

@ParameterizedTest :表示方法是参数化测试,下方会有详细介绍

@RepeatedTest :表示方法可重复执行,下方会有详细介绍

@DisplayName :为测试类或者测试方法设置展示名称(在控制台显示)

@BeforeEach :表示在每个单元测试之前执行

@AfterEach :表示在每个单元测试之后执行

@BeforeAll :表示在所有单元测试之前执行

@AfterAll :表示在所有单元测试之后执行

@Tag :表示单元测试类别,类似于JUnit4中的@Categories

@Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore

@Timeout :表示测试方法运行如果超过了指定时间将会返回错误

@ExtendWith :为测试类或测试方法提供扩展类引用

断言机制

在 Spring Boot 单元测试中,断言机制是验证代码行为是否符合预期的重要工具。Spring Boot 提供了多种断言库,如 JUnit 的 Assertions、Hamcrest 的 Matchers 和 AssertJ 的 Assertions。

@SpringBootTest
public class AssertTest {
​
    @Autowired
    private HelloService helloService;
​
    @Test
    @DisplayName("断言测试1")
    public void test1(){
​
        // 断言测试1
        String  hello=helloService.sayHello();
        //断言判断
        Assertions.assertEquals("Hello, Spring Boot!", hello);
    }
}
​

可观测性

可观测性(Observability)指应用的运行数据,可以被线上进行观测、监控、预警等。为后面的微服务开发中的监控(链路追踪)框架做铺垫,Spring Boot的可观测性自带底层的监控特性,为后面发展成UI界面提供方便

SpringBoot 提供了 actuator 模块,可以快速暴露应用的所有指标。首先要导入: spring-boot-starter-actuator场景依赖。然后修改配置文件,以web的形式暴露出想要观测的指标。最后启动项目后访问 http://localhost:8080/actuator地址;就可以展示出所有可以用的监控端点,以及系统的健康情况。

#以web的形式暴露所有的端点
management.endpoints.web.exposure.include=*

生命周期

监听器

/**
 * 监听到SpringBoot启动的全生命周期,选择对应的监听器并继承
 */
@Slf4j
public class MyListener implements SpringApplicationRunListener {
​
    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) {
        System.out.println("MyListener...starting...");
    }
​
    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) {
        log.info("MyListener...started...");
    }
​
    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
        log.info("MyListener...ready...");
    }
​
    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        log.info("MyListener...failed...");
    }
​
    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
        log.info("MyListener...environmentPrepared...");
    }
​
    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        log.info("MyListener...contextLoaded...");
    }
​
    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        log.info("MyListener...contextPrepared...");
    }
}

#配置监听器到项目中
org.springframework.boot.SpringApplicationRunListener=com.atguigu.boot.listener.MyListener

事件

事件VS监听器

事件驱动开发

SpringBoot的事件发送和感知不仅是用于Spring的生命周期,还能通过在项目中手动发出自定义的事件,然后利用自动感知来自动触发一些功能(比如用户登录自动签到,就可以在登录的Service中发出登录事件,签到功能被自动触发);

这就是事件驱动开发模式(自定义事件以驱动程序开发),在功能自动化的同时能对代码解耦,是一种较高效的模式

流程:

1.定义事件:

  • 任意事件:任意类可以作为事件类,建议命名 xxxEvent,其中设置好需要属性,然后使用构造器接收事件发来的参数

  • 系统事件:继承 ApplicationEvent

2.事件发布:

  • 组件实现 ApplicationEventPublisherAware

  • 自动注入 ApplicationEventPublisher publisher

  • 发送:publisher.publishEvent(【造好的事件类实例】)

3.事件监听:

  • 组件类中,给方法标注@EventListener(【要监听的事件】.class)

自定义stater

我们导入MVC、JDBC等等时本质上是导入了一种依赖场景,同理,我们可以自定义一个starter项目作为其他项目依赖的功能模块。作为一个stater项目,就要有一些基础的抽取。

  • 创建自定义starter项目,引入spring-boot-starter基础依赖

  • 编写模块功能,引入模块所有需要的依赖。

  • 编写xxxAutoConfiguration自动配置类,帮其他项目导入这个模块需要的所有组件

如上述,我们完成自定义stater的编写后,我们项目导入自定义的场景启动器之后,实际上还是无法使用stater功能。因为starter中的实现功能的种种组件没有进入IOC容器,为此我们要就这些功能统统配置到外部项目。

原因:SpingBoot项目,默认情况下只会扫描主程序所在的包以及它的子包,就算自定义stater中有@Component注解标识,也无法加入到IOC容器里面进行管理。

  1. 第一层抽取:编写一个自动配置类,别人导入我的stater,无需关心需要给容器中导入哪些组件,只需要导入自动配置类,自动配置类会帮你导入这个场景所需要的所有组件。

  2. 第二层抽取:编写@EnableXxx 注解,仿照比如开启异步@EnableAsync 编写,并在该注解类上标识@Import 导入配置类

  3. 第三层抽取:只要导入依赖就能自动配置好

    • 在starter的resources 目录下创建META-INF.spring 目录

    • 在META-INF.spring 目录下创建org.springframework.boot.autoconfigure.imports 文件

    • 在org.springframework.boot.autoconfigure.imports 文件下写好配置类的全类名写好


网站公告

今日签到

点亮在社区的每一天
去签到