spring boot最佳實戰2--外部配置
Spring Boot允許外化(externalize)你的配置,這樣你能夠在不同的環境下使用相同的程式碼。你可以使用properties檔案,YAML檔案,環境變數和命令列引數來外化配置。使用@Value註解,可以直接將屬性值注入到你的beans中,並通過Spring的Environment抽象或繫結到結構化物件來訪問。
Spring Boot使用一個非常特別的PropertySource次序來允許對值進行合理的覆蓋,需要以下面的次序考慮屬性:
命令列引數
來自於java:comp/env的JNDI屬性
Java系統屬性(System.getProperties())
作業系統環境變數
只有在random.*裡包含的屬性會產生一個RandomValuePropertySource
在打包的jar外的應用程式配置檔案(application.properties,包含YAML和profile變數)
在打包的jar內的應用程式配置檔案(application.properties,包含YAML和profile變數)
在@Configuration類上的@PropertySource註解
預設屬性(使用SpringApplication.setDefaultProperties指定)
下面是一個具體的示例(假設你開發一個使用name屬性的@Component):
import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;
@Component
public class MyBean {
@Value("${name}") private String name;
}
你可以將一個application.properties檔案捆綁到jar內,用來提供一個合理的預設name屬性值。當執行在生產環境時,可以在jar外提供一個application.properties檔案來覆蓋name屬性。對於一次性的測試,你可以使用特定的命令列開關啟動(比如,java -jar app.jar --name="Spring")。
配置隨機值
RandomValuePropertySource在注入隨機值(比如,金鑰或測試用例)時很有用。它能產生整數,longs或字串,比如:
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
random.int*語法是OPEN value (,max) CLOSE,此處OPEN,CLOSE可以是任何字元,並且value,max是整數。如果提供max,那麼value是最小的值,max是最大的值(不包含在內)。
訪問命令列屬性
預設情況下,SpringApplication將任何可選的命令列引數(以'--'開頭,比如,--server.port=9000)轉化為property,並將其新增到Spring Environment中。如上所述,命令列屬性總是優先於其他屬性源。
如果你不想將命令列屬性新增到Environment裡,你可以使用SpringApplication.setAddCommandLineProperties(false)來禁止它們。
application屬性檔案
SpringApplication將從以下位置載入application.properties檔案,並把它們新增到Spring Environment中:
當前目錄下的一個/config子目錄
當前目錄
一個classpath下的/config包
classpath根路徑(root)
這個列表是按優先順序排序的(列表中位置高的將覆蓋位置低的)。
注:你可以使用YAML('.yml')檔案替代'.properties'。
如果不喜歡將application.properties作為配置檔名,你可以通過指定spring.config.name環境屬性來切換其他的名稱。你也可以使用spring.config.location環境屬性來引用一個明確的路徑(目錄位置或檔案路徑列表以逗號分割)。
$ java -jar myproject.jar --spring.config.name=myproject//or$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
如果spring.config.location包含目錄(相對於檔案),那它們應該以/結尾(在載入前,spring.config.name產生的名稱將被追加到後面)。不管spring.config.location是什麼值,預設的搜尋路徑classpath:,classpath:/config,file:,file:config/總會被使用。以這種方式,你可以在application.properties中為應用設定預設值,然後在執行的時候使用不同的檔案覆蓋它,同時保留預設配置。
注:如果你使用環境變數而不是系統配置,大多數作業系統不允許以句號分割(period-separated)的key名稱,但你可以使用下劃線(underscores)代替(比如,使用SPRING_CONFIG_NAME代替spring.config.name)。如果你的應用執行在一個容器中,那麼JNDI屬性(java:comp/env)或servlet上下文初始化引數可以用來取代環境變數或系統屬性,當然也可以使用環境變數或系統屬性。
特定的Profile屬性
除了application.properties檔案,特定配置屬性也能通過命令慣例application-{profile}.properties來定義。特定Profile屬性從跟標準application.properties相同的路徑載入,並且特定profile檔案會覆蓋預設的配置。
屬性佔位符
當application.properties裡的值被使用時,它們會被存在的Environment過濾,所以你能夠引用先前定義的值(比如,系統屬性)。
app.name=MyAppapp.description=${app.name} is a Spring Boot application
使用YAML代替Properties
YAML是JSON的一個超集,也是一種方便的定義層次配置資料的格式。無論你何時將SnakeYAML 庫放到classpath下,SpringApplication類都會自動支援YAML作為properties的替換。
載入YAML
Spring框架提供兩個便利的類用於載入YAML文件,YamlPropertiesFactoryBean會將YAML作為Properties來載入,YamlMapFactoryBean會將YAML作為Map來載入。
示例:
environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App
上面的YAML文件會被轉化到下面的屬性中:
environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App
YAML列表被表示成使用[index]間接引用作為屬性keys的形式,例如下面的YAML:
my:
servers:
- dev.bar.com
- foo.bar.com
將會轉化到下面的屬性中:
my.servers[0]=dev.bar.commy.servers[1]=foo.bar.com
使用@ConfigurationProperties繫結配置到bean時,你需要確定目標bean中有個java.util.List或Set型別的屬性,並且需要提供一個setter或使用可變的值初始化它,比如,下面的程式碼將繫結上面的屬性:
@ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}}
在Spring環境中使用YAML暴露屬性
YamlPropertySourceLoader類能夠用於將YAML作為一個PropertySource匯出到Sprig Environment。這允許你使用熟悉的@Value註解和佔位符語法訪問YAML屬性。
Multi-profile YAML文件
你可以在單個檔案中定義多個特定配置(profile-specific)的YAML文件,並通過一個spring.profiles key標示應用的文件。例如:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120
在上面的例子中,如果development配置被啟用,那server.address屬性將是127.0.0.1。如果development和production配置(profiles)沒有啟用,則該屬性的值將是192.168.1.100。
YAML缺點
YAML檔案不能通過@PropertySource註解載入。所以,在這種情況下,如果需要使用@PropertySource註解的方式載入值,那就要使用properties檔案。
型別安全的配置屬性
使用@Value("${property}")註解注入配置屬性有時可能比較笨重,特別是需要使用多個properties或你的資料本身有層次結構。為了控制和校驗你的應用配置,Spring Boot提供一個允許強型別beans的替代方法來使用properties。
示例:
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
private String username;
private InetAddress remoteAddress;
// ... getters and setters
}
當@EnableConfigurationProperties註解應用到你的@Configuration時,任何被@ConfigurationProperties註解的beans將自動被Environment屬性配置。這種風格的配置特別適合與SpringApplication的外部YAML配置進行配合使用。
為了使用@ConfigurationProperties beans,你可以使用與其他任何bean相同的方式注入它們。
@Service
public class MyService {
@Autowired
private ConnectionSettings connection;
//...
@PostConstruct
public void openConnection() {
Server server = new Server();
this.connection.configure(server);
}
}
你可以通過在@EnableConfigurationProperties註解中直接簡單的列出屬性類來快捷的註冊@ConfigurationProperties bean的定義。
@Configuration
@EnableConfigurationProperties(ConnectionSettings.class)
public class MyConfiguration {
}
第三方配置
正如使用@ConfigurationProperties註解一個類,你也可以在@Bean方法上使用它。當你需要繫結屬性到不受你控制的第三方元件時,這種方式非常有用。
為了從Environment屬性配置一個bean,將@ConfigurationProperties新增到它的bean註冊過程:
@ConfigurationProperties(prefix = "foo")
@Bean
public FooComponent fooComponent() {
...
}
和上面ConnectionSettings的示例方式相同,任何以foo為字首的屬性定義都會被對映到FooComponent上。
@ConfigurationProperties校驗
Spring Boot將嘗試校驗外部的配置,預設使用JSR-303(如果在classpath路徑中)。你可以輕鬆的為你的@ConfigurationProperties類新增JSR-303 javax.validation約束註解:
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
@NotNull private InetAddress remoteAddress;
}
Profiles
Spring Profiles提供了一種隔離應用程式配置的方式,並讓這些配置只能在特定的環境下生效。任何@Component或@Configuration都能被@Profile標記,從而限制載入它的時機。
@Configuration
@Profile("production")
public class ProductionConfiguration {
}
以正常的Spring方式,你可以使用一個spring.profiles.active的Environment屬性來指定哪個配置生效。你可以使用平常的任何方式來指定該屬性,例如,可以將它包含到你的application.properties中:
spring.profiles.active=dev,hsqldb
或使用命令列開關:
--spring.profiles.active=dev,hsqldb
新增啟用的配置(profiles)
spring.profiles.active屬性和其他屬性一樣都遵循相同的排列規則,最高的PropertySource獲勝。也就是說,你可以在application.properties中指定生效的配置,然後使用命令列開關替換它們。
以程式設計方式設定profiles
在應用執行前,你可以通過呼叫SpringApplication.setAdditionalProfiles(…)方法,以程式設計的方式設定生效的配置。使用Spring的ConfigurableEnvironment介面激動配置也是可行的。
日誌
Spring Boot內部日誌系統使用的是Commons Logging,但開放底層的日誌實現。預設為會Java Util Logging, Log4J, Log4J2和Logback提供配置。每種情況下都會預先配置使用控制檯輸出,也可以使用可選的檔案輸出。
預設情況下,如果你使用'Starter POMs',那麼就會使用Logback記錄日誌。為了確保那些使用Java Util Logging, Commons Logging, Log4J或SLF4J的依賴庫能夠正常工作,正確的Logback路由也被包含進來。
注:如果上面的列表看起來令人困惑,不要擔心,Java有很多可用的日誌框架。通常,你不需要改變日誌依賴,Spring Boot預設的就能很好的工作。
檔案輸出
預設情況下,Spring Boot只會將日誌記錄到控制檯而不會寫進日誌檔案。如果除了輸出到控制檯你還想寫入到日誌檔案,那你需要設定logging.file或logging.path屬性
日誌檔案每達到10M就會被輪換(分割),和控制檯一樣,預設記錄ERROR, WARN和INFO級別的資訊。
日誌級別
所有支援的日誌系統在Spring的Environment(例如在application.properties裡)都有通過'logging.level.*=LEVEL'('LEVEL'是TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF中的一個)設定的日誌級別。
示例:application.properties
logging.level.org.springframework.web: DEBUGlogging.level.org.hibernate: ERROR
自定義日誌配置
通過將適當的庫新增到classpath,可以啟用各種日誌系統。然後在classpath的根目錄(root)或通過Spring Environment的logging.config屬性指定的位置提供一個合適的配置檔案來達到進一步的定製(注意由於日誌是在ApplicationContext被建立之前初始化的,所以不可能在Spring的@Configuration檔案中,通過@PropertySources控制日誌。系統屬性和平常的Spring Boot外部配置檔案能正常工作)。
根據你的日誌系統,下面的檔案會被載入:
日誌系統
定製
Logback
logback.xml
Log4j
log4j.properties或log4j.xml
Log4j2
log4j2.xml
JDK (Java Util Logging)
logging.properties
相關文章
- Spring Boot 外部化配置實戰解析Spring Boot
- # Spring Boot 外部化配置實戰解析Spring Boot
- Spring Boot外部化配置實戰解析Spring Boot
- Spring Boot自動配置原理、實戰Spring Boot
- Spring Boot實戰系列(7)整合Consul配置中心Spring Boot
- 從零開始學Spring Boot系列-外部化配置Spring Boot
- [翻譯]Spring Boot 特徵參考2——外部配置:下Spring Boot特徵
- Spring Boot 2 實戰:常用讀取配置的方式Spring Boot
- Spring Boot功能實戰Spring Boot
- 程式設計實戰篇——Spring Boot 自動配置實現程式設計Spring Boot
- Spring Boot:Spring Boot配置MybatisSpring BootMyBatis
- Spring Boot:Spring Boot配置SwaggerSpring BootSwagger
- Spring Boot實戰:模板引擎Spring Boot
- Spring Boot 整合 Elasticsearch 實戰Spring BootElasticsearch
- Spring Boot 安全性最佳實踐Spring Boot
- 10個Spring Boot效能最佳實踐Spring Boot
- Spring Boot整合Redis實戰操作Spring BootRedis
- Spring Boot & 配置Spring Boot
- Spring Boot專案部署到外部TomcatSpring BootTomcat
- Spring Boot 最佳實踐(一)快速入門Spring Boot
- 《Spring Boot 實戰紀實》之需求管理Spring Boot
- Spring Boot應用監控實戰Spring Boot
- Spring Boot讀取自定義外部屬性Spring Boot
- Spring Boot讀取外部配置檔案失敗,原因絕對出乎你意料Spring Boot
- spring boot 配置 JPASpring Boot
- Spring Boot核心配置Spring Boot
- Spring Boot 最佳實踐(三)模板引擎FreeMarker整合Spring Boot
- Spring Boot資料儲存最佳實踐 - AhadSpring Boot
- 《Spring Boot 實戰紀實》缺失的邏輯Spring Boot
- Spring boot學習(二) Spring boot基礎配置Spring Boot
- Spring Boot學習筆記:Spring Boot核心配置Spring Boot筆記
- 持續整合之 Spring Boot 實戰篇Spring Boot
- spring boot實戰讀書筆記(1)Spring Boot筆記
- Spring Boot Serverless 實戰系列 | 效能調優Spring BootServer
- Spring Boot 2.x實戰之StateMachineSpring BootMac
- 《Spring Boot 實戰紀實》之關鍵點文件Spring Boot
- Spring Boot 配置檔案Spring Boot
- Spring Boot中配置 AuditListenerSpring Boot
- spring boot 配置外接tomcatSpring BootTomcat