文章目录
SpringBoot3-数据访问1.整合SSM场景1.1创建SSM整合项目1.2配置数据源1.3配置MyBatis1.4CRUD编写
2.自动配置原理3.扩展:整合其他数据源3.1 Druid 数据源
SpringBoot3-基础特性1. SpringApplication1.1 自定义 banner1.2.自定义 SpringApplication1.3FluentBuilder API
2.Profiles2.1 使用2.1.1 指定环境2.1.2 环境激活2.1.3 环境包含
2.2 Profile 分组2.3Profile 配置文件
3.外部化配置3.1 配置优先级3.2. 外部配置3.3. 导入配置3.4. 属性占位符
4. 单元测试-JUnit54.1 整合4.2测试4.2.0 组件测试4.2.1 注解4.2.2 断言4.2.3 嵌套测试4.2.4 参数化测试
学习视频:
尚硅谷SpringBoot3视频
SpringBoot3-数据访问
1.整合SSM场景
SpringBoot 整合 Spring、SpringMVC、MyBatis 进行数据访问场景开发
1.1创建SSM整合项目
勾选之后会导入以下包
1.2配置数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
安装MyBatisX 插件,帮我们生成Mapper接口的xml文件即可 在接口处 : Alt + 回车
1.3配置MyBatis
必须把mapper的xml文件映射位置在配置文件定义! 而驼峰命名转换建议也开启
#指定mapper映射文件位置
mybatis.mapper-locations=classpath:/mapper/*.xml
#驼峰命名转换
mybatis.configuration.map-underscore-to-camel-case=true
1.4CRUD编写
编写Bean
package com.atguigu.boot.ssm.bean;
import lombok.Data;
@Data
public class TUser {
private Integer id;
private String loginName;
private String nickName;
private String passwd;
}
编写Mapper
public interface UserMapper {
public TUser getUserById(@Param("id") Long id);
}
使用mybatisx插件,快速生成MapperXML
select * from t_user where id=#{id}
测试CRUD
UserController
@RestController
public class UserController {
@Autowired
UserMapper userMapper;
@GetMapping("/user/{id}")
public TUser getUser(@PathVariable("id") Long id){
TUser user = userMapper.getUserById(id);
return user;
}
}
/**
* 1.@MapperScan告诉Mybatis,扫描哪个包下面的所有接口
* 2.使用mybatis.mapper-locations 告诉mybatis,每个接口的xml文件都在哪里
*/
@MapperScan(basePackages = "com.atguigu.boot.ssm.mapper")
@SpringBootApplication
public class Boot05SsmApplication {
public static void main(String[] args) {
SpringApplication.run(Boot05SsmApplication.class, args);
}
}
运行结果:
2.自动配置原理
导入 mybatis-spring-boot-starter配置数据源信息配置mybatis的 mapper接口扫描 与 xml映射文件扫描编写bean,mapper,生成xml,编写sql 进行crud。事务等操作依然和Spring中用法一样效果: - 所有sql写在xml中 - 所有mybatis配置写在application.properties下面
jdbc场景的自动配置:
mybatis-spring-boot-starter导入 spring-boot-starter-jdbc,jdbc是操作数据库的场景 Jdbc场景的几个自动配置
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
数据源的自动配置所有和数据源有关的配置都绑定在DataSourceProperties默认使用 HikariDataSource org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
给容器中放了JdbcTemplate操作数据库 org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration
基于XA二阶提交协议的分布式事务数据源 org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
支持事务 具有的底层能力:数据源、JdbcTemplate、事务 MyBatisAutoConfiguration:配置了MyBatis的整合流程
mybatis-spring-boot-starter导入 mybatis-spring-boot-autoconfigure(mybatis的自动配置包), 默认加载两个自动配置类:
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
必须在数据源配置好之后才配置给容器中SqlSessionFactory组件。创建和数据库的一次会话给容器中SqlSessionTemplate组件。操作数据库 MyBatis的所有配置绑定在MybatisProperties 每个Mapper接口的代理对象是怎么创建放到容器中。详见**@MapperScan**原理:
利用@Import(MapperScannerRegistrar.class)批量给容器中注册组件。解析指定的包路径里面的每一个类,为每一个Mapper接口类,创建Bean定义信息,注册到容器中。
如何分析哪个场景导入以后,开启了哪些自动配置类。
找:classpath:/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中配置的所有值,就是要开启的自动配置类,但是每个类可能有条件注解,基于条件注解判断哪个自动配置类生效了。
快速定位生效的配置
#开启调试模式,详细打印开启了哪些自动配置
debug=true
# Positive(生效的自动配置) Negative(不生效的自动配置)
3.扩展:整合其他数据源
3.1 Druid 数据源
暂不支持 SpringBoot3
导入druid-starter写配置分析自动配置了哪些东西,怎么用
Druid官网
#数据源基本配置
spring.datasource.url=jdbc:mysql://192.168.200.100:3306/demo
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 配置StatFilter监控
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.db-type=mysql
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000
# 配置WallFilter防火墙
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.filter.wall.db-type=mysql
spring.datasource.druid.filter.wall.config.delete-allow=false
spring.datasource.druid.filter.wall.config.drop-table-allow=false
# 配置监控页,内置监控页面的首页是 /druid/index.html
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
spring.datasource.druid.stat-view-servlet.allow=*
# 其他 Filter 配置不再演示
# 目前为以下 Filter 提供了配置支持,请参考文档或者根据IDE提示(spring.datasource.druid.filter.*)进行配置。
# StatFilter
# WallFilter
# ConfigFilter
# EncodingConvertFilter
# Slf4jLogFilter
# Log4jFilter
# Log4j2Filter
# CommonsLogFilter
附录:示例数据库
CREATE DATABASE IF NOT EXISTS test;
USE test;
CREATE TABLE `t_user`
(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`login_name` VARCHAR(200) NULL DEFAULT NULL COMMENT '用户名称' COLLATE 'utf8_general_ci',
`nick_name` VARCHAR(200) NULL DEFAULT NULL COMMENT '用户昵称' COLLATE 'utf8_general_ci',
`passwd` VARCHAR(200) NULL DEFAULT NULL COMMENT '用户密码' COLLATE 'utf8_general_ci',
PRIMARY KEY (`id`)
);
insert into t_user(login_name, nick_name, passwd) VALUES ('zhangsan','张三','123456');
SpringBoot3-基础特性
1. SpringApplication
1.1 自定义 banner
类路径添加banner.txt或设置spring.banner.location就可以定制 banner
推荐网站:Spring Boot banner 在线生成工具,制作下载英文 banner.txt,修改替换 banner.txt 文字实现自定义,个性化启动 banner-bootschool.net
1.2.自定义 SpringApplication
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
//1.SpringApplication:Boot应用的核心API入口
//SpringApplication.run(Boot306FeaturesApplication.class,args);
//1.自定义SpringApplication的底层设置
SpringApplication application = new SpringApplication(MyApplication.class);
//程序化调整SpringApplication的参数
//application.setDefaultProperties();
//这个配置不优先
//2.调整SpringApplication的参数
application.setBannerMode(Banner.Mode.OFF);
//3.SpringApplication运行起来
application.run(args);
}
1.3FluentBuilder API
流式方式启动SpringApplication
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
2.Profiles
环境隔离能力;快速切换开发、测试、生产环境
步骤:
标识环境:指定哪些组件、配置在哪个环境生效切换环境:这个环境对应的所有组件和配置就应该生效
2.1 使用
2.1.1 指定环境
Spring Profiles 提供一种隔离配置的方式,使其仅在特定环境生效;任何@Component, @Configuration 或 @ConfigurationProperties 可以使用 @Profile 标记,来指定何时被加载。【容器中的组件都可以被 @Profile标记】
2.1.2 环境激活
1.配置激活指定环境; 配置文件
spring.profiles.active=production,hsqldb
2.也可以使用命令行激活。--spring.profiles.active=dev,hsqldb
3.还可以配置默认环境; 不标注@Profile 的组件永远都存在。
以前默认环境叫defaultspring.profiles.default=test
4.推荐使用激活方式激活指定环境
2.1.3 环境包含
注意:
spring.profiles.active 和spring.profiles.default 只能用到 无 profile 的文件中,如果在application-dev.yaml中编写就是无效的也可以额外添加生效文件,而不是激活替换。比如:
spring.profiles.include[0]=common
spring.profiles.include[1]=local
最佳实战:
生效的环境 = 激活的环境/默认环境 + 包含的环境 项目里面这么用
基础的配置mybatis、log、xxx:写到包含环境中需要动态切换变化的 db、redis:写到激活的环境中
2.2 Profile 分组
创建prod组,指定包含db和mq配置
spring.profiles.group.prod[0]=db
spring.profiles.group.prod[1]=mq
使用--spring.profiles.active=prod ,就会激活prod,db,mq配置文件
2.3Profile 配置文件
application-{profile}.properties可以作为指定环境的配置文件。 激活这个环境,配置就会生效。最终生效的所有配置是
application.properties:主配置文件,任意时候都生效application-{profile}.properties:指定环境配置文件,激活指定环境生效
如果发生配置冲突:profile优先级 > application
3.外部化配置
场景:线上应用如何快速修改配置,并应用最新配置?
SpringBoot 使用 配置优先级 + 外部配置 简化配置更新、简化运维。只需要给jar应用所在的文件夹放一个application.properties最新配置文件,重启项目就能自动应用最新配置
3.1 配置优先级
Spring Boot 允许将配置外部化,以便可以在不同的环境中使用相同的应用程序代码。
我们可以使用各种外部配置源,包括Java Properties文件、YAML文件、环境变量和命令行参数。
@Value可以获取值,也可以用@ConfigurationProperties将所有属性绑定到java object中
以下是 SpringBoot 属性源加载顺序。 后面的会覆盖前面的值。由低到高,高优先级配置覆盖低优先级
默认属性(通过SpringApplication.setDefaultProperties指定的)@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/ymljar 包内的application-{profile}.properties/ymljar 包外的application.properties/ymljar 包外的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=8001包外: application-dev.properties server.port=9001
启动端口?:命令行 > 9001 > 8001 > 9000 > 8000
3.2. 外部配置
SpringBoot 应用启动时会自动寻找application.properties和application.yaml位置,进行加载。顺序如下:(后面覆盖前面)
1.类路径: 内部
类根路径类下/config包
2.当前路径(项目所在的位置)
当前路径当前下/config子目录/config目录的直接子目录
最终效果:优先级由高到低,前面覆盖后面
命令行 > 包外config直接子目录 > 包外config目录 > 包外根目录 > 包内目录 同级比较:
profile配置 > 默认配置properties配置 > yaml配置
规律:最外层的最优先。
命令行 > 所有包外 > 包内config目录 > 根目录profile > application
配置不同就都生效(互补),配置相同高优先级覆盖低优先级
3.3. 导入配置
使用spring.config.import可以导入额外配置
spring.config.import=my.properties
my.property=value
无论以上写法的先后顺序,my.properties的值总是优先于直接在文件中编写的my.property。
3.4. 属性占位符
配置文件中可以使用 ${name:default}形式取出之前配置过的值。
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
4. 单元测试-JUnit5
4.1 整合
SpringBoot 提供一系列测试工具集及注解方便我们进行测试。
spring-boot-test提供核心测试能力,spring-boot-test-autoconfigure 提供测试的一些自动配置。
我们只需要导入spring-boot-starter-test 即可整合测试
spring-boot-starter-test 默认提供了以下库供我们测试使用
JUnit 5Spring TestAssertJHamcrestMockitoJSONassertJsonPath
4.2测试
4.2.0 组件测试
直接@Autowired容器中的组件进行测试
4.2.1 注解
JUnit5的注解与JUnit4的注解有所变化
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("")
@Test
void succeedingTest() {
}
@Test
void failingTest() {
fail("a failing test");
}
@Test
@Disabled("for demonstration purposes")
void skippedTest() {
// not executed
}
@Test
void abortedTest() {
assumeTrue("abc".contains("Z"));
fail("test should have been aborted");
}
@AfterEach
void tearDown() {
}
@AfterAll
static void tearDownAll() {
}
}
4.2.2 断言
方法说明assertEquals判断两个对象或两个原始类型是否相等assertNotEquals判断两个对象或两个原始类型是否不相等assertSame判断两个对象引用是否指向同一个对象assertNotSame判断两个对象引用是否指向不同的对象assertTrue判断给定的布尔值是否为 trueassertFalse判断给定的布尔值是否为 falseassertNull判断给定的对象引用是否为 nullassertNotNull判断给定的对象引用是否不为 nullassertArrayEquals数组断言assertAll组合断言assertThrows异常断言assertTimeout超时断言fail快速失败
4.2.3 嵌套测试
JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试,从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的层次没有限制。
@DisplayName("A stack")
class TestingAStackDemo {
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());
}
}
}
}
4.2.4 参数化测试
参数化测试是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
return Stream.of("apple", "banana");
}
好文推荐
发表评论