# Spring Boot 基础


<!--more-->


## 1.约定优于配置

```tex
Build Anything with Spring Boot：Spring Boot is the starting point for
building all Spring-based applications. Spring Boot is designed to get you up
and running as quickly as possible, with minimal upfront configuration of
Spring.
```

上面是引自官网的一段话，大概是说： Spring Boot 是所有基于 Spring 开发的项目的起点。SpringBoot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件。

**约定优于配置**（Convention over Configuration），又称按约定编程，是一种软件**设计范式**。就是遵循约定

本质上是说，系统、类库或框架应该假定合理的默认值，而非要求提供不必要的配置。比如说模型中有一个名为User的类，那么数据库中对应的表就会默认命名为user。只有在偏离这一个约定的时候，例如想要将该表命名为person，才需要写有关这个名字的配置。

## 2.spring boot概念

### 2.1 优缺点分析

- 优点：
  spring是Java企业版(Java Enterprise Edition，JEE，也称J2EE)的轻量级代替品。无需开发重量级的Enterprise JavaBean(EJB)，Spring为企业级Java开发提供了一种相对简单的方法，通过依赖注入和面向切面编程，用简单 的Java对象(Plain Old Java Object，POJO)实现了EJB的功能 
- 缺点：
  虽然Spring的组件代码是轻量级的，但它的配置却是重量级的。一开始，Spring用XML配置，而且是很多XML配 置。Spring 2.5引入了基于注解的组件扫描，这消除了大量针对应用程序自身组件的显式XML配置。Spring 3.0引入 了基于Java的配置，这是一种类型安全的可重构配置方式，可以代替XML。 
  所有这些配置都代表了开发时的损耗。因为在思考Spring特性配置和解决业务问题之间需要进行思维切换，所以编 写配置挤占了编写应用程序逻辑的时间。和所有框架一样，Spring实用，但与此同时它要求的回报也不少。 
  除此之外，项目的依赖管理也是一件耗时耗力的事情。在环境搭建时，需要分析要导入哪些库的坐标，而且还需要分析导入与之有依赖关系的其他库的坐标，一旦选错了依赖的版本，随之而来的不兼容问题就会严重阻碍项目的开发进度 

### 2.2 SpringBoot解决上述spring问题

SpringBoot对上述Spring的缺点进行的改善和优化，基于约定优于配置的思想，可以让开发人员不必在配置与逻辑业务之间进行思维的切换，全身心的投入到逻辑业务的代码编写中，从而大大提高了开发的效率，一定程度上缩短 了项目周期 

- 起步依赖 
  起步依赖本质上是一个Maven项目对象模型(Project Object Model，POM)，定义了对其他库的传递依 赖，这些东西加在一起即支持某项功能。 
  简单的说，起步依赖就是将具备某种功能的坐标打包到一起，并提供一些默认的功能。
- 自动配置
  springboot的自动配置，指的是springboot，会自动将一些配置类的bean注册进ioc容器，我们可以需要的地方使用@autowired或者@resource等注解来使用它。
  “**自动**”的表现形式就是我们只需要引我们想用功能的包，相关的配置我们完全不用管，springboot会自动注入这些配置bean，我们直接使用这些bean即可
  **springboot**: 简单、快速、方便地搭建项目；对主流开发框架的无配置集成；极大提高了开发、部署效率

## 3.spring boot 案例实现

使用Spring Initializr方式构建Spring Boot web项目

- 项目结构如下：

  ![img](https://img.zhaojq.top/20260727091743214.png "img")

- 创建demoController

  ```java
  @RestController
  public class DemoController {
  
      @RequestMapping("/demo")
      public String demo() {
          return "你好，world";
      }
  }
  ```

- 运行项目

  ```
  @SpringBootApplication
  public class SpringBootDemoApplication {
  
  	public static void main(String[] args) {
  		SpringApplication.run(SpringBootDemoApplication.class, args);
  	}
  
  }
  ```

  运行启动类main方法，成功后，默认端口为8080

  ![img_1](https://img.zhaojq.top/20260727091743418.png "img_1")

  > 解决中文乱码(二选一)
  >
  > - `@RequestMapping(produces = "application/json; charset=utf-8")`
  > - spring.http.encoding.force-response=true



## 4.单元测试与热部署

### 4.1 单元测试

开发中，每当完成一个功能接口或业务方法的编写后，通常都会借助单元测试验证该功能是否正确。Spring Boot对项目的单元测试提供了很好的支持，在使用时，需要提前在项目的pom.xml文件中添加`spring-boot-starter-test`测试依赖启动器，可以通过相关注解实现单元测试

- 引入依赖
  ```xml
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  ```

  > Tips: 使用Spring Initializr方式搭建的Spring Boot项目，会自动加入spring-boot-starter-test测试依赖启动器，无需再手动添加  
  
- 编写测试类和方法
  
  使用Spring Initializr方式搭建的Spring Boot项目，会在src.test.java测试目录下自动创建与项目主程序启动类对应的单元测试类  
  
  ```java
  //测试启动器，并加载Spring Boot测试注解
  // 由于spring boot 2.6.3 依赖Junit5, 故用 @ExtendWith(SpringExtension.class)
  // 如果用junit4, 则为 @RunWith(SpringRunner.class)
  @ExtendWith(SpringExtension.class)
  //测试启动器，并加载Spring Boot测试注解
  @SpringBootTest
  class SpringBootDemoApplicationTests {
  
  	@Autowired
  	private DemoController demoController;
  
  	@Test
  	void contextLoads() {
  		String demo = demoController.demo();
  		System.out.println(demo);
  	}
  
  }
  ```

### 4.2热部署

在开发过程中，通常会对一段业务代码不断地修改测试，在修改之后往往需要重启服务，有些服务需要加载很久才能启动成功，这种不必要的重复操作极大的降低了程序开发效率。为此，Spring Boot框架专门提供了进行热部署的依赖启动器，用于进行项目热部署，而无需手动重启项目  

- 添加依赖

  ```xml
  dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
  </dependency>
  ```

- IDEA需勾选的功能

  ![img_2](https://img.zhaojq.top/20260727091743616.png "img_2")



## 5.全局配置文件

全局配置文件能够对一些默认配置值进行修改。Spring Boot使用一个application.properties或者application.yaml的文件作为全局配置文件，该文件存放在src/main/resource目录或者类路径
的/conﬁg，一般会选择resource目录。

### 5.1 application.properties

使用Spring Initializr方式构建Spring Boot项目时，会在resource目录下自动生成一个空的application.properties文件，Spring Boot项目启动时会自动加载application.properties文件。
我们可以在application.properties文件中定义Spring Boot项目的相关属性，当然，这些相关属性可以是系统属性、环境变量、命令参数等信息，也可以是自定义配置文件名称和位置  

如：

```properties
server.port=8081
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.config.additional-location=
spring.config.location=
spring.config.name=application
```

自定义配置属性注入示例：

```java
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private Integer id;
    private String name;
    private List hobby;
    private String[] families;
    private Map map;
    private Pet pet;
    //省略getter,setter...
}

@Component
public class Pet {
    private String type;
    private String name;
}
```

> **@ConﬁgurationProperties(preﬁx = "person")**注解的作用是将配置文件中以person开头的属性值通过setXX()方法注入到实体类对应属性中
> **@Component**注解的作用是将当前注入属性值的Person类对象作为Bean组件放到Spring容器中，只有这样才能被@ConﬁgurationProperties注解进行赋值 

```properties
person.id=1
person.name=tony
person.hobby=music,paint
person.families=father,mother
person.map.k1=v1
person.map.k2=v2
person.pet.type=dog
person.pet.name=小狗
```

> 编写application.properties配置文件时，由于要配置的Person对象属性是我们自定义的，Spring Boot无法自动识别，所以不会有任何书写提示。在实际开发中，为了出现代码提示的效果来方便配置，在使用@ConﬁgurationProperties注解进行配置文件属性值注入时，可以在pom.xml文件中添加一个Spring Boot提供的配置处理器依赖:
>
> ```xml
> <dependency>
>   <groupId>org.springframework.boot</groupId>
>   <artifactId>spring-boot-configuration-processor</artifactId>
>   <optional>true</optional>
> </dependency>
> ```

```java
	@Autowired
	private Person person;
	
	@Test
	void configurationTest(){
		System.out.println(person);
	}
```

### 5.2 application.yml配置文件

YAML文件格式是Spring Boot支持的一种JSON超集文件格式，相较于传统的Properties配置文件， YAML文件以数据为核心，是一种更为直观且容易被电脑识别的数据序列化格式。application.yaml配置文件的工作原理和application.properties是一样的，只不过yaml格式配置文件看起来更简洁一些。

> YAML文件的扩展名可以使用.yml或者.yaml。 
> application.yml文件使用 “key:（空格）value”格式配置属性，使用缩进控制层级关系。

yml数值规范：

- 普通数据类型

  当YAML配置文件中配置的属性值为普通数据类型时，可以直接配置对应的属性值，同时对于字符串类型的属性值，不需要额外添加引号，示例代码如下  

  ```yml
  server:
  	port:8080
  ```

- value值为数组和单列集合

  当YAML配置文件中配置的属性值为数组或单列集合类型时，主要有两种书写方式：**缩进式写法**和行内式写法

  ```yml
  #以下写法都可以
  person:
  	hobby:
  		- play
  		- read
  		- sleep
  
  person:
  	hobby:
  		play,
  		read,
  		sleep
  		
  person:
  	hobby: [play,read,sleep]
  ```

- value值为map

  ```yaml
  #以下写法都可以
  person:
  	map:
  		k1:v1
  		k2:v2
  		
  person:
  	map: [k1:v1, k2:v2]		
  ```



## 6.配置文件属性值注入

如果配置属性是Spring Boot已有属性，例如服务端口server.port，那么Spring Boot内部会自动扫描并读取这些配置文件中的属性值并覆盖默认属性

如果配置的属性是用户自定义属性，例如刚刚自定义的Person实体类属性，还必须在程序中注入这些配置属性方可生效

Spring Boot支持多种注入配置文件属性的方式

- @ConﬁgurationProperties 前面已示例过

- @Value

   @Value注解是Spring框架提供的，用来读取配置文件中的属性值并逐个注入到Bean对象的对应属性中，Spring Boot框架从Spring框架中对@Value注解进行了默认继承，所以在Spring Boot框架中还可以使用该注解读取和注入配置文件属性值。使用@Value注入属性的示例代码如下。

  @Value不仅可以将配置文件的属性注入Person的id属性，还可以直接给id属性赋值，这点是@ConﬁgurationProperties不支持的。

  @Value注解方式需要对每一个属性注入设置，同时又免去了属性的setXX()方法 。

  

## 7.自定义配置

对于这种加载自定义配置文件的需求，可以使用@PropertySource注解结合@Conﬁguration注解配置类的方式来实现。

### 7.1@PropertySource加载配置文件

@PropertySource注解用于指定自定义配置文件的具体位置和名称。同时，为了保证Spring Boot能够扫描该注解，还需要类上添加@Conﬁguration注解将实体类作为自定义配置类。

当然，如果需要将自定义配置文件中的属性值注入到对应类的属性中，可以使用@ConﬁgurationProperties或者@Value注解进行属性值注入  

```properties
#test.properties
test.id=1
test.name=test
```

```java
@Configuration
@PropertySource("classpath:test.properties")
@ConfigurationProperties(prefix = "test")
//@EnableConﬁgurationProperties
public class CustomYml {
    private Integer id;
    private String name;
		//省略get,set,toString
}
```

> - @Conﬁguration注解表示当前类是一个自定义配置类，并添加为Spring容器的组件，这里也可以使用传统的@Component注解；
> - @PropertySource("classpath:test.properties")注解指定了自定义配置文件的位置和名称，此示例表示自定义配置文件为classpath类路径下的test.properties文件；
> - @ConﬁgurationProperties(preﬁx = "test")注解将上述自定义配置文件test.properties中以test开头的属性值注入到该配置类属性中。
>   如果配置类上使用的是@Component注解而非@Conﬁguration注解，那么
> - @EnableConﬁgurationProperties注解还可以省略  

### 7.2 使用@Conﬁguration编写自定义配置类

在Spring Boot框架中，推荐使用**配置类**的方式向容器中添加和配置组件

在Spring Boot框架中，通常使用**@Conﬁguration**注解定义一个配置类，Spring Boot会自动扫描和识别配置类，从而替换传统Spring框架中的XML配置文件。

当定义一个配置类后，还需要在类中的方法上使用@Bean注解进行组件配置，将方法的返回对象注入到Spring容器中，并且组件名称默认使用的是方法名，当然也可以使用@Bean注解的name或value属性自定义组件的名称 。

示例：

```java
public class MyService {
}

@Configuration
public class MyConfig {

    //默认方法名，可以使用name指定
    @Bean(name = "myService")
    public MyService myService() {
        return new MyService();
    }
}
```

```java
@Test
void testConfiguration(){
  System.out.println(context.containsBean("myService"));
  System.out.println(myService);
}

//true
//com.example.springbootdemo.config.MyService@a2b54e3
```

## 8.随机数设置及参数间引用

在Spring Boot配置文件中设置属性时，除了可以像前面示例中显示的配置属性值外，还可以使用
随机值和参数间引用对属性值进行设置

### 8.1随机值设置

在Spring Boot配置文件中，随机值设置使用到了Spring Boot内嵌的RandomValuePropertySource类，对一些隐秘属性值或者测试用例属性值进行随机值注入

随机值设置的语法格式为${random.xx}，xx表示需要指定生成的随机数类型和范围，它可以生成随机的整数、uuid或字符串，示例代码如下 

```properties
# 配置随机值
my.secret=${random.value}
# 配置随机整数
my.number=${random.int}
# 配置随机long类型数
my.bignumber=${random.long}
# 配置随机uuid类型数
my.uuid=${random.uuid}
# 配置小于10的随机整数
my.number.less.than.ten=${random.int(10)}
# 配置范围在[1024,65536]之间的随机整数
my.number.in.range=${random.int[1024,65536]}
```

### 8.2参数间引用

在Spring Boot配置文件中，配置文件的属性值还可以进行参数间的引用，也就是在后一个配置的属性值中直接引用先前已经定义过的属性，这样可以直接解析其中的属性值了。

使用参数间引用的好处就是，在多个具有相互关联的配置属性中，只需要对其中一处属性预先配置，其他地方都可以引用，省去了后续多处修改的麻烦

参数间引用的语法格式为${xx}，xx表示先前在配置文件中已经配置过的属性名

```properties
app.name=MyApp
app.description=${app.name} is a Spring Boot application
```




































































