以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
強(qiáng)烈推薦將主應(yīng)用類放在其它類之上的根包中。如果您的主類在根包中够掠,可以使用@SpringBootApplication
注解民褂,它隱式定義了某些項目的包搜索的基準(zhǔn)起點(diǎn)。當(dāng)然疯潭,你也可以通過設(shè)置屬性赊堪,自定義掃描包的范圍。
提示
- @SpringBootApplication = (默認(rèn)屬性)@Configuration + @EnableAutoConfiguration + @ComponentScan竖哩。
1.3. 配置類
1.3.1. 導(dǎo)入額外的配置類
SpringBoot不推薦使用XML配置哭廉,額外的配置類可以通過@Import
導(dǎo)入,或者可以在@ComponentScan
的掃描范圍內(nèi)相叁,添加@Configuration
類群叶。
1.3.2. 禁用指定的自動配置類
SpringBoot有一套默認(rèn)的自動配置類,如果你發(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ùn)行你的應(yīng)用
在您使用IDEA或Eclipse,Maven構(gòu)建項目的前提下雹有,您可以通過開發(fā)工具輕松運(yùn)行您的應(yīng)用偿渡。您也可以通過命令行運(yùn)行應(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ùn)行打包應(yīng)用程序時開啟遠(yuǎn)程調(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詳細(xì)信息,請參閱 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)詳細(xì)信息,請參閱 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)或者都不打痈淄谩(off)日裙。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ùn)行應(yīng)用時,應(yīng)用程序事件將按照以下順序發(fā)送:
- 在開始應(yīng)用開始運(yùn)行但還沒有進(jìn)行任何處理時(除了注冊監(jiān)聽器和初始化器[initializer])收苏,將發(fā)送 ApplicationStartingEvent亿卤。
- 當(dāng) Environment 被上下文使用,但是在上下文創(chuàng)建之前鹿霸,將發(fā)送 ApplicationEnvironmentPreparedEvent排吴。
- 在開始刷新之前,bean 定義被加載之后發(fā)送 ApplicationPreparedEvent懦鼠。
- 在上下文刷新之后且所有的應(yīng)用和命令行運(yùn)行器(command-line runner)被調(diào)用之前發(fā)送 ApplicationStartedEvent钻哩。
- 在應(yīng)用程序和命令行運(yùn)行器(command-line runner)被調(diào)用之后,將發(fā)出 ApplicationReadyEvent肛冶,該事件用于通知應(yīng)用已經(jīng)準(zhǔn)備處理請求街氢。
- 如果啟動時發(fā)生異常,將發(fā)送 ApplicationFailedEvent淑趾。
應(yīng)用程序事件發(fā)送使用了 Spring Framework 的事件發(fā)布機(jī)制阳仔。該部分機(jī)制確保在子上下文中發(fā)布給監(jiān)聽器的事件也會發(fā)布給所有祖先上下文中的監(jiān)聽器。因此扣泊,如果您的應(yīng)用程序使用有層級結(jié)構(gòu)的 SpringApplication 實例近范,則監(jiān)聽器可能會收到同種類型應(yīng)用程序事件的多個實例。
為了讓監(jiān)聽器能夠區(qū)分其上下文事件和后代上下文事件延蟹,您應(yīng)該注入其應(yīng)用程序上下文评矩,然后將注入的上下文與事件的上下文進(jìn)行比較≮迤可以通過實現(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
指令对蒲,由于智能覆蓋默認(rèn)值钩蚊。屬性值將按照以下順序加載:
- 在您的主目錄(當(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
注解。 - 默認(rèn)屬性(使用
SpringApplication.setDefaultProperties
指定)辙纬。
2.4.1. 配置隨機(jī)值
RandomValuePropertySource
對于隨機(jī)值注入非常有用(比如在保密場景或者測試用例中)豁遭。它可以產(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. 訪問命令行屬性
默認(rèn)情況下,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 進(jìn)行過濾,因此您可以返回之前定義的值(例如底挫,從系統(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以行縮進(jìn)的形式表示層級關(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 表達(dá)式允許表達(dá)更復(fù)雜的 profile 邏輯畔塔,例如
production & (eu-central | eu-west)
潭辈。有關(guān)詳細(xì)信息,請查閱參考指南澈吨。
2.4.4.3. YAML 的缺點(diǎn)
無法使用 @PropertySource
注解加載 YAML 文件把敢。因此,如果您需要以這種方式加載值谅辣,請使用屬性文件(properties)修赞。
2.4.5. 類型安全的配置屬性
使用 @Value("${property}")
注解來注入配置屬性有時會很麻煩,特別是如果您使用了多個屬性或者您的數(shù)據(jù)本質(zhì)上是分層結(jié)構(gòu)。Spring Boot 提供了另一種使用屬性的方法柏副,該方法使用強(qiáng)類型的 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
,默認(rèn)值為 false割择。 -
acme.remote-address
眷篇,可以從 String 強(qiáng)制轉(zhuǎn)換的類型。 -
acme.security.username
荔泳,內(nèi)嵌一個 security 對象蕉饼,其名稱由屬性名稱決定。特別是玛歌,返回類型根本沒有使用昧港,可能是 SecurityProperties。 -
acme.security.password
支子。 -
acme.security.roles
创肥,String 集合。
@Value
和 @ConfigurationProperties
之間的差異
功能 | @ConfigurationProperties |
@Value |
---|---|---|
寬松綁定 | 是 | 否 |
元數(shù)據(jù)支持 | 是 | 否 |
SpEL 表達(dá)式 |
否 | 是 |
同時译荞,不要忘了注冊屬性類瓤的,如下所示:
@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)詳細(xì)信息糯俗,請參閱附錄 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ù)~