SpringBoot3框架,基础特性

MyBatis整合

导入MyBatis整合的依赖:

<!-- <https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter> -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

在使用Spring Initialzr时,额外勾选到MyBatis Framework和MySql Driver即可

MyBatis整合

  1. 写好相应的mapper接口和mapper.xml文件后,在启动类上加上@MapperScan注解,在其中的basePackages属性指定要扫描的包的全限定符即可

    @SpringBootApplication
    @MapperScan(basePackages = "com.ergou.boot3.ssm.mapper")
    public class Boot305SsmApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(Boot305SsmApplication.class, args);
        }
    
    }
    
  2. 使用mybatis.mapper-locations指定每个mapper接口对应的xml文件在哪里,mybatis就会自动关联绑定(mapper接口的接口名和mapper.xml文件的文件名一致才会关联),例:

    mybatis.mapper-locations=classpath:/mapper/*.xml
    
  3. 最后可以在配置文件中进行mybatis的一些额外配置,比如字段驼峰映射、类全限定符映射等

自动配置分析

  • DataSourceAutoConfiguration配置了数据源等基本信息,会自动配置数据源(和数据源相关的配置都绑定在DataSourceProperties)
    • 导入了jdbc的场景,给jdbcTemplate导入了dataSource的信息
    • 导入了和事务有关的数据源,支持了事务
  • MyBatisAutoConfiguration配置了MyBatis的整合流程(和MyBatis相关的配置绑定在MybatisProperties)
    • 给容器中准备了SqlSessionFactory等组件,以操作数据库
    • 在数据源配置好后再配置mybatis
  • MapperScan原理:利用Import(MapperScannerRegistrar.class)批量给容器中注册组件。解析指定包中的mapper接口,为其每一个mapper接口创建bean定义信息,注册到容器中

SpringBoot3基础特性

自定义banner

banner就是springboot启动时在控制台上出现的那个由字符拼接成的那个spring图标

自定义banner:

  • 在配置文件中的spring.banner.location属性指定其classpath,在项目下放一个banner的文本图标的文件,然后写在classpath:后即可

自定义SpringApplication

可以在SpringApplication的run操作前,插入一些自定义设置(这些设置在配置文件中也可以起作用)

@SpringBootApplication
public class Boot306FeaturesApplication {

    public static void main(String[] args) {
		//可以拆分springApplication的run操作,在中间插入自定义的底层设置
		SpringApplication springApplication = new SpringApplication(Boot306FeaturesApplication.class);
		//例:设置banner的模式
		springApplication.setBannerMode(Banner.Mode.CONSOLE);
		//        SpringApplication运行起来
		springApplication.run(args);
    }
}

还可以通过SpringApplicationBuilder:

@SpringBootApplication
public class Boot306FeaturesApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder().main(Boot306FeaturesApplication.class)
				        .sources(Boot306FeaturesApplication.class)
                .bannerMode(Banner.Mode.CONSOLE)
                .listeners(……).run(args);
    }

}

但是:配置文件的的优先级高于程序化调整的优先级

Profiles

指定环境

  • Spring Profiles 提供一种隔离配置的方式,使其仅在特定环境生效;
    • 环境:dev(开发环境)、test(测试环境)、prod(生产环境)
    • 默认环境:default,即在所有环境都生效。未标注@Profile,即为default环境。
  • 任何@Component, @Configuration 或 @ConfigurationProperties 可以使用 @Profile 标记,来指定何时被加载。【容器中的组件都可以被 @Profile标记】
  • 在@Profile注解的value属性中指定要生效的环境即可(value是Stirng类型的数组,可以指定多个环境)

激活环境

  • 通过配置文件激活
spring.profiles.active=dev
  • 也可以使用命令行激活,在使用命令行运行时加上--spring.profiles.active=dev
  • 还可以配置默认环境; 不标注@Profile 的组件永远都存在。以前默认环境叫default,使用spring.profiles.default=test 配置后,默认环境为test
  • 不推荐使用修改默认环境,建议配置active激活环境
  • 还可以使用包含环境
    • 配置spring.profiles.include=环境1,环境2。则环境1和环境总是激活
  • 用法:
    • 基础的配置mybatislogxxx:写到包含环境中
    • 需要动态切换变化的 dbredis:写到激活的环境中

环境分组

可以使用 spring.profiles.group.组名 对多个环境进行分组,再对组进行active激活,就可以激活组中的相应的多个环境

spring.profiles.group.aaaa=dev,test
spring.profiles.active=aaaa

Profile配置文件

  • application.properties是主配置文件,在任何情况下都生效。
  • 可以使用application-环境标识.properties配置文件(例如:application-dev.properties、application-test.properties等)
  • 指定Profile配置文件只会在其特定环境下生效
  • 如果Profile配置文件中的配置和主配置文件中的配置有冲突,则以Profile配置文件的配置为优先
  • spring.profiles.active 和spring.profiles.default 只能用到非Profile配置文件中,如果在application-dev.yaml中编写就是无效的

外部化配置

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

配置优先级

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

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

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

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

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

结论:配置可以写到很多位置,常见的优先级顺序:

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

配置文件的优先级:(由低到高)

  1. jar 包内的application.properties/yml
  2. jar 包内的application-{profile}.properties/yml(Profile配置文件)
  3. jar 包外的application.properties/yml
  4. jar 包外的application-{profile}.properties/yml(Profile配置文件)

即:包外大于包内,Profile配置文件大于主配置文件

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

  1. 类路径: 内部
    1. 类根路径
    2. 类下/config包
  2. 当前路径(项目所在的位置)
    1. 当前路径
    2. 当前下/config子目录
    3. /config目录的直接子目录

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

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

配置的优先级规律:最外层的最优先。

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

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

导入配置

使用spring.config.import属性可以导入额外配置文件中的配置,属性值写其他配置文件的文件名即可

spring.config.import=classpath:/xxxx.properties

例:

application.properties内容如下: spring.config.import=classpath:/abc.properties server.port=8888

abc.properties内如如下: server.port=8889

结论:服务端口是8889

属性占位符

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

app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}

:后表示默认值,以上为例,如果找不到username,则${username:Unknown}的结果为Unknown

单元测试

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

相关注解:

@SpringBootTest

  • 在测试类上加上@SpringBootTest注解后,测试方法运行时,会启动boot项目测试。
  • 加上@SpringBootTest后,在测试类中,可以使用整个项目中的组件,只要在测试类中进行使用@Autowired注解进行组件注入即可

@Test

表示该方法是测试方法

@DisplayName

给测试方法命名其展示的测试名

@BeforeAll

标注了BeforeAll注解的方法,所有测试方法在运行之前,先运行此方法

@BeforeEach

标注了BeforeEach的方法,每个测试方法运行之前,先运行此方法

@AfterAll、@AfterEach

和BeforeAll和BeforeEach类似,将之前改为之后即可

断言

测试时可以使用断言,来进行一些判断

与断言有关的方法如下:

方法说明
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 {

        @BeforeEach
        void 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";

            @BeforeEach
            void 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");//返回一个流
}

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二狗mao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值