第3章 零XML配置的Spring Boot
Spring Boot 提供了一種統(tǒng)一的方式來管理應(yīng)用的配置惜颇,允許開發(fā)人員使用屬性properties文件皆刺、YAML 文件、環(huán)境變量和命令行參數(shù)來定義優(yōu)先級(jí)不同的配置值凌摄。
本章我們就來體驗(yàn)一下零XML配置的Spring Boot 應(yīng)用的開發(fā)羡蛾。
2.1 Spring Boot 簡(jiǎn)介
2.1.1 Spring 去 XML配置簡(jiǎn)史
Spring IOC有一個(gè)非常核心的概念——Bean。由Spring容器來負(fù)責(zé)對(duì)Bean的實(shí)例化锨亏,裝配和管理痴怨。
最早XML是用來描述Bean最為流行的配置方式忙干。Spring可以從XML配置文件中讀取任何類型的元數(shù)據(jù)并自動(dòng)轉(zhuǎn)換成相應(yīng)的Java代碼。
隨著Spring的日益發(fā)展浪藻,越來越多的人對(duì)Spring提出了批評(píng)捐迫。“Spring項(xiàng)目大量的爛用XML”就是最為嚴(yán)勵(lì)的一個(gè)批評(píng)珠移。
由于Spring會(huì)把幾乎所有的業(yè)務(wù)類都以Bean的形式配置在XML文件中弓乙,造成了大量的XML文件。使用XML來配置Bean失去了編譯時(shí)的類型安全檢查钧惧。大量的XML配置使得整個(gè)項(xiàng)目變得更加復(fù)雜暇韧。
我們使用XML配置的問題之一是要等到運(yùn)行時(shí)的時(shí)候來發(fā)現(xiàn)Bean里面的錯(cuò)誤或者其他愚蠢的問題。當(dāng)然浓瞪,在使用Spring的IDE插件(或者其他整合了Spring Tools Suite的工具)能在一定程度上發(fā)現(xiàn)這方面問題懈玻。
- Spring 2.5中我們開始有了面向注解的依賴注入編程(@Component和 @Autowired)。
- Spring 3.0中我們有了 JavaConfig , 它能夠取代 XML乾颁。Spring 3.1中又提供了@Enable* 系列的注解涂乌,使得基于注解的配置更加自動(dòng)化。
- 在 Spring 4.0中@Conditional注解(org.springframework.context.annotation.Conditional)實(shí)現(xiàn)的基于條件的配置英岭,根據(jù)應(yīng)用的類路徑中的類湾盒、環(huán)境信息以及其他一些相關(guān)信息,在運(yùn)行時(shí)自動(dòng)化地完成配置诅妹,大量省去了程序員們大量樣板化的手工配置工作罚勾。
2.1.2 要進(jìn)一步解決的問題
在有了上面的這些支持后,使用Spring或者SpringMVC的過程中吭狡,仍然有很多配置以及繁瑣的操作需要我們手工去完成尖殃。例如:
- 單獨(dú)部署配置一個(gè) tomcat(tomcat 的相關(guān)配置需要單獨(dú)去tomcat安裝目錄下配)
- 使用大量依賴庫(kù)可能導(dǎo)致的版本沖突
- Spring 集成使用使用模板引擎 Freemarker、velocity划煮、thymeleaf 等需要單獨(dú)配置
- Spring 集成使用 MyBatis送丰、JPA 等 ORM 框架需要單獨(dú)配置
- Spring 集成使用安全框架 Security 、日志框架等等都需要單獨(dú)一套配置
- 配置 SpringMVC 中的 DispatcherServlet 需要在 web.xml 或者在 Servlet 初始化代碼里進(jìn)行顯式配置
- 靜態(tài)資源的處理
- 應(yīng)用的運(yùn)維監(jiān)控工作等
由于這些已經(jīng)存在的問題弛秋,Spring Boot應(yīng)運(yùn)而生器躏,使用Spring Boot可以讓我們快速創(chuàng)建一個(gè)基于Spring的項(xiàng)目,而讓這個(gè)Spring項(xiàng)目跑起來我們只需要很少的配置就可以了蟹略。
2.1.3 SpringBoot 的核心功能
Spring Boot主要有如下核心功能:
直接創(chuàng)建一個(gè)可以獨(dú)立運(yùn)行的Spring項(xiàng)目
Spring Boot可以以jar包的形式來運(yùn)行登失,我們可以直接通過 java -jar xx.jar 命令來運(yùn)行一個(gè)Spring Boot項(xiàng)目。內(nèi)嵌Servlet容器
Spring Boot可以內(nèi)嵌Tomcat直接一鍵運(yùn)行 Web 應(yīng)用科乎。我們不再需要打 war 包壁畸,丟到 Tomcat 下面,再啟動(dòng) Tomcat 等等一系列操作了。
- 提供starter簡(jiǎn)化 Maven/Gradle 配置
使用Spring或者SpringMVC我們需要添加大量的依賴捏萍,而這些依賴很多都是固定的樣板化配置太抓。Spring Boot 通過starter 幫助我們簡(jiǎn)化 Maven/Gradle 配置。
自動(dòng)配置Spring
SpringBoot 提供了大量超級(jí)實(shí)用的 starter令杈,大大簡(jiǎn)化了我們使用 Spring 開發(fā)過程中的配置走敌。生產(chǎn)環(huán)境的應(yīng)用監(jiān)控
使用SpringBoot 提供的 Actuator ,我們可以方便地進(jìn)行應(yīng)用程序的監(jiān)控逗噩。無代碼生成和xml配置
SpringBoot 沒有引入任何形式的代碼生成掉丽,它是使用的 Spring 4.0的條件注解以實(shí)現(xiàn)根據(jù)條件進(jìn)行配置;同時(shí)使用了 Maven/Gradle 的依賴傳遞解析機(jī)制來實(shí)現(xiàn) Spring 應(yīng)用里面的自動(dòng)配置异雁。
2.2 回顧 Spring
Spring能夠進(jìn)行自動(dòng)化的裝配捶障,它使用兩種方式來進(jìn)行自動(dòng)化裝配:
1、組件掃描:
Spring會(huì)自動(dòng)發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean
2纲刀、自動(dòng)裝配:
Spring會(huì)自動(dòng)構(gòu)建bean之間的依賴關(guān)系
Spring的自動(dòng)化裝配使用了零xml配置项炼,也就是使用了全代碼配置(注解配置),其中代碼配置類使用@Configuration注解進(jìn)行標(biāo)注示绊。
2.2.1 組件掃描:
@Component能給一個(gè)類自動(dòng)生成對(duì)象并注入到Spring容器中锭部,比如下面的CDPlayer,會(huì)自動(dòng)new一個(gè)CDPlayer的對(duì)象并放置到Spring容器中面褐。
public interface Player {
void play();
}
@Component
public class CDPlayer implements Player {
public void play() {
System.out.print("播放CD");
}
}
我們知道拌禾,Spring容器中每個(gè)bean都有自己唯一的一個(gè)id,自動(dòng)注入的bean的id的規(guī)則如下:
1展哭、如果@Component中有值湃窍,類似
@Component("xxx"),那么此bean的id即為xxx 摄杂。
2坝咐、如果類名為第一個(gè)字母大寫循榆,第二個(gè)字母小寫析恢,即滿足首字母大寫的駝峰命令規(guī)則,比如CdPlayer, 那么其bean的id第一個(gè)字母要小寫秧饮,其余不變映挂,所以最終為cdplayer。
3盗尸、如果不滿足規(guī)則1柑船,比如類名是CDPlayer, 那么其bean的id跟類名相同,所以最終為CDPlayer泼各。
2.2.2 自動(dòng)裝配
需要注意的是鞍时,配置對(duì)象需要 @Configuration和@ComponentScan注解,而@ComponentScan注解是標(biāo)注Spring掃描的基礎(chǔ)包名的。如果沒有值逆巍,默認(rèn)會(huì)掃描自己所在的包的所有類及塘。
其中的Configuration配置對(duì)象:
@Configuration
@ComponentScan
public class PlayerConfig {
}
那么如何配置掃描包呢?比如我想掃描 com.easy.springboot 包下的所有類锐极,可以這樣:
@ComponentScan(basePackages = "com.easy.springboot")
我們使用junit4來進(jìn)行測(cè)試笙僚,注意在想獲取Spring中bean上加上@Autowired,Spring會(huì)自動(dòng)注入灵再。
另外肋层,下面的Player可以換成CDPlayer,因?yàn)镃DPlayer的對(duì)象既是CDPlayer的對(duì)象翎迁,也是Player的對(duì)象栋猖。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = PlayerConfig.class)
public class TestCDPlayer {
@Autowired
private Player cdPlayer;
@Test
public void testNotNull(){
cdPlayer.play();
}
}
另外,我們也可以將一個(gè)對(duì)象注入到另一個(gè)對(duì)象中汪榔。比如有一個(gè)People類掂铐,要為其注入一個(gè)Player類,然后其跑步的時(shí)候會(huì)調(diào)用Player類的play方法揍异,這樣實(shí)現(xiàn)即可:
@Component
public class People {
@Autowired
private Player player;
public void run(){
player.play();
System.out.println("正在跑步");
}
}
這里的
@Autowired
private Player player
Spring會(huì)自動(dòng)把生成的Player對(duì)象注入到People類中全陨。
注入的規(guī)則分為兩步:
1、Spring會(huì)先查找id為player的Bean對(duì)象衷掷,如果找到辱姨,注入進(jìn)來
2、如果沒有找到id為player的Player對(duì)象戚嗅,那么就去尋找Spring容器中查找Player的對(duì)象雨涛,如果一個(gè)都沒有,或者有兩個(gè)或者多個(gè)懦胞,那么就會(huì)報(bào)錯(cuò)替久。
2.2.3 使用用JavaConfig
一般來說,自動(dòng)裝配bean已經(jīng)能為我們解決很多問題躏尉。但是蚯根,有的時(shí)候可能我們需要更自動(dòng)的配置,這個(gè)時(shí)候我們就可以使用 JavaConfig 來完成胀糜。
Spring Boot的零XML配置也是基于 JavaConfig來實(shí)現(xiàn)的颅拦。
JavaConfig就是使用注釋來描述Bean配置的組件,也就是注解驅(qū)動(dòng)配置( Annotation-Driven Configuration)教藻。它是從Spring 3.0后嵌入到Spring里的一個(gè)以前的獨(dú)立項(xiàng)目距帅。JavaConfig能夠等價(jià)看成是XML文件,不過它只是用Java編寫的括堤。
提示:JavaConfig 是Spring的一個(gè)子項(xiàng)目(詳細(xì)了解可參考:http://docs.spring.io/spring-javaconfig/docs/).
比如我想獲取同一個(gè)類的多個(gè)bean對(duì)象碌秸,就可以在JavaConfig中聲明方法來裝配bean:
@Bean
public Player player(){
return new CDPlayer();
}
此時(shí)Spring容器就會(huì)生成一個(gè)Player的對(duì)象绍移,其id為player(注意id與方法名是一樣的)。
我們也可以為Player對(duì)象指定Bean id:
@Bean(name="firstPlayer")
public Player player(){
return new CDPlayer();
}
那么我們?cè)诖a中就可以根據(jù)這個(gè)id名稱來裝配這個(gè) Bean
@Autowired
private Player firstPlayer
不過讥电,要注意的是@Autowired默認(rèn)按類型(byType)裝配登夫。如果我們想使用名稱裝配,可以結(jié)合@Qualifier注解進(jìn)行使用允趟,如下:
@Autowired
@Qualifier("firstPlayer")
private Player firstPlayer;
另外恼策,我們還可以使用@Resource(這個(gè)注解屬于J2EE的)
@Resource(name="firstPlayer") //在字段上的注入,先按照名字裝配
private Player firstPlayer;
默認(rèn)按照名稱(byName)進(jìn)行裝配潮剪,名稱可以通過name屬性進(jìn)行指定涣楷, 裝配規(guī)則是:
如果沒有指定name屬性,當(dāng)注解寫在字段上時(shí)抗碰,默認(rèn)取字段名進(jìn)行按照名稱查找狮斗,如果注解寫在setter方法上默認(rèn)取屬性名進(jìn)行裝配。
當(dāng)找不到與名稱匹配的bean時(shí)才按照類型進(jìn)行裝配弧蝇。但是需要注意的是碳褒,如果name屬性一旦指定,就只會(huì)按照名稱進(jìn)行裝配看疗。
Spring的XML配置方式是使用被Spring命名空間的所支持的一系列的XML標(biāo)簽來實(shí)現(xiàn)的沙峻。Spring有以下主要的命名空間:context、beans两芳、jdbc摔寨、tx、aop怖辆、mvc等是复。
使用XML來配置Bean所能實(shí)現(xiàn)的功能,通過JavaConfig同樣可以很好的實(shí)現(xiàn)竖螃。之前我們都是在xml文件中定義bean的淑廊,比如:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloBean" class="com.hello.impl.HelloWorldImpl">
</beans>
其實(shí)我們可以使用注解來完成這些事情,例如下面的代碼特咆,完成的功能和上面的xml配置的功能是一樣的:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.hello.HelloWorld;
import com.hello.impl.HelloWorldImpl;
@Configuration
public class AppConfig {
@Bean(name="helloBean")
public HelloWorld helloWorld() {
return new HelloWorldImpl();
}
}
使用@Bean注解季惩,來標(biāo)識(shí)此方法構(gòu)造出一個(gè)由Spring容器管理的bean。@Bean聲明所起到的作用與<bean/> 元素類似坚弱。
Spring對(duì)Java配置的支持是由@Configuration注解和@Bean注解來實(shí)現(xiàn)的蜀备。由@Bean注解的方法將會(huì)實(shí)例化关摇、配置和初始化一個(gè)新對(duì)象荒叶,這個(gè)對(duì)象將由Spring的IoC容器來管理。
2.2.4 導(dǎo)入子配置類
其實(shí)输虱,Spring 中的 XML 配置文件本質(zhì)上說是一種編程元數(shù)據(jù)些楣。在早期Java版本中,應(yīng)用中的元數(shù)據(jù)一般使用屬性文件、XML愁茁。但是用配置文件不夠靈活而且比較繁瑣蚕钦。從Spring 3起,JavaConfig功能已經(jīng)包含在Spring核心模塊鹅很,它允許開發(fā)者將bean定義和在Spring配置XML文件到Java類中嘶居。與此同時(shí)仍然允許使用經(jīng)典的XML方式來定義bean和配置。
一般在一個(gè)大型工程項(xiàng)目中促煮,如果將所有的bean都配置在一個(gè)xml文件中邮屁,那么這個(gè)文件就會(huì)非常的大。所以一般會(huì)將一個(gè)大的xml配置文件分割為好幾份菠齿。這樣方便管理佑吝,最后在總的那個(gè)xml文件中導(dǎo)入。比如:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="config/customer.xml"/>
<import resource="config/scheduler.xml"/>
</beans>
但是現(xiàn)在我們也可以使用JavaConfig來完成同樣的工作了:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({ CustomerConfig.class, SchedulerConfig.class })
public class AppConfig {
}
@Configuration可以被認(rèn)為是相當(dāng)于XML的< bean / >元素绳匀。
2.2.5 導(dǎo)入XML 配置
在 Spring XML中, 啟動(dòng)注解注入bean芋忿,通過如下標(biāo)簽實(shí)現(xiàn):
<context:annotation-config/>
在 JavaConfig中, 等同于 @AnnotationDrivenConfig注解。
代碼示例:
@Configuration
@AnnotationDrivenConfig
public class Config {
}
使用@ComponentScan注解疾棵,等同于在 Spring XML中的
<context:component-scan/>
代碼示例:
package com.company.foo;
@Service
public class FooServiceImpl implements FooService {
private final FooRepository fooRepository;
@Autowired
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
// ...
}
package com.company.foo;
@Repository
public class JdbcFooRepository implements FooRepository {
private final DataSource dataSource;
@Autowired
public FooRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
// ...
}
@Configuration
@ComponentScan("com.company") // search the com.company package for @Component classes
@ImportXml("classpath:com/company/data-access-config.xml") // XML with DataSource bean
public class Config {
}
在配置類中使用上述的配置戈钢,我們就可以在代碼里調(diào)用service方法了:
public class Main {
public static void main(String[] args) {
JavaConfigApplicationContext ctx = new JavaConfigApplicationContext(Config.class);
FooService fooService = ctx.getBean(FooService.class);
fooService.doStuff();
}
}
2.3 SpringBoot的應(yīng)用級(jí)配置文件
SpringBoot應(yīng)用中有個(gè)應(yīng)用級(jí)的配置文件application.properties 。
例如是尔,我們?cè)赼pplication.properties中配置一個(gè)使用 JPA 的數(shù)據(jù)源
# datasource: unicode編碼的支持逆趣,設(shè)定為utf-8
spring.datasource.url=jdbc:mysql://localhost:3306/blog?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&characterSetResults=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto=update
# Naming strategy
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
2.3.1 配置文件所在目錄
Spring Boot 提供的 SpringApplication 類會(huì)搜索并加載 application.properties 文件來獲取配置屬性值。SpringApplication 類會(huì)在下面位置搜索該文件:
1.當(dāng)前目錄的/config子目錄
2.當(dāng)前目錄
3.classpath 中的/config包
4.classpath
我們?cè)陂_發(fā)的時(shí)候嗜历,application.properties經(jīng)常使用它來配置一些可以手動(dòng)修改而且不用編譯的變量宣渗。這樣我們?cè)诖虺蓋ar包或者jar包用于生產(chǎn)環(huán)境時(shí),我們可以直接通過application.properties配置文件來修改環(huán)境變量梨州,而不用再次重新編譯痕囱。
Spring Boot幾乎所有的配置項(xiàng)都可以在這個(gè)文件中配置,如果不配置暴匠,則使用默認(rèn)項(xiàng)鞍恢。Spring Boot會(huì)檢測(cè)配置項(xiàng)的key,啟動(dòng)相應(yīng)的自動(dòng)配置模塊每窖。
提示:這個(gè)application.properties里面到底有哪些key是可配置的呢帮掉?在SpringBoot官網(wǎng)文檔給出了詳盡的配置以及說明。
參考 Appendix A. Common application properties中: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#common-application-properties
這個(gè)完整的application properties文件窒典,有1000多行蟆炊,屬性key有900多個(gè)。當(dāng)你看到如此龐大的配置瀑志,你一定會(huì)被嚇到涩搓。不過污秆,在實(shí)際項(xiàng)目中,我們?nèi)绻裱璖pring Boot的約定昧甘,通常不需要我們單獨(dú)指定太多配置良拼。這里SpringBoot的實(shí)現(xiàn)方案,充分體現(xiàn)了Spring框架的“約定優(yōu)于配置”理念充边。通過約定俗成的規(guī)范庸推,很多問題的解決講得到大大的簡(jiǎn)化。
雖然是零XML配置浇冰,但是“有些配置的事情”予弧,還是必須要做的。
2.3.2 yml 格式的配置文件
相對(duì)于屬性文件來說湖饱,application.yml 是一個(gè)更好的配置文件格式掖蛤。
當(dāng)有同一前綴大量使用的情況下,使用.yml格式的配置文件會(huì)更加簡(jiǎn)單井厌。例如上面的使用 JPA 的數(shù)據(jù)源的配置蚓庭,我們使用 yml 格式配置如下
# datasource: unicode編碼的支持,設(shè)定為utf-8
spring:
datasource:
url: jdbc:mysql://localhost:3306/blog?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&characterSetResults=utf8
username: root
password: root
testWhileIdle: true
validationQuery: SELECT 1
spring:
jpa:
database: MYSQL
show-sql: true
# Hibernate ddl auto (create, create-drop, update)
hibernate:
ddl-auto: update
# Naming strategy
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
注意:使用.yml時(shí)仅仆,屬性名的值和冒號(hào)中間必須有空格器赞。它的基本語法規(guī)則如下:
- 區(qū)分大小寫
- 使用縮進(jìn)表示層級(jí)關(guān)系
- 縮進(jìn)時(shí)不允許使用Tab鍵,只允許使用空格墓拜。
- 縮進(jìn)的空格數(shù)目不重要港柜,只要相同層級(jí)的元素左側(cè)對(duì)齊即可
-
#
表示注釋,從這個(gè)字符一直到行尾咳榜,都會(huì)被解析器忽略夏醉。
只要將SnakeYAML 庫(kù)放到classpath下,SpringApplication就會(huì)自動(dòng)支持YAML涌韩,以作為.properties的替換畔柔。當(dāng)然,我們通常不需要這么做臣樱,因?yàn)槲覀円话愣紩?huì)使用Starters靶擦,在spring-boot-starter里已經(jīng)集成了SnakeYAML,所以不需要我們單獨(dú)去添加該依賴雇毫。
2.4 配置服務(wù)端口號(hào)
Spring Boot默認(rèn)已經(jīng)配置了很多環(huán)境變量玄捕,例如,tomcat的默認(rèn)端口是8080棚放,項(xiàng)目的contextpath是“/”等等枚粘。
我們?cè)谏弦徽轮校褂玫氖悄J(rèn)的服務(wù)端口8080席吴。如果我們想自定義端口號(hào)赌结,在SpringBoot中怎么搞?
很簡(jiǎn)單捞蛋,在application.properties中只需要一行配置即可孝冒。
server.port=5678
如果是在application.yml中
server:
port: 8080
注意:冒號(hào)之后有空格柬姚。
啟動(dòng)應(yīng)用,你將看到:
2017-04-04 23:31:21.673 INFO 90250 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2017-04-04 23:31:21.774 INFO 90250 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 5678 (http)
2017-04-04 23:31:21.780 INFO 90250 --- [ main] com.example.DemoApplication : Started DemoApplication in 4.712 seconds (JVM running for 5.511)
TomcatEmbeddedServletContainer已經(jīng)在5678端口監(jiān)聽請(qǐng)求了庄涡。
瀏覽器訪問:http://localhost:5678/hello
你會(huì)看到成功輸出:
Hello World! Tue Apr 04 23:32:38 CST 2017
2.5 配置 Profile
一般在一個(gè)項(xiàng)目中量承,總是會(huì)有好多個(gè)環(huán)境。通常的應(yīng)用部署會(huì)包含開發(fā)穴店、測(cè)試和生產(chǎn)等若干個(gè)環(huán)境撕捍。比如:
開發(fā)環(huán)境 -> 測(cè)試環(huán)境 -> 預(yù)發(fā)布環(huán)境 -> 生產(chǎn)環(huán)境
在開發(fā)中, 通常針對(duì)不同的環(huán)境我們都會(huì)有不同的配置。例如日志打印泣洞、數(shù)據(jù)庫(kù)連接等忧风,開發(fā)、測(cè)試球凰、生產(chǎn)等每個(gè)環(huán)境的配置可能都不一樣狮腿。
Spring Boot支持通過不同的profile來配置不同環(huán)境的配置。
---
#開發(fā)環(huán)境配置
spring:
profiles: dev
server:
port: 8080
---
#測(cè)試環(huán)境配置
spring:
profiles: test
server:
port: 8081
---
#生產(chǎn)環(huán)境配置
spring:
profiles: prod
server:
port: 8082
application.yml配置文件中呕诉,我們使用一組(---)來作為分隔符缘厢。
然后,我們通過spring.profiles.active來指定采用哪個(gè) profiles
spring:
profiles:
active: dev
這樣我們可以控制本地啟動(dòng)調(diào)用 dev 環(huán)境的配置文件甩挫。
如果是部署到服務(wù)器的話,我們正常打成jar包,發(fā)布是時(shí)候,采用:
--spring.profiles.active=dev (test贴硫、pro) 來控制加載哪個(gè)環(huán)境的配置,完整命令如下:
java -jar xxxxx.jar --spring.profiles.active=test 表示加載測(cè)試環(huán)境test的配置
java -jar xxxxx.jar --spring.profiles.active=prod 表示加載生產(chǎn)環(huán)境prod的配置
2.6 使用 JavaConfig 配置 Profile
Spring 框架本身提供了多種的方式來管理配置屬性文件。Spring 3.1 之前可以使用 PropertyPlaceholderConfigurer伊者。Spring 3.1 引入了新的環(huán)境(Environment)和概要信息(Profile)API英遭,是一種更加靈活的處理不同環(huán)境和配置文件的方式。
Spring Profiles提供了一種隔離應(yīng)用程序配置的方式亦渗,并讓這些配置只在特定的環(huán)境下生效贪绘。任何@Component或@Configuration都能注解@Profile,從而限制加載它的環(huán)境:
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
指定的屬性方式常用的有2種:
1.配置在application.properties中:
spring.profiles.active=production
2.或使用命令行開關(guān):
--spring.profiles.active=production
如果應(yīng)用中包含多個(gè) profile央碟,可以為每個(gè) profile 定義各自的屬性文件税灌,按照application-{profile}.properties(.yml)來命名。
2.7 自定義配置項(xiàng)
我們可以將自己自定義的屬性配置在application.properties中(注意不要和Spring Boot的默認(rèn)配置的key重復(fù))亿虽,然后在java類中通過@Value("${屬性名}")注解來加載對(duì)應(yīng)的配置屬性菱涤,例如:application.properties文件中有如下自定義配置項(xiàng):
com.easy.springboot.h5perf.app.name = H5性能測(cè)試平臺(tái)
則在java中有如下應(yīng)用:
@Component
public class TestProperties {
@Value("${com.easy.springboot.h5perf.app.name }")
private String appName;
}
Spring Boot使用application.properties默認(rèn)了很多配置。但需要自己添加一些配置的時(shí)候洛勉,我們應(yīng)該怎么做呢粘秆。
例如,下面這段yml格式的配置
environments:
dev:
url: http://dev.easy.springboot.com
name: Easy Spring Boot
會(huì)轉(zhuǎn)化為:
environments.dev.url=http://dev.easy.springboot.com
environments.dev.name=Easy Spring Boot
如果我們自定義了屬性key收毫,在代碼中怎樣使用上面的配置信息呢攻走?利用Spring DataBinder工具集殷勘,Spring Boot通過注解@ConfigurationProperties 和@EnableConfigurationProperties 來完成這件事情。
在代碼中對(duì)應(yīng)的Bean對(duì)象:
@ConfigurationProperties(prefix="environments")
public class EnvironmentsConfig {
private String url;
private String name;
public String getUrl(){ return this.url; }
public void setUrl(String url){ this.url = url; }
public String getName(){ return this.name; }
public void setName(){ this.name = name; }
}
有些時(shí)候昔搂,我們還會(huì)配置類似下面這樣的列表的屬性
my:
servers:
- dev1.easy.com
- dev2.easy.com
會(huì)轉(zhuǎn)化為:
my.servers[0]=dev1.easy.com
my.servers[1]=dev2.easy.com
使用@ConfigurationProperties這個(gè)注解來實(shí)現(xiàn)屬性Bean的綁定玲销,需要在Bean里面添加一個(gè)java.util.List(或者Set)類型的屬性,然后寫好setter(setter也可以換成初始化一個(gè)對(duì)象)摘符,getter:
@ConfigurationProperties(prefix="my")
public class ServersConfig {
private List<String> servers = new ArrayList<String>();//initialize it with a mutable value贤斜, equals a setter
public List<String> getServers() {
return this.servers;
}
}
YamlPropertySourceLoader類能夠?qū)AML作為PropertySource導(dǎo)出到Spring Environment。所以我們可以使用常用的@Value注解配合占位符語法來訪問yml 中的屬性逛裤。
另外瘩绒,當(dāng)我們使用@ConfigurationProperties注解定義配置的Bean時(shí),需要在SpringBoot Application啟動(dòng)類上標(biāo)注@EnableConfigurationProperties带族。
2.8 配置的優(yōu)先級(jí)
常規(guī)情況下锁荔,我們都知道Spring Boot的配置會(huì)從application.properties中讀取。實(shí)際上蝙砌,從resource目錄下的application.properties文件讀取是Spring Boot配置鏈中的一環(huán)而已阳堕。
Spring Boot提供了一種優(yōu)先級(jí)配置讀取的機(jī)制來幫助我們從這種困境中走出來。
Spring Boot 所提供的配置優(yōu)先級(jí)順序比較復(fù)雜拍霜。按照優(yōu)先級(jí)從高到低的順序嘱丢,具體的列表(從高到低)如下所示。
- 命令行參數(shù)(優(yōu)先級(jí)最高)祠饺。
- 通過 System.getProperties() 獲取的 Java 系統(tǒng)參數(shù)越驻。
- 操作系統(tǒng)環(huán)境變量。
- 從 java:comp/env 得到的 JNDI 屬性道偷。
- 通過 RandomValuePropertySource 生成的random.*屬性缀旁。
- jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件,通過spring.config.location參數(shù)指定
- jar包內(nèi)部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
- jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
- jar包內(nèi)部的application.properties或application.yml(不帶spring.profile)配置文件
- 應(yīng)用 Java配置類勺鸦,包含@Configuration注解的 Java 類并巍,通過@PropertySource注解聲明的屬性文件。
- 通過SpringApplication.setDefaultProperties聲明的默認(rèn)屬性换途。
如果Spring Boot在優(yōu)先級(jí)更高的位置找到了配置懊渡,那么它就會(huì)覆蓋優(yōu)先級(jí)低的配置。
Spring Boot 的這個(gè)配置優(yōu)先級(jí)看似復(fù)雜军拟,其實(shí)是很合理的剃执。命令行參數(shù)的優(yōu)先級(jí)之所以被設(shè)置為最高,是因?yàn)榭梢苑奖阄覀冊(cè)跍y(cè)試或生產(chǎn)環(huán)境中快速地修改配置參數(shù)值懈息,而不需要重新打包和部署應(yīng)用肾档。
SpringApplication 類默認(rèn)會(huì)把以“--”開頭的命令行參數(shù)轉(zhuǎn)化成應(yīng)用中可以使用的配置參數(shù),如 “--name=Alex” 會(huì)設(shè)置配置參數(shù) “name” 的值為 “Alex”。
如果不需要這個(gè)功能怒见,可以通過
SpringApplication.setAddCommandLineProperties(false)
禁用解析命令行參數(shù)俗慈。
2.9 本章小結(jié)
Spring Boot 它拋棄了Spring 中繁瑣的xml配置文件的方式,聲明式注解的方法為服務(wù)開發(fā)提供快速簡(jiǎn)潔的配置方式遣耍。在Spring Boot 中闺阱,我們會(huì)發(fā)現(xiàn),我們其實(shí)不用做一些基本的配置也能直接運(yùn)行剛創(chuàng)建好的工程項(xiàng)目配阵,因?yàn)樗鼉?nèi)嵌了很多基本的通用的配置組件而不需要我們自己來做一些重復(fù)的配置工作馏颂。
Spring Boot讓環(huán)境配置變得輕松很多示血。
參考資料:
1.https://www.ibm.com/developerworks/cn/java/j-lo-spring-boot/index.html
2.http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#common-application-properties