约定大于配置!
一、SpringBoot简介及快速搭建
1. 简介
SpringBoot基于Spring开发,继承了Spring框架原有的优秀特性,但并不是来替代Spring的解决方案,而和Spring框架紧密结合进一步简化了Spring应用的整个搭建和开发过程。其设计目的是用来简化Spring应用的初始搭建一级开发过程,主要是通过提供默认配置等方式让我们更容易使用。
关于SpringBoot有一句很出名的话就是约定大于配置。采用SpringBoot可以大大简化开发模式,它集成了大量常用的第三方配置,所有想集成的常用框架,都有对应的组件支持,例如Redis、MongoDB、Dubbo、kafka、ES等。Springboot应用中这些第三方库几乎可以零配置地开箱即用,大部分的SpringBoot应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。另外SpringBoot通过集成大量的框架,使得依赖包的版本冲突以及引用的不稳定性等问题得到了很好的解决。
简化Spring应用开发的一个框架;
对整个企业级开发技术栈的一个大整合;
J2EE开发的一站式解决方案。
优点:
- 快速构建一个独立的Spring应用程序;
- 嵌入的Tomcat、Jetty或者Undertow,无需部署WAR文件(install成一个jar包,通过【java -jar 打包的jar包】 命令即可执行);
- 提供Starter POMs来简化Maven配置和减少版本冲突所带来的问题;
- 提供生产就绪型功能,如指标、健康检查和外部配置;
- 无需配置XML(通过JavaConfig代替了)、无代码生成,开箱即用;
2. 微服务
SpringBoot简化了基于Spring开发,这只是最直观的一方面,还有一个方面,也是得力于各微服务组件的支持,这也是谈SpringBoot必谈微服务的原因。(起初是Netfix移植到Spring)可以说是SpringCloud带动了SpringBoot,SpirngBoot成就了SpringCloud。
传统的web开发架构模式的测试部署比较简单,因为不涉及到多个服务的互联互调,只需要把一个包上传到服务器就行了,同样也不会给运维带来麻烦,方便水平扩展,只需要把相同的应用复制多份放到不同的服务器中就达到了扩展的目的。单体应用的缺点也显而易见,容易牵一发而动全身,比如要更改一个小小的功能,就可能需要重新部署整个应用。当然,更大的挑战就是日益增长的用户需求。
3. SpringBoot Hello World
jdk需要17版本
java
@RestController
public class TestController {
@RequestMapping("test")
public String test() {
return "hello springboot";
}
}
启动主启动类后,访问:localhost:8080/test 可以看到以下结果:
以上是在本地IDE中启动访问,还可以将程序打成jar包,放到服务器执行,模拟操作步骤如下:
第一步:打包:install或者package都可以
第二部:打开控制台,或者win+R输入cmd打开运行对话框
第三步:在IDE的控制台或者运行的对话框中输入【java -jar 生成的包名】--> 【回车】,即开启了服务
或
经过以上操作,再去浏览器访问,即可看到返回的结果。
通过命令方式启动程序后,终止程序运行的快捷键:Ctrl + C
4. 代码说明
SpringBoot提供了很多场景启动器starter。
所有的springboot都必须要继承spring-boot-starter-parent,它通过spring-boot-dependencies帮助管理了所有springboot内置的依赖的版本,避免了jar包跟jar包之间的依赖冲突。尚未内置的依赖,导入时依旧需要版本信息。该配置生成项目时就有,2.7.17目前(2025年1月)看来最稳定。
XML
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
打包springboot项目为一个jar包:
XML
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
jar包可以运行的原理:生成的jar包下有一个叫BOOT-INF的文件夹,里面的lib文件夹中放了很多的jar包;META-INF文件夹中的MANIFEST.MF文件:
① 是运行java -jar后会执行的代码,是自定义的类加载器去加载BOOT-INF中lib里的所有jar包;
② 是我们开发的代码项目的主启动类。
综上所述:spring-boot-maven-plugin帮我们把所有依赖的jar统统放在生成的jar文件里面的BOOT-INF\lib。并且在文件MANIFEST.MF中设置了启动类---JarLauncher,自定义加载器去加载所有的jar;和调用start-class.SpringBoot内嵌Tomcat。
在application.properties中设置懒加载:
XML
spring.main.lazy-initialization=true
作用:在使用/访问的时候才创建bean,而不是在Srpingboot加载的时候创建。
自定义SpringApplication主启动类:
java
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Springboot2025Application.class);
app.setBannerMode(Banner.Mode.OFF); // 可以关闭springboot启动横幅
app.run(args);
}
可以通过自定义主启动类的方式填加监听器、加载外部配置文件等。
二、SpringBoot配置文件和自动配置原理
配置文件的使用
SpringBoot使用一个全局的配置文件:核心配置文件,配置文件名在约定的情况下名字是固定的;
配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层给我们自动配置好。
application.properties
application.yml
YAML :Ain't Markup Language,是一个标记语言,
1. 两种配置文件的格式
(属性和值都是大小写敏感的)
在springboot框架中,resource文件夹里可以存放配置的文件有两种:properties和yml
① application.properties的用法:扁平的k/v格式
XML
server.port=8099
② application.yml的用法:树形结构(冒号和属性值之间有空格)
XML
server:
port: 8080
2. 配置文件的加载顺序
XML
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
如果同时存在不同后缀的文件按照这个顺序加载主配置文件,互补配置。
3. 外部约定配置文件加载顺序
springboot启动还会扫描以下位置的application.properties或者application.yml文件作为SpringBoot的默认配置文件
- classpath类根路径下的
- classpath类路径/config包下的
- 项目根目录:如果当前项目是继承/耦合关系maven项目的话,项目根目录=父maven项目的根目录
- 项目根目录/config
- 直接子目录/config的子目录:java -jar 打包的jar包 --server.port=8098
优先级由低到高,高优先级的配置会覆盖低优先级的配置。3和4一般不用,打jar的时候,这两个位置的配置文件也不会打到包里,5的方式是在运行jar包的时候,以【--】开始写上配置信息,该配置信息的优先级最高。第5个优先级还可以指定外部配置文件的位置,如果是文件夹,最后需要以"/"结尾:
4. Profile文件的加载
Profile的意思是配置,对于应用程序来说,不同的环境需要不同的配置,SpringBoot框架提供了profile的管理功能,可以使用profile功能来区分不同环境的配置。
① 多Profile文件
Spring官方给出的语法规则是application-(profile).properties (.yaml / .yml)。
② 如果需要创建自定义的properties文件时,可以用application-xxx.properties的命名方式,根据实际情况,公司一般会创建开发环境下使用的properties文件和一个生产环境下使用的properties文件,其中只对端口进行了配置,例如
dev为开发环境,prod为生产环境,默认识别的是application.yml配置文件,三个文件具体的配置如下:
application-dev.yml
XML
server:
port: 8080
#开发环境的数据库信息等
application-prod.yml
XML
server:
port: 8081
#生产环境的数据库信息等
application.yml (意为使用生产环境application-prod.yml的配置)
XML
spring:
profiles:
active: prod
经上操作,运行时启动的是生产环境的端口:
5. 配置文件值注入
将yaml映射到属性
① 字面量:普通的值(数字、字符串、布尔)
|------|------------------------------------|------------------------------------------------|
| k: v | 字面直接来写;字符串默认不用加上单引号或者双引号; | |
| "" | 双引号:不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思 | name: "zhangsan \n lisi" 输出:zhangsan 换行 lsi |
| '' | 单引号:会转义特殊字符,特殊字符最终只是一个普通的字符串数据 | name: 'zhangsan \n lisi' 输出:zhangsan \n lisi |
| | | |
② 对象、Map(属性和值)(键值对):
k: v :在下一行来写对象的属性和值的关系;注意缩进;对象还是k: v的方式
java
friend:
userName: pattie
age: 20
行内写法:
java
info: {userName: pattie, age: 20}
数组:(或List、Set)
用 "-值" 表示数组中的一个元素
java
pets:
- cat
- dog
行内写法:
java
pets: [cat,dog]
在配置文件中赋值之后,在java文件中如果想用这些值,可以通过以下方式:
① @Value + SPEL 的方式直接绑定springboot配置文件中的值。
java
public class Friend {
@Value("${friend.userName}")
String userName;
@Value("${friend.age}")
int age;
}
② 在实体类上加注解:@ConfigurationProperties(prefix = "friend") ,其中前缀是配置文件中设置的属性的第一层的名称。该注解常用于bean属性和yml配置文件的绑定,prefix可以指定配置文件中某一个节点,该节点的子节点将自动和属性进行绑定。
java
@ConfigurationProperties(prefix = "friend")
@Component
@Data
public class Friend {
String userName;
int age;
}
XML
friend:
age: 20
userName: pattie
测试类:
java
@SpringBootTest
class ConfigfileApplicationTests {
@Autowired
private Friend friend;
@Test
void contextLoads() {
System.out.println(friend);
}
}
运行结果:
prefix指定的配置文件中某一个节点的子节点可以自动和属性进行绑定,且支持松散绑定,例如配置文件中friend的子节点有四种写法均可支持与属性值userName进行绑定,分别为:USERNAME、userName、user_name、user-name。
@Value 获取值和 @ConfigurationProperties(prefix = "friend") 获取值的比较:
|------------|--------------------------|--------|
| | @ConfigurationProperties | @Value |
| 绑定 | 批量注入配置文件中的属性 | 一个个指定 |
| 松散绑定 | 支持 | 有限支持 |
| SpEL | 不支持 | 支持 |
| 自动提示 | 支持 | 不支持 |
| JSR303数据校验 | 支持 | 不支持 |
@ConfigurationProperties 支持自动提示需要加入依赖:(2024版的IDE不用,其他版本不清楚)
XML
<dependency>
<!-- 会生成META-INF元数据,用于提供idea自动提示配置文件属性-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<!--以来不会传播-->
<optional>true</optional>
</dependency>
并且在settings中开启一下配置:
6. 属性占位符
支持对其他属性的引用,以及设置随机值
java
@ConfigurationProperties(prefix = "friend")
@Component
@Data
public class Friend {
String userName;
int age;
String hobby;
}
XML
friend:
age: ${random.int(99)}
userName: pattie
hobby: ${friend.userName}的兴趣爱好是睡觉
运行结果:
其他例子如下所示:
JSR303的校验:@Validated (注意:只对@ConfigurationProperties起作用)
包括@NotNull (javax.validation下的注解) @Nullable @Email等等
java
@ConfigurationProperties(prefix = "friend")
@Component
@Data
@Validated // JSR303的校验
public class Friend {
String userName;
int age;
String hobby;
}
需要导入校验的依赖:
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>