本文是 Spring Boot 第一天的学习笔记,涵盖 Spring Boot 简介、微服务架构、环境搭建、HelloWorld 入门、配置文件、YAML 语法以及自动配置原理等核心内容。适合 Spring Boot 初学者快速入门。
目录
- [一、Spring Boot 简介](#一、Spring Boot 简介)
- 二、微服务架构
- 三、环境准备
- [四、Spring Boot HelloWorld](#四、Spring Boot HelloWorld)
- [五、Hello World 探究](#五、Hello World 探究)
- [六、使用 Spring Initializer 快速创建项目](#六、使用 Spring Initializer 快速创建项目)
- 七、配置文件
- 八、自动配置原理
- 总结
一、Spring Boot 简介
Spring Boot 是简化 Spring 应用开发的一个框架,是整个 Spring 技术栈的大整合,也是 J2EE 开发的一站式解决方案。
Spring Boot 的优点:
- 快速创建独立运行的 Spring 项目以及与主流框架集成
- 使用嵌入式的 Servlet 容器,应用无需打成 war 包,内嵌 Tomcat
- Starters 自动依赖和版本控制
- 大量的自动装配,简化开发,也可以修改默认值
- 无需配置 XML,无代码生成,开箱即用
- 准生产环境的运行时应用监控
- 与云计算的天然集成
二、微服务架构
2.1 什么是微服务
微服务概念由 Martin Fowler 在 2014 年提出。微服务是一种架构风格(服务微化),指的是开发单个小型的但有业务功能的服务,每个服务都有自己处理和轻量通讯机制,可以部署在单个或多个服务器上。微服务也是一种松耦合的、有一定的有界上下文的面向服务架构。
核心理念: 一个应用应该是一组小型服务,可以通过 HTTP 的方式进行互通。
- 单体应用: ALL IN ONE
- 微服务: 每一个功能元素最终都是一个可独立替换和独立升级的软件单元
参考文档:https://martinfowler.com/articles/microservices.html#MicroservicesAndSoa
2.2 微服务的优点
- 每一个微服务都很小,能聚焦一个指定的业务功能或业务需求
- 微服务能够被小团队单独开发(2 到 5 人)
- 微服务是松耦合的,开发阶段和部署阶段都是独立的
- 微服务能够使用不同的语言开发
- 微服务允许容易且灵活的方式集成自动部署
- 微服务易于被开发人员理解、修改和维护
- 微服务能够即时被要求扩展
- 微服务能够部署在中低端配置的服务器上
- 易于和第三方集成
- 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一的数据库
2.3 微服务的缺点
- 微服务架构可能带来过多的操作
- 可能双倍的努力
- 分布式系统可能复杂难以管理
- 因为分布部署,跟踪问题难
- 当服务量增加,管理复杂性增加
三、环境准备
3.1 环境约束
- jdk1.8 :Spring Boot 推荐 jdk1.7 及以上,使用
java version "1.8.0_112" - maven3.x :maven 3.3 以上版本,使用
Apache Maven 3.3.9 - IntelliJ IDEA 2017:IntelliJ IDEA 2017.3.3 x64、STS
- SpringBoot 1.5.9.RELEASE:统一环境,对应 Spring 5
说明:单一 Spring Boot 项目不要求版本,但在 Spring Cloud 微服务治理时需要关注版本冲突问题。
3.2 Maven 设置
给 maven 的 settings.xml 配置文件的 profiles 标签添加以下内容:
xml
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
3.3 IDEA 设置
在 IDEA 中开启自动编译以及 Maven 集成配置,确保项目的编译环境与上述约束保持一致。
四、Spring Boot HelloWorld
需求: 浏览器发送 hello 请求,服务器接受请求并处理,响应 Hello World 字符串。
4.1 实现步骤
- 创建一个 maven 工程(jar 包形式)
- 导入 spring boot 相关的依赖
- 编写一个主程序,启动 Spring Boot 应用
- 编写相关的 Controller、Service
- 运行主程序测试
- 简化部署:将应用打成 jar 包,直接使用
java -jar命令执行
4.2 导入 Spring Boot 依赖
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
4.3 编写主程序
java
/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个 Spring Boot 应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
// Spring 应用启动起来
SpringApplication.run(HelloWorldMainApplication.class, args);
}
}
4.4 编写 Controller
java
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
}
4.5 简化部署
xml
<!-- 这个插件,可以将应用打包成一个可执行的 jar 包 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
执行 mvn package 后,使用 java -jar xxx.jar 即可运行应用。
五、Hello World 探究
5.1 POM 文件
5.1.1 父项目
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
它的父项目是:
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
spring-boot-dependencies 真正管理 Spring Boot 应用里面的所有依赖版本,是 Spring Boot 的版本仲裁中心。以后导入依赖默认不需要写版本号(没有在 dependencies 里面管理的依赖自然需要声明版本号)。
5.1.2 启动器
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- spring-boot-starter-web: spring-boot 场景启动器,帮我们导入了 web 模块正常运行所依赖的组件
- Spring Boot 将所有的功能场景都抽取出来,做成一个个的 starters(启动器)
- 只要在项目里面引入这些 starter,相关场景的所有依赖都会导入进来
- 要用什么功能就导入什么场景的启动器
5.2 主程序类(主入口类)
5.2.1 @SpringBootApplication
Spring Boot 应用标注在某个类上说明这个类是 SpringBoot 的主配置类,SpringBoot 就应该运行这个类的 main 方法来启动 SpringBoot 应用。
java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
// ...
}
5.2.2 @SpringBootConfiguration
Spring Boot 的配置类,标注在某个类上表示这是一个 Spring Boot 的配置类。其底层是 @Configuration,配置类也是容器中的一个组件(@Component)。
5.2.3 @EnableAutoConfiguration
开启自动配置功能。以前我们需要配置的东西,Spring Boot 帮我们自动配置,@EnableAutoConfiguration 告诉 SpringBoot 开启自动配置功能,这样自动配置才能生效。
java
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// ...
}
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class) 是 Spring 的底层注解,给容器中导入一个组件,将主配置类(@SpringBootApplication 标注的类)的所在包及下面所有子包里面的所有组件扫描到 Spring 容器。
@Import(EnableAutoConfigurationImportSelector.class)
给容器中导入组件的选择器,将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中。会给容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件。
5.3 自动配置加载机制
有了自动配置类,免去了我们手动编写配置注入功能组件等的工作。
SpringFactoriesLoader.loadFactoryNames()
↓
扫描所有 jar 包类路径下 META-INF/spring.factories
↓
把扫描到的这些文件的内容包装成 properties 对象
↓
从 properties 中获取到 EnableAutoConfiguration.class 类(类名)对应的值
↓
把他们添加在容器中
Spring Boot 在启动的时候从类路径下的 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。
J2EE 的整体整合解决方案和自动配置都在
spring-boot-autoconfigure-1.5.9.RELEASE.jar中。
六、使用 Spring Initializer 快速创建项目
IDE 都支持使用 Spring 的项目创建向导快速创建一个 Spring Boot 项目。
步骤:
- 选择我们需要的模块,向导会联网创建 Spring Boot 项目
- 默认生成的 Spring Boot 项目中主程序已经生成好了,只需要我们自己的逻辑
- resources 文件夹中目录结构:
- static: 保存所有的静态资源(js、css、images)
- templates: 保存所有的模板页面(Spring Boot 默认 jar 包使用嵌入式的 Tomcat,默认不支持 JSP 页面),可以使用模板引擎(freemarker、thymeleaf)
- application.properties: Spring Boot 应用的配置文件,可以修改一些默认设置
七、配置文件
7.1 Spring Boot 的热部署
Spring 为开发者提供了一个名为 spring-boot-devtools 的模块来使 Spring Boot 应用支持热部署,提高开发效率,无需手动重启 Spring Boot 应用。
引入依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
修改 java 代码或者配置文件模板后可以通过 Ctrl + F9 来实施热部署。
7.2 配置文件简介
SpringBoot 使用一个全局的配置文件,配置文件名是固定的:
application.propertiesapplication.yml
配置文件的作用:修改 SpringBoot 自动配置的默认值。SpringBoot 在底层都给我们自动配置好。
YAML(YAML Ain't Markup Language)
- YAML A Markup Language:是一个标记语言
- YAML isn't Markup Language:不是一个标记语言
以前的配置文件大多使用 xxxx.xml 文件,而 YAML 以数据为中心,比 json、xml 等更适合做配置文件。
7.3 YAML 语法
7.3.1 基本语法
k:(空格)v:表示一对键值对(空格必须有)- 以空格的缩进来控制层级关系,只要是左对齐的一列数据都是同一个层级的
- 属性和值也是大小写敏感
7.3.2 值的写法
字面量(普通的值:数字、字符串、布尔)
k: v:字面直接来写- 字符串默认不用加上单引号或者双引号
""双引号:不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思name: "zhangsan \n lisi"输出:zhangsan 换行 lisi
''单引号:会转义特殊字符,特殊字符最终只是一个普通的字符串数据name: 'zhangsan \n lisi'输出:zhangsan \n lisi
对象、Map(属性和值、键值对)
k: v:在下一行来写对象的属性和值的关系,注意缩进- 对象还是
k: v的方式
数组(List、Set)
用 - 值 表示数组中的一个元素:
yaml
pets:
- cat
- dog
- pig
行内写法:
yaml
pets: [cat, dog, pig]
7.4 配置文件值注入
我们可以导入配置文件处理器,以后编写配置就有提示了:
xml
<!-- 导入配置文件处理器,配置文件进行绑定就会有提示 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
注意: properties 配置文件在 IDEA 中默认 utf-8 可能会乱码。
7.4.1 @Value 与 @ConfigurationProperties 的比较
配置文件 yml 还是 properties 都能获取到值:
- 如果只是某个业务逻辑中需要获取一下配置文件中的某项值,使用
@Value - 如果专门编写了一个 javaBean 来和配置文件进行映射,使用
@ConfigurationProperties
7.4.2 @ConfigurationProperties 示例
java
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉 SpringBoot 将本类中的所有属性和配置文件中相关的配置进行绑定
* prefix = "person":配置文件中哪个下面的所有属性进行一一映射
*
* 只有这个组件是容器中的组件,才能容器提供的 @ConfigurationProperties 功能
* @ConfigurationProperties(prefix = "person") 默认从全局配置文件中获取值
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
// getter、setter 省略
}
7.5 配置文件注入值数据校验
java
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
// lastName 必须是邮箱格式
@Email
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String, Object> maps;
private List<Object> lists;
private Dog dog;
}
7.6 @PropertySource & @ImportResource & @Bean
@PropertySource: 加载指定的配置文件
java
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
// ...
}
@ImportResource: 导入 Spring 的配置文件,让配置文件里面的内容生效。
Spring Boot 里面没有 Spring 的配置文件,我们自己编写的配置文件也不能自动识别。想让 Spring 的配置文件生效,加载进来,使用 @ImportResource 标注在一个配置类上。
SpringBoot 推荐给容器中添加组件的方式:
- 配置类
@Configuration------> Spring 配置文件 - 使用
@Bean给容器中添加组件
java
/**
* @Configuration:指明当前类是一个配置类,就是来替代之前的 Spring 配置文件
* 在配置文件中用 <bean></bean> 标签添加组件
*/
@Configuration
public class MyAppConfig {
// 将方法的返回值添加到容器中;容器中这个组件默认的 id 就是方法名
@Bean
public HelloService helloService02() {
System.out.println("配置类 @Bean 给容器中添加组件了...");
return new HelloService();
}
}
7.7 配置文件占位符
7.7.1 随机数
properties
${random.value}
${random.int}
${random.long}
${random.int(10)}
${random.int[1024,65536]}
7.7.2 占位符获取之前配置的值
properties
person.last-name=张三${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
如果占位符找不到之前的值,可以使用
:hello指定默认值。
7.8 Profile
7.8.1 多 Profile 文件
在主配置文件编写时,文件名可以是 application-{profile}.properties/yml,默认使用 application.properties 的配置。
7.8.2 yml 支持多文档块方式
使用 --- 分隔不同的文档块,可以在不同块中指定不同的 profile。
7.8.3 激活指定 profile
- 在配置文件中指定:
spring.profiles.active=dev - 命令行:
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev - 测试时配置命令行参数: 可以直接在测试时传入
- 虚拟机参数:
-Dspring.profiles.active=dev
7.9 配置文件加载位置
SpringBoot 启动会扫描以下位置的 application.properties 或者 application.yml 文件作为默认配置文件:
file:./config/file:./classpath:/config/classpath:/
优先级由高到低,高优先级的配置会覆盖低优先级的配置。 SpringBoot 会从这四个位置全部加载主配置文件,形成互补配置。
例如,在 classpath:/ 的 application.properties 中加入:
properties
server.servlet.context-path=/boot3
7.10 外部配置加载顺序
SpringBoot 支持从多种位置加载配置,优先级从高到低,高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置:
- 命令行参数
- 所有配置都可以在命令行上指定
java -jar xxx.jar --server.port=8087 --server.context-path=/abcjava -jar xxx.jar --spring.config.location=C:/application.properties- 多个配置用空格分开:
--配置项=值
- 来自
java:comp/env的 JNDI 属性 - Java 系统属性(
System.getProperties()) - 操作系统环境变量
RandomValuePropertySource配置的random.*属性值
由 jar 包外向 jar 包内进行寻找,优先加载带 profile 的配置文件:
- jar 包外部的
application-{profile}.properties或application.yml(带 spring.profile) - jar 包内部的
application-{profile}.properties或application.yml(带 spring.profile)
再来加载不带 profile 的配置文件:
- jar 包外部的
application.properties或application.yml(不带 spring.profile) - jar 包内部的
application.properties或application.yml(不带 spring.profile) @Configuration注解类上的@PropertySource- 通过
SpringApplication.setDefaultProperties指定的默认属性
八、自动配置原理
8.1 自动配置核心流程
配置文件到底能写什么?怎么写?这就是自动配置原理要解决的问题。
- SpringBoot 启动时加载主配置类,开启了自动配置功能
@EnableAutoConfiguration @EnableAutoConfiguration利用EnableAutoConfigurationImportSelector给容器中导入一些组件- 查看方法内容,获取候选配置:
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes) - 将类路径下
META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到了容器中
每一个这样的 xxxAutoConfiguration 类都是容器中的一个组件,都加入到容器中,用它们来做自动配置。
8.2 以 HttpEncodingAutoConfiguration 为例
以 Http 编码自动配置为例解释自动配置原理:
java
@Configuration // 表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties(HttpEncodingProperties.class) // 启动指定类的 ConfigurationProperties 功能
@ConditionalOnWebApplication // 判断当前应用是否是 web 应用,如果是,当前配置类生效
@ConditionalOnClass(CharacterEncodingFilter.class) // 判断当前项目有没有 CharacterEncodingFilter 类
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
// 即使配置文件中不配置 spring.http.encoding.enabled=true,也是默认生效的
public class HttpEncodingAutoConfiguration {
// 他已经和 SpringBoot 的配置文件映射了
private final HttpEncodingProperties properties;
// 只有一个有参构造器的情况下,参数的值就会从容器中拿
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
@Bean // 给容器中添加一个组件,这个组件的某些值需要从 properties 中获取
@ConditionalOnMissingBean(CharacterEncodingFilter.class) // 判断容器没有这个组件
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}
}
对应的 HttpEncodingProperties:
java
@ConfigurationProperties(prefix = "spring.http.encoding") // 从配置文件中获取指定的值和 bean 的属性进行绑定
public class HttpEncodingProperties {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
// ...
}
8.3 自动配置精髓
根据当前不同的条件判断,决定这个配置类是否生效。一旦配置类生效,就会给容器中添加各种组件;这些组件的属性是从对应的 properties 类中获取的,这些类里面的每一个属性又是和配置文件绑定的。
所有在配置文件中能配置的属性都是在 xxxxProperties 类中封装的,配置文件能配置什么就可以参照某个功能对应的这个属性类。
自动配置的精髓总结:
- SpringBoot 启动会加载大量的自动配置类
- 我们要看我们需要的功能有没有 SpringBoot 默认写好的自动配置类
- 我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件有,我们就不需要再来配置了)
- 给容器中自动配置类添加组件的时候,会从 properties 类中获取某些属性,我们就可以在配置文件中指定这些属性的值
xxxxAutoConfiguration:自动配置类 → 给容器中添加组件
xxxxProperties:属性类 → 封装配置文件中相关属性
8.4 @Conditional 派生注解
作用:必须是 @Conditional 指定的条件成立,才给容器中添加组件,配置里面的所有内容才生效。自动配置类必须在一定的条件下才能生效。
| @Conditional 扩展注解 | 作用(判断是否满足当前指定条件) |
|---|---|
@ConditionalOnJava |
系统的 java 版本是否符合要求 |
@ConditionalOnBean |
容器中存在指定 Bean |
@ConditionalOnMissingBean |
容器中不存在指定 Bean |
@ConditionalOnExpression |
满足 SpEL 表达式指定 |
@ConditionalOnClass |
系统中有指定的类 |
@ConditionalOnMissingClass |
系统中没有指定的类 |
@ConditionalOnSingleCandidate |
容器中只有一个指定的 Bean,或者这个 Bean 是首选 Bean |
@ConditionalOnProperty |
系统中指定的属性是否有指定的值 |
@ConditionalOnResource |
类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication |
当前是 web 环境 |
@ConditionalOnNotWebApplication |
当前不是 web 环境 |
@ConditionalOnJndi |
JNDI 存在指定项 |
8.5 如何查看哪些自动配置类生效
我们可以通过启用 debug=true 属性,让控制台打印自动配置报告,方便知道哪些自动配置类生效。
在 application.properties 中添加:
properties
debug=true
控制台输出示例:
=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches:(自动配置类启用的)
---------------------------
DispatcherServletAutoConfiguration matched:
- @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet';
@ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnWebApplication (required) found StandardServletEnvironment
(OnWebApplicationCondition)
Negative matches:(没有启动,没有匹配成功的自动配置类)
---------------------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory',
'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
AopAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required classes
'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)
总结
本文系统地介绍了 Spring Boot 第一天的学习内容,主要包括:
- Spring Boot 简介: 是简化 Spring 应用开发的框架,提供了一站式解决方案
- 微服务架构: 一种新的架构风格,将应用拆分为一组小型服务
- 环境准备: jdk1.8、maven3.x、IDEA、SpringBoot 1.5.9.RELEASE
- HelloWorld 入门: 通过简单的示例快速上手 Spring Boot
- HelloWorld 探究: 深入理解父项目、启动器和主程序类的工作原理
- Spring Initializer: 使用向导快速创建项目
- 配置文件: 包括热部署、YAML 语法、配置文件值注入、占位符、Profile、加载位置等
- 自动配置原理: Spring Boot 自动配置的核心机制和精髓
核心要点:
- Spring Boot 通过 starter 简化依赖管理
- 通过
@SpringBootApplication注解开启自动配置 - 自动配置类根据
@Conditional条件判断是否生效 - 配置文件中的属性值通过
xxxxProperties类与组件绑定 - 使用
debug=true可以查看自动配置报告
掌握这些基础知识后,我们就可以更深入地学习 Spring Boot 的高级特性,如数据库访问、Web 开发、安全等。
参考资料:
如果本文对你有帮助,欢迎点赞、收藏、关注!如有错误欢迎指正交流~