SpringBoot3——基础特性

embedded/2024/12/27 2:15:44/
htmledit_views">

SpringApplication

自定义banner

  • 类路径添加banner.txt或设置spring.banner.location就可以定制banner
  • 推荐网站:Spring Boot banner 在线生成工具,制作下载英文 banner.txt,修改替换 banner.txt 文字实现自定义,个性化启动 banner-bootschool.net

自定义SpringApplication

package com.ling.boot3.features;import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;@SpringBootApplication // 由这个注解来标注主程序类
public class Boot306FeaturesApplication {public static void main(String[] args) {// SpringApplication —— 整个Boot应用的核心API入口
//		SpringApplication.run(Boot306FeaturesApplication.class, args);// 1. 若是跟下面一样拆成两个部分的话,我们就可以自定义Spring应用SpringApplication springApplication = new SpringApplication(Boot306FeaturesApplication.class);// 程序化调整【调整SpringApplication的参数】
//		springApplication.setDefaultProperties();// 如果配置文件也配置了这个属性,以配置文件为准springApplication.setBannerMode(Banner.Mode.CONSOLE);// 【配置文件的优先级高于程序化调整】// 2. SpringApplication运行起来springApplication.run(args);}}

FluentBuilder API

package com.ling.boot3.features;import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;@SpringBootApplication // 由这个注解来标注主程序类
public class Boot306FeaturesApplication {public static void main(String[] args) {// SpringApplication —— 整个Boot应用的核心API入口
//		SpringApplication.run(Boot306FeaturesApplication.class, args);// Builder 方式构建 SpringApplication —— 通过FluentAPI进行设置new SpringApplicationBuilder().main(Boot306FeaturesApplication.class).sources(Boot306FeaturesApplication.class).bannerMode(Banner.Mode.OFF)
//				.environment(null)
//				.listeners(null).run(args);}
}

Profiles

环境隔离能力:快速切换开发、测试、生产环境

步骤:

  • 标识环境:能够指定哪些组件或者哪些配置能够在哪个环境中生效
  • 切换环境:切换环境后,这个环境对应的所有组件和配置就应该生效

使用

指定环境

Spring Profiles提供一种隔离配置的方法,十七仅在特定环境生效

任何@Component,@Configuration或者@ConfigurationProperties可以使用@Profile标记,来指定何时被加载。【容器中的组件都可以被@Profile标记】

环境激活

  • 通过配置文件激活指定环境
spring.profiles.active=prod,dev
  • 也可以使用命令行激活  --spring.profiles,active=dev
  • 还可以配置默认环境:不标注@Profile的组件永远都存在
    • 以前默认环境叫default
    • spring.peofiles.default=test
  • 推荐使用激活方式激活指定环境

环境包含

注意:

spring.profiles,activespring.profiles.default只能用到无profile的文件中,如果在application-dev.yaml中编写就是无效的

也可以额外添加生效文件,而不是激活替换。比如:

spring.profiles.include[0]=common
spring.profiles.include[1]=local# 也可以直接写
spring.profiles.include=common,local

最佳实战:

  • 生效的环境 = 激活的环境 + 默认的环境 + 包含的环境
  • 项目里面这么用
    • 基础的配置mybatislogxxx:写到包含环境中
    • 需要动态切换变化的dbredis:写到激活的环境中

Profile分组

创建haha组,指定包含db和mq配置

spring.profiles.group.haha=db,mq# 也可以拆开来写
spring.profiles.group[0]=db
spring.profiles.group[1]=mq

使用 --spring.profiles.active=haha,就会激活db、ma配置文件

Profile配置文件

  • application-{profile}.properties 可以作为指定环境的配置文件
  • 激活这个环境,配置就会生效。最生效的所有配置
    • application-{profile}.properties中的所有配置
    • 以及
    • application.properties中的没有与application-{profile}.properties中的配置冲突的配置项

/*** 1. 标识环境*    1)、区分出几个环境: dev(开发环境)  test(测试环境)  prod(生产环境)*    2)、指定哪个组件能够在哪个环境中生效  默认环境 —— default*       通过@Profile()注解指定在哪个环境下生效*       如果组件没有标注@Profile注解,则代表任意时候都生效*    3)、默认只有激活指定的环境,这些组件才会生效* 2. 激活环境*    配置文件激活:spring.profiles.active=dev*    命令行激活: java -jar xxx.jar --spring.profiles.active=dev* 3. 配置文件怎么使用Profile功能*    1)、application.properties:主配置文件,任何情况下都生效*    2)、其他Profile环境下命名规范:application-{profile标识}.properties*        比如:*           application-dev.properties*    3)、激活指定环境即可: 配置文件激活  命令行激活*    4)、效果:*        项目的所有生效配置项 = 激活环境的配置文件的所有配置项 + 主配置文件和激活文件不冲突的所有配置项*        如果发生了冲突,以激活环境的配置文件为准*        application-{profile标识}.properties 的优先级大于 application.properties**     主配置和激活的配置都生效,但是以激活的配置为准*/

外部化配置

场景:线上应用如何快速修改配置,并应用最新配置

  • SpringBoot使用 配置优先级 + 外部配置 简化配置、简化运维
  • 只需要给 jar 应用所在的文件夹放一个 application.properties 最新配置文件,重启项目就能自动应用最新配置

配置优先级

Spring Boot 允许将配置外部化,以便可以在不同的环境中使用相同的应用程序代码。

我们可以使用各种外部配置源,包括 Java Properties 文件、YAML 文件、环境变量和命令行参数。

@Value 可以获取值,也可以用 @ConfigurationProperties 将所有属性绑定到 java object 中

以下是 SpringBoot 属性源加载顺序后面的会覆盖前面的值,由低到高,高优先级配置覆盖低优先级

  • 默认属性(通过 SpringApplication.setDefaultPropertie 指定的)
  • @PropertySource 指定加载的配置(需要写在 @Configuration 类上才可生效)
  • 配置文件(application.properties/yml等)
  • RandomValuePropertySource 支持的 random.* 配置(如:@Value("${random.int}"))
  • OS 环境变量
  • Java 系统属性( System.getProperties() )
  • JNDI 属性(来自 java:comp/env )
  • ServletContext 初始化参数
  • ServletConfig 初始化参数
  • SPRING_APPLICATION_JSON属性(内置在环境变量或系统属性中的 JSON)
  • 命令行参数
  • 测试属性。( @SpringBootTest 进行测试时指定的属性)
  • 测试类 @TestPropertySource 注解
  • Devtools 设置的全局属性。( $HOME/.config/spring-boot )

结论:配置可以写道很多未知,常见的优先级顺序:

  • 命令行 > 配置文件 > SpringApplication配置

配置文件优先级如下:(后面覆盖前面

  • jar包内的 application.properties/yml
  • jar包内的application-{profile}.properties/yml
  • jar包外的 application.properties/yml
  • jar包外的application-{profile}.properties/yml

建议:用一种格式的配置文件。如果.properties 和 .yml 同时存在,则 .properties 优先

结论:包外  > 包内;同级情况:profile配置 > application配置

所有参数均可由命令行传入,使用 -- 参数想=参数值,将会被添加到环境变量中,并优先于配置文件

比如 java -jar app.jar --name="Spring",可以使用 @Value("${name}")获取

演示场景:

  • 包内: application.properties    server.port=8000
  • 包内: application-dev.properties    server.port=9000
  • 包外: application.properties    server.port=800
  • 包外: application-dev.properties    server.port=9001

启动端口:命令行 > 9001 > 8001 > 9000 > 8000

外部配置

SpringBoot 应用启动时会自动寻找 application.propertiesapplication.yaml 位置,进行加载。顺序如下:(后面覆盖前面)

  • 类路径:内部
    • 类根路径
    • 类下 /config
  • 当前路径(项目所在的位置):外部
    • 当前路径
    • 当前路径下 /config 子目录
    • /config 目录的直接子目录

最终效果:优先级由高到低,前面覆盖后面

  • 命令行 > 包外config直接子目录 > 包外config目录 > 包外根目录 > 包内目录
  • 同级比较:
    • profile配置 > 默认配置
    • properties配置 > yaml配置

规律:最外层的最优先

  • 命令行 > 所有
  • 包外 > 包内
  • config目录 > 根目录
  • profile > application

配置不同就都生效(互补),配置相同高优先级覆盖低优先级

导入配置

使用 spring.config.import 可以导入额外配置

spring.config.import=my.properties
my.property=value

无论以上写法的先后顺序,my.properties 的值总是优先于直接在文件中编写的 my.properties

属性占位符

配置文件中可以使用 ${name:default} 形式取出之前配置过的值。

  • 冒号后面的值就是默认值,在系统知道不到对应的值之后会显示该默认值
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}

单元测试-Junit5

整合

SpringBoot提供一些列测试工具集及注解方便我们进行测试

spring-boot-test 提供核心测试呢管理,spring-boot-test-autoconfigure 提供测试的一些自动配置

我们只需要导入 spring-boot-starter-test 即可整合测试

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

spring-boot-starter-test 默认提供了以下库供我们测试使用

  • JUnit 5
  • Spring Test
  • AssertJ
  • Hamcrest
  • Mockito
  • JSONassert
  • JsonPath

测试

组件测试

JUnit5的注解与JUnit4的注解有所变化

JUnit 5 User Guidehtml/release2.3.7/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=O83A" alt="icon-default.png?t=O83A" />https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

  • @Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
  • @ParameterizedTest :表示方法是参数化测试,下方会有详细介绍
  • @RepeatedTest :表示方法可重复执行,下方会有详细介绍
  • @DisplayName :为测试类或者测试方法设置展示名称
  • @BeforeEach :表示在每个单元测试之前执行
  • @AfterEach :表示在每个单元测试之后执行
  • @BeforeAll :表示在所有单元测试之前执行
  • @AfterAll :表示在所有单元测试之后执行
  • @Tag :表示单元测试类别,类似于JUnit4中的@Categories
  • @Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
  • @Timeout :表示测试方法运行如果超过了指定时间将会返回错误
  • @ExtendWith :为测试类或测试方法提供扩展类引用
     
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;class StandardTests {@BeforeAll  // 所有测试方法运行之前先运行这个  只打印一次static void initAll() {}@BeforeEach  // 每个测试方法运行之前先运行这个  每个方法打印一次void init() {}@DisplayName("😱")  // 给该测试方法命名@Testvoid succeedingTest() {}@Testvoid failingTest() {fail("a failing test");}@Test@Disabled("for demonstration purposes")void skippedTest() {// not executed}@Testvoid abortedTest() {assumeTrue("abc".contains("Z"));fail("test should have been aborted");}@AfterEachvoid tearDown() {}@AfterAllstatic void tearDownAll() {}}

断言

方法

说明

assertEquals

判断两个对象或两个原始类型是否相等

assertNotEquals

判断两个对象或两个原始类型是否不相等

assertSame

判断两个对象引用是否指向同一个对象

assertNotSame

判断两个对象引用是否指向不同的对象

assertTrue

判断给定的布尔值是否为 true

assertFalse

判断给定的布尔值是否为 false

assertNull

判断给定的对象引用是否为 null

assertNotNull

判断给定的对象引用是否不为 null

assertArrayEquals

数组断言

assertAll

组合断言

assertThrows

异常断言

assertTimeout

超时断言

fail

快速失败

嵌套测试

JUnit 5 可以通过 Java 中的内部类和 @Nested 注解实现嵌套测试,从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用 @BeforeEach 和 @AfterEach 注解,而且嵌套的层次没有限制。

@DisplayName("A stack")
class TestingAStackDemo {Stack<Object> stack;@Test@DisplayName("is instantiated with new Stack()")void isInstantiatedWithNew() {new Stack<>();}@Nested@DisplayName("when new")class WhenNew {@BeforeEachvoid createNewStack() {stack = new Stack<>();}@Test@DisplayName("is empty")void isEmpty() {assertTrue(stack.isEmpty());}@Test@DisplayName("throws EmptyStackException when popped")void throwsExceptionWhenPopped() {assertThrows(EmptyStackException.class, stack::pop);}@Test@DisplayName("throws EmptyStackException when peeked")void throwsExceptionWhenPeeked() {assertThrows(EmptyStackException.class, stack::peek);}@Nested@DisplayName("after pushing an element")class AfterPushing {String anElement = "an element";@BeforeEachvoid pushAnElement() {stack.push(anElement);}@Test@DisplayName("it is no longer empty")void isNotEmpty() {assertFalse(stack.isEmpty());}@Test@DisplayName("returns the element when popped and is empty")void returnElementWhenPopped() {assertEquals(anElement, stack.pop());assertTrue(stack.isEmpty());}@Test@DisplayName("returns the element when peeked but remains not empty")void returnElementWhenPeeked() {assertEquals(anElement, stack.peek());assertFalse(stack.isEmpty());}}}
}

参数化测试

参数化测试是JUnit5很重要的一个新特性,它使得用不同的参数多次运行测试成为了可能,也为我们的单元测试带来许多便利。

利用@ValueSource等注解,指定入参,我们将可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。

@ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型

@NullSource: 表示为参数化测试提供一个null的入参

@EnumSource: 表示为参数化测试提供一个枚举入参

@CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参

@MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)

@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("参数化测试1")
public void parameterizedTest1(String string) {System.out.println(string);Assertions.assertTrue(StringUtils.isNotBlank(string));
}@ParameterizedTest
@MethodSource("method")    //指定方法名
@DisplayName("方法来源参数")
public void testWithExplicitLocalMethodSource(String name) {System.out.println(name);Assertions.assertNotNull(name);
}static Stream<String> method() {return Stream.of("apple", "banana");
}

http://www.ppmy.cn/embedded/149058.html

相关文章

【Spring】Spring的模块架构与生态圈—Spring Boot、Spring Cloud与Spring Security

随着互联网的发展&#xff0c;企业对快速开发和高可用性的需求不断增加&#xff0c;Spring生态系统&#xff08;包括Spring Boot、Spring Cloud和Spring Security&#xff09;应运而生&#xff0c;为Java开发提供了强大的支持。 在实际应用中&#xff0c;Spring Boot使得开发者…

【git】git命令

目录 1. 在当前目录下创建一个新的git仓库2. 克隆一个远程仓库到本地3. 显示工作目录和暂存区的状态4. 将文件添加到暂存区&#xff0c;准备提交5. 将暂存区的文件提交到本地仓库6. 显示提交历史记录7.版本回退8.查所有操作记录(包括删除记录)9.添加文件到忽略列表10.列出所有本…

【理解机器学习中的过拟合与欠拟合】

在机器学习中&#xff0c;模型的表现很大程度上取决于我们如何平衡“过拟合”和“欠拟合”。本文通过理论介绍和代码演示&#xff0c;详细解析过拟合与欠拟合现象&#xff0c;并提出应对策略。主要内容如下&#xff1a; 什么是过拟合和欠拟合&#xff1f; 如何防止过拟合和欠拟…

运动控制卡网络通讯的心跳检测之C#上位机编程

本文导读 今天&#xff0c;正运动小助手给大家分享一下如何使用C#上位机编程实现运动控制卡网络通讯的心跳检测功能。 01 ECI2618B硬件介绍 ECI2618B经济型多轴运动控制卡是一款脉冲型、模块化的网络型运动控制卡。控制卡本身最多支持6轴&#xff0c;可扩展至12轴的运动控制…

芯科科技蓝牙、Wi-Fi、Wi-SUN产品广获业界认可,技术创新引领行业潮流

物联网领军企业领跑未来无线开发平台发展 2024年&#xff0c;Silicon Labs&#xff08;亦称“芯科科技“&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;在物联网&#xff08;IoT&#xff09;领域持续深耕&#xff0c;凭借创新的企业发展理念与实践、行业领先的技术与产品&am…

No.27 笔记 | RCE远程命令执行基础

一、RCE概述 &#xff08;一&#xff09;定义 RCE指攻击者可以通过远程方式在目标系统上执行恶意代码的漏洞或攻击技术&#xff0c;范围广泛&#xff0c;包括代码执行、文件包含、反序列化、命令执行、写文件Getshell等情况。 &#xff08;二&#xff09;危害 攻击者可继承…

云手机群控能用来做什么?

随着云手机的发展&#xff0c;云手机群控技术逐渐从小众的游戏多开工具&#xff0c;发展为涵盖多个领域的智能操作平台。不论是手游搬砖、短视频运营&#xff0c;还是账号养成等场景&#xff0c;云手机群控都展现出了强大的应用潜力。本文将为大家详细解析云手机群控的应用场景…

关于UDP缓冲区和丢包统计

Tunning and observing UDP buffers 调整和观察 UDP 缓冲区 UDP 缓冲区由 7 个 sysctl 参数控制。单个缓冲区的大小由以下参数控制&#xff1a; net.core.wmem_default、net.core.wmem_max&#xff1a; 控制套接字默认和最大发送缓冲区大小&#xff0c;单位为字节。 每个套…