最近在學習了 Spring Boot
後,也用它寫了一個簡單的專案,真的發現它對使用 Spring
開發的人來說是一大福音,無需在像以前那樣需要配置很多東西。這篇文章,就結合一些常見的面試題和開發中會用到的,對 Spring Boot
來總結一下。
一、Spring Boot 是什麼
Spring Boot
,看這個名字,就可以猜出來它是一個快速啟動 Spring
的框架,其實也正是如此,它採用“約定大於配置”的理念,提供了大量的自動配置,而無須再去編寫模板化的配置檔案,可以快速地建立一個可以獨立執行的 Spring
專案。
除了自動配置特性之外,它還有以下特性:
starter 啟動器
它提供了很多框架的 starter
啟動器,來簡化 maven
的依賴管理。Spring
專案中,在匯入其他框架的依賴時,還需要匯入其他附屬的依賴,如果框架比較多,那就會比較難以管理。而 Spring Boot
中提供了各種 starter
啟動器,可以對其進行很好的管理。例如,匯入 spring-boot-starter-web
依賴後,會自動新增如下依賴:
內嵌 Servlet 容器
它內嵌了很多 Servlet
容器,可以選擇 Tomcat
、Jetty
等。這樣就無須先下載 Tomcat
,搭建好執行環境,再以 war
包的形式進行部署,而是可以直接以 jar
包的形式,通過 java -jar xxx.jar
去獨立執行。
準生產環境的應用監控
提供了準生產環境的應用監控。可以基於 HTTP
、JMX
、SSH
等對執行時的專案進行監控。對 Actuator
還不太瞭解,後續再進行補充。
二、Spring、SpringBoot、SpringCloud
很多人應該都聽說過這三個東西,那它們之間到底有什麼區別呢?
學過 Spring
的應該都知道這樣一句話,Spring
是一個 JavaSE/EE
一站式的輕量級開源框架。其中提供了很多模組,例如 IoC
、AOP
、MVC
、Test
等。SpringMVC
只是其中的一個模組。
而 SpringBoot
是基於 Spring
的一個 Boot
啟動器,為了更容易、更快速地搭建一個 Spring
專案。針對的是單體應用。
SpringCloud
則是微服務架構下的一個綜合性解決方案,對使用 SpringBoot
開發的一個個服務進行管理,它整合了許多基礎元件,來解決業務拆分後帶來的如配置管理、服務治理、容錯等問題。
三、Spring Boot 的啟動方式
Spring Boot 的啟動方式主要有三種,下面就分別來看一下:
1. 打成 jar 包
前面說了 Spring Boot
中內建了 Serlvet
容器,可以直接使用 java -jar xxx.jar
。目前也推薦使用這種方式。另外通過這種方式,也可以在執行時指定一些引數。
在 pom.xml
檔案中,引入 spring-boot-maven-plugin
外掛後:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
複製程式碼
可以執行 mvn clean package
命令,將其打包成一個 jar
包,然後就可以通過 jar -jar xxx.jar
命令執行。
2. 執行 main 方法
在 Spring Boot
專案都會有一個主類,可以通過執行該類的 main
方法來啟動。這比較適用於開發除錯的時候。
3. 打成 war 包
如果是 web
專案,也可以打成 war
包,然後使用外部的 Tomcat
容器。
四、配置檔案
雖然 Spring Boot
提供了一系列自動化配置,來簡化繁重的配置。但是我們也要了解如何來修改這些預設配置,來適應一些特殊需求的場景。
4.1 配置方式
目前 Spring Boot
支援兩種配置方式,一種是傳統的 properties
檔案,以 key=value
形式來表示。例如,要修改預設的埠:
server.port=8081
複製程式碼
另一種是目前比較推薦使用的 YAML
檔案。它是以縮排的形式來表示,其結構更加地清晰易讀。例如:
server:
port: 8081
複製程式碼
另外,YAML
檔案也支援在同一個檔案中通過 spring.profiles
屬性來定義多個不同的環境的配置。例如,在下面的檔案中:
server:
port: 8080
---
server:
port: 8081
spring:
profiles: prod
---
server:
port: 8082
spring:
profiles: test
複製程式碼
如果我們指定為 test
環境,server.port
就使用 8082
埠;如果指定為 prod
環境,就使用 8081
埠,否則沒有指定的話,就使用 8080
埠。
但是 YAML
檔案有一些不足,它不能通過 @PropertySource
註解來載入指定的 YAML
配置檔案。不過可以通過 @Value
註解。
更多關於 YAML
的詳細語法,可以參考:阮一峰:YAML 語言教程
4.2 配置讀取方式
對於自定義的配置,要應用到我們的專案當中,SpringBoot
目前支援兩種讀取方式。它們也都支援和 @PropertySource
配合,來指定使用的配置檔案。
1. @Value
一種是剛才提到的 @Value
,讀取配置到具體的屬性上。
例如,在 application.yml
檔案中新增如下配置:
user:
name: TimberLiu
age: 21
address: China
複製程式碼
在 User
類就可以按照如下的方式進行讀取:
@Component
@Setter
@Getter
public class User {
@Value("${user.name}")
public String name;
@Value("${user.age}")
public int age;
@Value("${user.address}")
public String address;
}
複製程式碼
2. @ConfigurationProperties
另外一種是 @ConfigurationProperties
,讀取配置到類上。
同樣是上面的配置內容,使用 @ConfigurationProperties
就可以像如下這樣配置:
@Component
@Setter
@Getter
@ConfigurationProperites(prefix="user")
public class User {
public String name;
public Integer age;
public String address;
}
複製程式碼
3. 兩者的區別
那這兩種方式有什麼區別呢?通過下面這個表格來看一下:
/ | @ConfigurationProperties | @Value |
---|---|---|
功能 | 讀取配置到類上 | 讀取配置到屬性上 |
鬆散繫結 | 支援 | 不支援 |
JSR303 資料校驗 | 支援 | 不支援 |
複雜型別封裝 | 支援 | 不支援 |
下面通過一個例子來說明,例如對於下面的配置內容:
person:
name: timberliu
age: 21
birthday: 2019/4/17
info: {k1: v1,k2: v2}
lists:
- jack
- rose
dog:
last_name: wang # 屬性中的名,last_name 匹配 lastName,鬆散繫結
age: 3
複製程式碼
使用 @ConfigurationProperties
可以如下配置:
@Component
@Getter
@Setter
@ConfigurationProperties("person")
@Validated
public class Person {
// 非空校驗
@NotNull
private String name;
private Integer age;
// 日期型別,資料校驗
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private Date birthday;
// 複雜型別
private Map<String, String> info;
private List<Object> lists;
private Dog dog;
}
@Component
@Getter
@Setter
@ConfigurationProperties("person.dog")
public class Dog {
private String lastName;
private Integer age;
}
複製程式碼
4.3 多環境配置
一般來說,專案都會對於不同的環境使用不同的配置,在 Spring Boot
中,多環境配置的檔名需要滿足 application-{profile}.properties
或者 .yml
的格式,其中 profile
對應的環境標識。
至於具體哪個環境會被載入,需要在 application.properties
檔案中通過 spring.profiles.active
屬性進行設定。
例如,如果有三個環境的配置檔案:
application-dev.properties
application-test.properties
application-prod.properties
複製程式碼
在 application.properties
檔案中指定 spring.profiles.active=dev
,就會載入 application-dev.properties
配置檔案中的內容。
一般在實際開發中,多環境的配置思路如下:
- 在
application.properties
檔案中配置一些通用的屬性,並設定spring.profiles.active=dev
,預設配置為開發環境。 - 在
application-{profile}.properties
檔案中去配置不同環境不同的內容。 - 具體什麼環境,通過命令列的方式去啟用對應環境的配置。
4.4 配置載入順序
通過前面已經瞭解到,屬性可以在很多地方進行配置,例如 application.properties
或者 application-{profile}.properties
檔案中,命令列中等等。那麼為了能夠更合理地重寫各屬性的值,下面來看一下這些配置的載入順序是怎樣的。由於這裡載入順序非常多,這裡只列舉一些常用的:
- 命令列指定的引數。例如
java -jar myapplication.jar --server.port=8081
。 Java
系統變數。- 通過
random.*
配置的隨機屬性。 Jar
包外部的,針對不同{profile}
環境的配置檔案內容,例如application-{profile}.properties
。Jar
包內部的,針對不同{profile}
環境的配置檔案內容,例如application-{profile}.yml
。Jar
包外部的application.properties
或application.yml
。Jar
包內部的application.properties
或application.yml
。- 在自定義的
@Configuration
類中,通過@PropetySource
註解定義的屬性。 - 使用
SpringApplication.setDefaultProperties
定義的屬性。
這些載入順序,越往下優先順序越低。
五、最後
本文介紹了 Spring Boot
的基本概念。其中詳細說了 SpringBoot
的配置檔案,例如配置檔案的格式、讀取方式,多環境下應該如何配置,及配置檔案的載入順序。
下篇文章將詳細說一下 SpringBoot
的啟動方式和自動配置原理。