以SpringBoot官方文檔為原型,闡述SpringBoot。僅供學(xué)習(xí)參考,如有錯漏之處,望多包涵。
1.Spring Boot 入門
1.1 構(gòu)建SpringBoot項目
構(gòu)建springboot的方法有很多,如:maven\gradle\springboot-cli等。
介紹一下我常用的方法:
1、使用IDEA new->project

2、選擇 spring Initializr(spring初始化),設(shè)置JDK,一路next

3、選擇初始化導(dǎo)入的依賴,按需選擇

4、finished,喝杯咖啡等IDEA下載依賴就好了。
1.2. 包結(jié)構(gòu)規(guī)范
經(jīng)典的包結(jié)構(gòu):
com
+- example
+- myapplication
+- Application.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
強烈推薦將主應(yīng)用類放在其它類之上的根包中。如果您的主類在根包中,可以使用@SpringBootApplication 注解,它隱式定義了某些項目的包搜索的基準(zhǔn)起點。當(dāng)然,你也可以通過設(shè)置屬性,自定義掃描包的范圍。
提示
- @SpringBootApplication = (默認屬性)@Configuration + @EnableAutoConfiguration + @ComponentScan。
1.3. 配置類
1.3.1. 導(dǎo)入額外的配置類
SpringBoot不推薦使用XML配置,額外的配置類可以通過@Import導(dǎo)入,或者可以在@ComponentScan的掃描范圍內(nèi),添加@Configuration類。
1.3.2. 禁用指定的自動配置類
SpringBoot有一套默認的自動配置類,如果你發(fā)現(xiàn)不需要指定的配置類,可以通過使用 @EnableAutoConfiguration 的 exclude 屬性來禁用它們。
@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
如果類不在 classpath 下,您可以使用注解的excludeName 屬性并指定完全類名。最后,您還可以通過 spring.autoconfigure.exclude property 控制要排除的自動配置類列表。
1.4.Spring Bean與依賴注入
如果您按照上述最佳實踐(將應(yīng)用類放在根包中)來組織代碼,則可以添加無參的 @ComponentScan。所有應(yīng)用組件(@Component、@Service、@Repository、@Controller 等)將自動注冊為 Spring Bean。
如何獲取Spring Bean?
通常使用@Autowired獲取Bean。
@Component
public class DatabaseAccountController {
@Autowired
private RiskAssessService riskAssessService;
// ...
}
如果說一個項目出現(xiàn)了相同名字的Bean,那么就要給其中一個設(shè)置另外的name,@Autowired結(jié)合@Qualifier獲取。
@Component
public class DatabaseAccountController {
@Autowired
@Qualifier("RAssessService")
private RiskAssessService riskAssessService;
// ...
}
@Service("RAssessService")
public class RiskAssessService {
// ...
}
也可以通過構(gòu)造注入所需Bean。
@Service
public class RiskAssessService {
private final RiskAssessor riskAssessor;
@Autowired
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
提示
- 如果 bean 中只有一個構(gòu)造方法,您可以忽略掉 @Autowired 注解。
- 構(gòu)造注入允許 riskAssessor 字段被修飾為 final,這表示以后它不能被更改
1.5.運行你的應(yīng)用
在您使用IDEA或Eclipse,Maven構(gòu)建項目的前提下,您可以通過開發(fā)工具輕松運行您的應(yīng)用。您也可以通過命令行運行應(yīng)用。例如:
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
提示
- target指向您項目的路徑。
- myapplication-0.0.1-SNAPSHOT.jar是您打包應(yīng)用的名稱。您可以通過
mvn package命令行打包應(yīng)用。
也可以在運行打包應(yīng)用程序時開啟遠程調(diào)試支持。該功能允許您將調(diào)試器附加到打包的應(yīng)用中。
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myapplication-0.0.1-SNAPSHOT.jar
使用maven插件。
mvn spring-boot:run
1.6.熱插拔
java應(yīng)用熱插拔,即JVM熱插拔,應(yīng)用更新不需要重啟就能獲得相應(yīng)的效果。JVM 熱插拔在可替換字節(jié)碼方面有所限制。想要更完整的解決方案,可以使用 JRebel。
1.7.spring-boot-devtools
詳情參考開發(fā)者工具
2. Spring Boot的特性
2.1. 自定義SpringApplication
如果您想自定義SpringBoot應(yīng)用的初始化配置,您可以創(chuàng)建本地實例定制化。例如,關(guān)閉banner:
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
或者,優(yōu)雅的使用流式構(gòu)建器API(Fluent Builder API),
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);
也可以使用 application.properties 文件外部化配置。
關(guān)于配置選項的完整列表,請參閱 SpringApplication Javadoc。
關(guān)于SpringApplicationBuilder詳細信息,請參閱 SpringApplicationBuilder Javadoc。
2.2. 自定義banner
banner文件是用來定義應(yīng)用啟動日志輸出的。在 classpath 下添加一個 banner.txt 文件,或者將 spring.banner.location 屬性指向該文件的位置來更改啟動時打印的 banner。如果文件采用了非 UTF-8 編碼,您可以設(shè)置 spring.banner.charset 來解決。除了文本文件,您還可以將 banner.gif、banner.jpg 或者 banner.png 圖片文件添加到 classpath 下,或者設(shè)置 spring.banner.image.location 屬性。指定的圖片將會被轉(zhuǎn)換成 ASCII 形式并打印在 banner 文本上方。
您可以在 banner.txt 文件中使用以下占位符:
| 變量 | 描述 |
|---|---|
${application.version} |
您的應(yīng)用版本號,聲明在 MANIFEST.MF 中。例如,Implementation-Version: 1.0 將被打印為 1.0。 |
${application.formatted-version} |
您的應(yīng)用版本號,聲明在 MANIFEST.MF 中,格式化之后打?。ㄓ美ㄌ柪ㄆ饋恚?v 為前綴),例如 (v1.0)。 |
${spring-boot.version} |
您使用的 Spring Boot 版本。例如 2.1.1.RELEASE.。 |
${spring-boot.formatted-version} |
您使用的 Spring Boot 版本格式化之后顯示(用括號括起來,以 v 為前綴)。例如 (v2.1.1.RELEASE)。 |
${Ansi.NAME}(或 ${AnsiColor.NAME}、${AnsiBackground.NAME}、${AnsiStyle.NAME}) |
其中 NAME 是 ANSI 轉(zhuǎn)義碼的名稱。有關(guān)詳細信息,請參閱 AnsiPropertySource。 |
${application.title} |
您的應(yīng)用標(biāo)題,聲明在 MANIFEST.MF 中,例如 Implementation-Title: MyApp 打印為 MyApp。 |
注意
- 如果您想以編程的方式生成 banner,可以使用 SpringApplication.setBanner(?...) 方法。使用 org.springframework.boot.Banner 接口并實現(xiàn)自己的 printBanner() 方法。打印的 banner 被注冊名為 springBootBanner 的單例 bean。
- 您還可以使用
spring.main.banner-mode屬性來確定是否必須在 System.out(console)上打印 banner,還是使用日志記錄器(log)或者都不打?。╫ff)。YAML 將 off 映射為 false,因此如果要禁用應(yīng)用程序 banner,請確保屬性添加引號。
spring:
main:
banner-mode: "off"
2.3. 應(yīng)用事件與監(jiān)聽器
Spring Framework事件都繼承了抽象類 org.springframework.context.ApplicationEvent,諸如:ContextRefreshedEvent等。
注意
在
ApplicationContext創(chuàng)建之前,實際上觸發(fā)了一些事件,因此您不能像@Bean一樣注冊監(jiān)聽器。您可以通過SpringApplication.addListeners(?...)或者SpringApplicationBuilder.listeners(...?)方法注冊它們。如果您希望無論應(yīng)用使用何種創(chuàng)建方式都能自動注冊這些監(jiān)聽器,您都可以將META-INF/spring.factories文件添加到項目中,并使用org.springframework.context.ApplicationListener屬性鍵指向您的監(jiān)聽器。比如:org.springframework.context.ApplicationListener=com.example.project.MyListener。
當(dāng)您運行應(yīng)用時,應(yīng)用程序事件將按照以下順序發(fā)送:
- 在開始應(yīng)用開始運行但還沒有進行任何處理時(除了注冊監(jiān)聽器和初始化器[initializer]),將發(fā)送 ApplicationStartingEvent。
- 當(dāng) Environment 被上下文使用,但是在上下文創(chuàng)建之前,將發(fā)送 ApplicationEnvironmentPreparedEvent。
- 在開始刷新之前,bean 定義被加載之后發(fā)送 ApplicationPreparedEvent。
- 在上下文刷新之后且所有的應(yīng)用和命令行運行器(command-line runner)被調(diào)用之前發(fā)送 ApplicationStartedEvent。
- 在應(yīng)用程序和命令行運行器(command-line runner)被調(diào)用之后,將發(fā)出 ApplicationReadyEvent,該事件用于通知應(yīng)用已經(jīng)準(zhǔn)備處理請求。
- 如果啟動時發(fā)生異常,將發(fā)送 ApplicationFailedEvent。
應(yīng)用程序事件發(fā)送使用了 Spring Framework 的事件發(fā)布機制。該部分機制確保在子上下文中發(fā)布給監(jiān)聽器的事件也會發(fā)布給所有祖先上下文中的監(jiān)聽器。因此,如果您的應(yīng)用程序使用有層級結(jié)構(gòu)的 SpringApplication 實例,則監(jiān)聽器可能會收到同種類型應(yīng)用程序事件的多個實例。
為了讓監(jiān)聽器能夠區(qū)分其上下文事件和后代上下文事件,您應(yīng)該注入其應(yīng)用程序上下文,然后將注入的上下文與事件的上下文進行比較??梢酝ㄟ^實現(xiàn) ApplicationContextAware 來注入上下文,如果監(jiān)聽器是 bean,則使用 @Autowired 注入上下文。
提示
您可能不會經(jīng)常使用應(yīng)用程序事件,但了解他們的存在還是很有必要的。在框架內(nèi)部,Spring Boot 使用這些事件來處理各種任務(wù)。
2.4.外部化配置
為了適配多環(huán)境的部署。Spring Boot可以通過properties 文件、YAML 文件、環(huán)境變量或者命令行參數(shù)來外部化配置??梢允褂?@Value 注解將屬性值直接注入到 bean 中,可通過 Spring 的 Environment 訪問,或者通過 @ConfigurationProperties 綁定到結(jié)構(gòu)化對象。
Spring Boot使用了PropertySource指令,由于智能覆蓋默認值。屬性值將按照以下順序加載:
- 在您的主目錄(當(dāng) devtools 被激活,則為
~/.spring-boot-devtools.properties)中的 Devtools 全局設(shè)置屬性。 - 在測試中使用到的
@TestPropertySource注解。 - 在測試中使用到的
properties屬性,可以是@SpringBootTest和用于測試應(yīng)用程序某部分的測試注解。 - 命令行參數(shù)。
- 來自
SPRING_APPLICATION_JSON的屬性(嵌入在環(huán)境變量或者系統(tǒng)屬性【system propert】中的內(nèi)聯(lián) JSON)。 -
ServletConfig初始化參數(shù)。 -
ServletContext初始化參數(shù)。 - 來自
java:comp/env的 JNDI 屬性。 - Java 系統(tǒng)屬性(
System.getProperties())。 - 操作系統(tǒng)環(huán)境變量。
- 只有
random.*屬性的RandomValuePropertySource。 - 在已打包的 jar 外部的指定 profile 的應(yīng)用屬性文件(
application-{profile}.properties和 YAML 變量)。 - 在已打包的 jar 內(nèi)部的指定 profile 的應(yīng)用屬性文件(
application-{profile}.properties和 YAML 變量)。 - 在已打包的 jar 外部的應(yīng)用屬性文件(
application.properties和 YAML 變量)。 - 在已打包的 jar 內(nèi)部的應(yīng)用屬性文件(
application.properties和 YAML 變量)。 - 在
@Configuration類上的@PropertySource注解。 - 默認屬性(使用
SpringApplication.setDefaultProperties指定)。
2.4.1. 配置隨機值
RandomValuePropertySource 對于隨機值注入非常有用(比如在保密場景或者測試用例中)。它可以產(chǎn)生 integer、long、uuid 和 string。如下示例:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
2.4.2. 訪問命令行屬性
默認情況下,SpringApplication 將所有命令行選項參數(shù)(即以 -- 開頭的參數(shù),比如 --server.port=9000)轉(zhuǎn)換為屬性,并將它們添加到 Spring Environment 中。如之前所述,命令行屬性始終優(yōu)先于其他屬性源。
如果您不希望將命令行屬性添加到 Environment,可以使用 SpringApplication.setAddCommandLineProperties(false)來禁用它們。
2.4.3. 應(yīng)用程序?qū)傩晕募?/h4>
SpringApplication 從以下位置的 application.properties 文件中加載屬性(properties),并將它們添加到 Spring Environment 中:
- 當(dāng)前目錄/config 子目錄
- 當(dāng)前目錄
- classpath 上的 /config 包
-
classpath 根路徑
列表按序號優(yōu)先級排序,序號越小,優(yōu)先級越高。
用于多環(huán)境配置,如下圖:
如果您不喜歡 application.properties 作為配置文件名,則可以通過指定 spring.config.name 環(huán)境屬性來切換到另一個文件名。您還可以使用 spring.config.location 環(huán)境屬性來引用一個顯式位置(以逗號分隔的目錄位置或文件路徑列表)。以下示例展示了如何指定其他文件名:
$ java -jar myproject.jar --spring.config.name=myproject
以下示例展示了如何指定兩個位置:
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
2.4.3. 屬性文件中的占位符
application.properties 中的值在使用時通過現(xiàn)有的 Environment 進行過濾,因此您可以返回之前定義的值(例如,從系統(tǒng)屬性)。
app.name=MyApp
app.description=${app.name} is a Spring Boot application
2.4.4. 使用 YAML 代替屬性文件
YAML 是 JSON 的超集,是一個可用于指定層級配置數(shù)據(jù)的便捷格式。只要在 classpath 上有 SnakeYAML庫,SpringApplication 類就會自動支持 YAML 作為屬性文件(properties)的替代。
注意
如果使用 starter,則
spring-boot-starter會自動提供 SnakeYAML。
通常YAML文件后綴名用 .yml。
2.4.4.1. 加載YAML
例如以下文件:
environments:
dev:
url: http://dev.example.com
name: Developer Setup
my:
servers:
- dev.example.com
- another.example.com
轉(zhuǎn)換為以下屬性(properties):
environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
YAML以行縮進的形式表示層級關(guān)系。
2.4.4.2. 多profile YAML文檔
spring.profiles key 在單個文件中指定多個特定 profile 的 YAML 文檔,以指示文檔何時應(yīng)用,如下所示:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production & eu-central
server:
address: 192.168.1.120
在前面示例中,如果 development profile 處于激活狀態(tài),則 server.address 屬性得值為 127.0.0.1。 同樣,如果 production 和 eu-central profile 處于激活狀態(tài),則 server.address 屬性的值為 192.168.1.120。如果未激活 development、production 或 eu-central profile,則該屬性的值為 192.168.1.100。
注意
profile 表達式允許表達更復(fù)雜的 profile 邏輯,例如
production & (eu-central | eu-west)。有關(guān)詳細信息,請查閱參考指南。
2.4.4.3. YAML 的缺點
無法使用 @PropertySource 注解加載 YAML 文件。因此,如果您需要以這種方式加載值,請使用屬性文件(properties)。
2.4.5. 類型安全的配置屬性
使用 @Value("${property}") 注解來注入配置屬性有時會很麻煩,特別是如果您使用了多個屬性或者您的數(shù)據(jù)本質(zhì)上是分層結(jié)構(gòu)。Spring Boot 提供了另一種使用屬性的方法,該方法使用強類型的 bean 來管理和驗證應(yīng)用程序的配置,如下所示:
@ConfigurationProperties("acme")
public class AcmeProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
public boolean isEnabled() { ... }
public void setEnabled(boolean enabled) { ... }
public InetAddress getRemoteAddress() { ... }
public void setRemoteAddress(InetAddress remoteAddress) { ... }
public Security getSecurity() { ... }
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
public String getUsername() { ... }
public void setUsername(String username) { ... }
public String getPassword() { ... }
public void setPassword(String password) { ... }
public List<String> getRoles() { ... }
public void setRoles(List<String> roles) { ... }
}
}
前面的 POJO 定義了以下屬性:
-
acme.enabled,默認值為 false。 -
acme.remote-address,可以從 String 強制轉(zhuǎn)換的類型。 -
acme.security.username,內(nèi)嵌一個 security 對象,其名稱由屬性名稱決定。特別是,返回類型根本沒有使用,可能是 SecurityProperties。 -
acme.security.password。 -
acme.security.roles,String 集合。
@Value 和 @ConfigurationProperties 之間的差異
| 功能 | @ConfigurationProperties |
@Value |
|---|---|---|
| 寬松綁定 | 是 | 否 |
| 元數(shù)據(jù)支持 | 是 | 否 |
SpEL 表達式 |
否 | 是 |
同時,不要忘了注冊屬性類,如下所示:
@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}
Bean方式配置屬性,與外部YAML配置,有異曲同工之妙。
# application.yml
acme:
remote-address: 192.168.1.1
security:
username: admin
roles:
- USER
- ADMIN
要使用@ConfigurationProperties bean,您可以使用與其他 bean 相同的方式注入它們,如下所示:
@Service
public class MyService {
@Autowired
private final AcmeProperties properties;
//...
}
提示
使用
@ConfigurationProperties還可以生成元數(shù)據(jù)文件,IDE 可以通過這些文件來為您自己的 key 提供自動完成功能。有關(guān)詳細信息,請參閱附錄 B:配置元數(shù)據(jù)。
2.4.6. 寬松綁定
Spring Boot 使用一些寬松的規(guī)則將 Environment 屬性綁定到 @ConfigurationProperties bean,因此 Environment 屬性名不需要和 bean 屬性名精確匹配。常見的示例包括使用了 - 符號分割的環(huán)境屬性(例如,context-path 綁定到 contextPath)和大寫環(huán)境屬性(例如,PORT 綁定到 port)。
注意
注解的
prefix值必須是 kebab (短橫線命名)風(fēng)格(小寫并用-分隔,例如acme.my-project.person)。
表2.4.6.1 每種屬性源(property source)的寬松綁定規(guī)則
| 屬性源 | 簡單類型 | 列表集合類型 |
|---|---|---|
| properties 文件 | 駝峰式、短橫線式或下劃線式 | 標(biāo)準(zhǔn)列表語法使用 [] 或逗號分隔值 |
| YAML 文件 | 駝峰式、短橫線式或者下劃線式 | 標(biāo)準(zhǔn) YAML 列表語法或者逗號分隔值 |
| 環(huán)境變量 | 大寫并且以下劃線作為定界符,_ 不能放在屬性名之間使用 |
數(shù)字值兩邊使用下劃線連接,例如 MY_ACME_1_OTHER = my.acme[1].other
|
| 系統(tǒng)屬性 | 駝峰式、短橫線式或者下劃線式 | 標(biāo)準(zhǔn)列表語法使用 [] 或逗號分隔值 |
提示
Spring Boot建議,屬性盡可能以kebab (短橫線命名)風(fēng)格存儲,比如
my.property-name=acme。
未完待續(xù)~
