SpringBoot3——基础特性

server/2024/12/26 17:12:01/
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/server/153385.html

相关文章

CSharp: Oracle Stored Procedure query table

存储过程查询postgreSQL,Oracle 和sql server,Mysql 有区别。程序调用也是有区别。 oracle sql script: CREATE OR REPLACE PROCEDURE procSelectSchool(paramSchoolId IN char,p_cursor OUT SYS_REFCURSOR ) AS BEGINOPEN p_cursor FORSELECT *FROM SchoolWHERE SchoolId p…

给bmp和png,设置BLENDFUNCTION的AlphaFormat不同参数的效果

BLENDFUNCTION是AlphaBlend用控制透明效果的重要参数。 选择一个32位的png图片&#xff0c;设置AlphaFormat 为 AC_SRC_ALPHA&#xff0c;效果如上图。 选择一个32位的png图片&#xff0c;设置AlphaFormat 为 0&#xff0c;效果如上图。 选择一个24位的bmp图片&#xff0c;设置…

Linux嵌入式系统利用套接字编程(Socket Programming)实现网络通信的基础知识并附对一个简单实例的分析

目录 套接字编程的简介套接字的基本概念套接字编程的特点套接字编程的主要步骤**服务端工作流程**&#xff1a;**客户端工作流程**&#xff1a; 服务端代码(使用 TCP 协议)示例代码及分析服务端(使用 TCP 协议)的源代码代码int server_fd, new_socket;分析(int server_fd、new_…

一、后端到摄像头(监控摄像头IOT)

前言&#xff1a; 开发流程从 后端到摄像头 打通是第一步&#xff0c;那么我们可以着手设计 后端实现 的具体步骤&#xff0c;确保能够稳定地接收和处理来自摄像头的视频流&#xff0c;并提供后续的功能扩展&#xff0c;如视频流转发、存储和控制。 1. 后端系统架构设计 在开始…

科技赋能医疗挂号:SSM 医院预约挂号系统的 Vue 卓越设计与达成

3系统分析 3.1可行性分析 通过对本医院预约挂号系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本医院预约挂号系统采用SSM框架&#xff0c;JAVA作为开发语…

Android简洁缩放Matrix实现图像马赛克,Kotlin

Android简洁缩放Matrix实现图像马赛克&#xff0c;Kotlin 原理&#xff0c;通过Matrix把一个原图缩小到原先的1/n&#xff0c;然后再把缩小后的小图放大n倍&#xff0c;自然就是马赛克效果&#xff08;相当于是放大后像素“糊”成一片了&#xff09;。 import android.content.…

React State(状态)

React State(状态) 引言 在React的世界里&#xff0c;状态&#xff08;State&#xff09;是一个核心概念&#xff0c;它允许我们创建动态和交互式的用户界面。状态是React组件内部数据的存储机制&#xff0c;当状态发生变化时&#xff0c;React会自动重新渲染组件&#xff0c…

RabbitMQ概述

目录 RabbitMQ概述 前言 MQ MQ的作用 为什么选择RabbitMQ RabbitMQ的介绍 RabbitMQ概述 前言 Rabbit, 兔⼦的意思 互联⽹⾏业很多公司, 都喜欢⽤动物命名产品, 或者作为公司的logo, 吉祥物. ⽐如: 腾讯的企鹅, 京东的狗, 美团的袋⿏, 携程的海豚,阿⾥就更多了, 蚂蚁, ⻜…