Spring boot 2 -配置詳解
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
1、自動化配置
Spring Boot 對於開發人員最大的好處在於可以對 Spring 應用進行自動配置。Spring Boot 會根據應用中宣告的第三方依賴來自動配置 Spring 框架,而不需要進行顯式的宣告。比如當聲明瞭對 HSQLDB 的依賴時,Spring Boot 會自動配置成使用 HSQLDB 進行資料庫操作。
Spring Boot 推薦採用基於 Java 註解的配置方式,而不是傳統的 XML。只需要在主配置 Java 類上新增“@EnableAutoConfiguration”註解就可以啟用自動配置。Spring Boot 的自動配置功能是沒有侵入性的,只是作為一種基本的預設實現。開發人員可以通過定義其他 bean 來替代自動配置所提供的功能。比如當應用中定義了自己的資料來源 bean 時,自動配置所提供的 HSQLDB 就不會生效。這給予了開發人員很大的靈活性。既可以快速的建立一個可以立即執行的原型應用,又可以不斷的修改和調整以適應應用開發在不同階段的需要。可能在應用最開始的時候,嵌入式的記憶體資料庫(如 HSQLDB)就足夠了,在後期則需要換成 MySQL 等資料庫。Spring Boot 使得這樣的切換變得很簡單。
2、外部化的配置
在應用中管理配置並不是一個容易的任務,尤其是在應用需要部署到多個環境中時。通常會需要為每個環境提供一個對應的屬性檔案,用來配置各自的資料庫連線資訊、伺服器資訊和第三方服務賬號等。通常的應用部署會包含開發、測試和生產等若干個環境。不同的環境之間的配置存在覆蓋關係。測試環境中的配置會覆蓋開發環境,而生產環境中的配置會覆蓋測試環境。Spring 框架本身提供了多種的方式來管理配置屬性檔案。Spring 3.1 之前可以使用 PropertyPlaceholderConfigurer。Spring 3.1 引入了新的環境(Environment)和概要資訊(Profile)API,是一種更加靈活的處理不同環境和配置檔案的方式。不過 Spring 這些配置管理方式的問題在於選擇太多,讓開發人員無所適從。Spring Boot 提供了一種統一的方式來管理應用的配置,允許開發人員使用屬性檔案、YAML 檔案、環境變數和命令列引數來定義優先順序不同的配置值。
Spring Boot 所提供的配置優先順序順序比較複雜。按照優先順序從高到低的順序,具體的列表如下所示。
- 命令列引數。
- 通過 System.getProperties() 獲取的 Java 系統引數。
- 作業系統環境變數。
- 從 java:comp/env 得到的 JNDI 屬性。
- 通過 RandomValuePropertySource 生成的“random.*”屬性。
- 應用 Jar 檔案之外的屬性檔案。
- 應用 Jar 檔案內部的屬性檔案。
- 在應用配置 Java 類(包含“@Configuration”註解的 Java 類)中通過“@PropertySource”註解宣告的屬性檔案。
- 通過“SpringApplication.setDefaultProperties”宣告的預設屬性。
Spring Boot 的這個配置優先順序看似複雜,其實是很合理的。比如命令列引數的優先順序被設定為最高。這樣的好處是可以在測試或生產環境中快速地修改配置引數值,而不需要重新打包和部署應用。
命令列引數
通過Java -jar app.jar --name="Spring" --server.port=9090
方式來傳遞引數。
SpringApplication 類預設會把以“--”開頭的命令列引數轉化成應用中可以使用的配置引數,如 “--name=Alex” 會設定配置引數 “name” 的值為 “Alex”.
可以使用的引數可以是我們自己定義的,也可以是Spring Boot中預設的引數。
注意:命令列引數在app.jar
的後面!
可以通過SpringApplication.setAddCommandLineProperties(false)
禁用命令列配置。
Java系統屬性
注意Java系統屬性位置java -Dname="isea533" -jar app.jar
,可以配置的屬性都是一樣的,優先順序不同。
例如java -Dname="isea533" -jar app.jar --name="Spring!"
中name
值為Spring.
有些系統,關於一些資料庫或其他第三方賬戶等資訊,由於安全問題,其配置並不會提前配置在專案中暴露給開發人員。
對於這種情況,我們在執行程式的時候,可以通過引數指定一個外部配置檔案。
以 demo.jar 為例,方法如下: java -jar demo.jar --spring.config.location=/opt/config/application.properties
其中檔名隨便定義,無固定要求。
RandomValuePropertySource
RandomValuePropertySource 可以用來生成測試所需要的各種不同型別的隨機值,從而免去了在程式碼中生成的麻煩。RandomValuePropertySource 可以生成數字和字串。數字的型別包含 int 和 long,可以限定數字的大小範圍。以“random.”作為字首的配置屬性名稱由 RandomValuePropertySource 來生成:
系統中用到隨機數的地方,例如 使用 RandomValuePropertySource 生成的配置屬性:
user.id=${random.value}user.count=${random.int}user.max=${random.long}user.number=${random.int(100)}user.range=${random.int[100, 1000]
random.int*
支援value
引數和,max
引數,當提供max
引數的時候,value
就是最小值
3、屬性檔案
3.1 屬性配置檔案的位置
屬性檔案是最常見的管理配置屬性的方式。Spring Boot 提供的 SpringApplication 類會搜尋並載入 application.properties 或application.yml檔案來獲取配置屬性值。SpringApplication 類會在下面位置搜尋該檔案。
- 當前目錄的“/config”子目錄。
- 當前目錄。
- classpath 中的“/config”包。
- classpath
上面的順序也表示了該位置上包含的屬性檔案的優先順序。優先順序按照從高到低的順序排列。 即:/config優先於classpath根目錄
可以通過“spring.config.name”配置屬性來指定不同的屬性檔名稱。也可以通過“spring.config.location”來新增額外的屬性檔案的搜尋路徑。如果應用中包含多個 profile,可以為每個 profile 定義各自的屬性檔案,按照“application-{profile}”來命名。
3.2應用配置檔案(.properties或.yml)
在配置檔案application.properties 中直接寫:
name=Isea533
server.port=8080
.yml格式的配置檔案如:
name: Isea533
server:
port: 8080
當有字首的情況下,使用.yml格式的配置檔案更簡單。關於.yml配置檔案用法請看這裡
注意:使用.yml時,屬性名的值和冒號中間必須有空格,如name: Isea533正確,name:Isea533就是錯的。
3.3 @PropertySource優先順序比較
這個註解可以指定具體的屬性配置檔案,優先順序比較低。
SpringApplication.setDefaultProperties
例如:
SpringApplication application = new SpringApplication(Application.class);Map<String, Object> defaultMap = new HashMap<String, Object>();defaultMap.put("name", "Isea-Blog");//還可以是Properties物件application.setDefaultProperties(defaultMap);application.run(args);
3.5 應用程式使用屬性@Value(“${xxx}”)
對於配置屬性,可以在程式碼中通過“@Value”來使用,如:
@[email protected] class Application { @Value("${name}") private String name; @RequestMapping("/") String home() { return String.format("Hello %s!", name); }}
變數 name 的值來自配置屬性中的“name”屬性。
比如application.properties有 port=8081
則
@Value("${port:8082}")
private String port;
即可獲取8081這個值
3.6屬性佔位符
例如:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
可以在配置檔案中引用前面配置過的屬性(優先順序前面配置過的這裡都能用)。
通過如${app.name:預設名稱}方法還可以設定預設值,當找不到引用的屬性時,會使用預設的屬性。
由於${}方式會被Maven處理。如果你pom繼承的spring-boot-starter-parent,Spring Boot 已經將maven-resources-plugins預設的${}方式改為了@ @方式,例如@[email protected]。
如果你是引入的Spring Boot,你可以修改使用其他的分隔符
3.7通過屬性佔位符還能縮短命令引數
例如修改web預設埠需要使用--server.port=9090方式,如果在配置中寫上:
server.port=${port:8080}
那麼就可以使用更短的--port=9090,當不提供該引數的時候使用預設值8080。
3.8屬性名匹配規則
例如有如下配置物件:
@Component@ConfigurationProperties(prefix="person")public class ConnectionSettings { private String firstName;}
firstName可以使用的屬性名如下:
person.firstName,標準的駝峰式命名
person.first-name,虛線(-)分割方式,推薦在.properties和.yml配置檔案中使用
PERSON_FIRST_NAME,大寫下劃線形式,建議在系統環境變數中使用
3.9屬性驗證
可以使用JSR-303註解進行驗證,例如:
@Component@ConfigurationProperties(prefix="connection")public class ConnectionSettings { @NotNull private InetAddress remoteAddress; // ... getters and setters}
4、自定義配置
spring boot使用application.properties默認了很多配置。但需要自己新增一些配置的時候,我們應該怎麼做呢。
若繼續在application.properties中新增
如:
wisely2.name=wyf2 wisely2.gender=male2
定義配置類:
@ConfigurationProperties(prefix = "wisely2") public class Wisely2Settings { private String name; private String gender; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
若新用新的配置檔案
如我新建一個wisely.properties
wisely.name=wangyunfei wisely.gender=male
需定義如下配置類
@ConfigurationProperties(prefix = "wisely",locations = "classpath:config/wisely.properties") public class WiselySettings { private String name; private String gender; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
最後注意在spring Boot入口類加上@EnableConfigurationProperties
@SpringBootApplication
@EnableConfigurationProperties({WiselySettings.class,Wisely2Settings.class})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
使用定義的properties
在別的bean中可直接注入
@Controller public class TestController { @Autowired WiselySettings wiselySettings; @Autowired Wisely2Settings wisely2Settings; @RequestMapping("/test") public @ResponseBody String test(){ System.out.println(wiselySettings.getGender()+"---"+wiselySettings.getName()); System.out.println(wisely2Settings.getGender()+"==="+wisely2Settings.getGender()); return "ok"; } }
或者
在@Bean方法上使用@ConfigurationProperties
例如:
@ConfigurationProperties(prefix = "foo")@Beanpublic FooComponent fooComponent() { ...}
Spring Boot 會將foo開頭的屬性按照名字匹配注入到FooComponent物件中。
涉及四個檔案:
1:properties檔案,這裡是config.properties,放置在properties檔案常放置的地方,即src/main/resources目錄下
2:一個存放properties配置檔案屬性的Bean,這裡是WiselySettings.Java
4:在spring Boot入口類加上@EnableConfigurationProperties
3:讀取配置的Controller或者bean
5、YAML配置
相對於屬性檔案來說,YAML 是一個更好的配置檔案格式。YAML 在 Ruby on Rails 中得到了很好的應用。SpringApplication 類也提供了對 YAML 配置檔案的支援,只需要新增對 SnakeYAML 的依賴即可。application.yml 檔案的示例。
spring: profiles: developmentdb: url: jdbc:hsqldb:file:testdb username: sa password:---spring: profiles: testdb: url: jdbc:mysql://localhost/test username: test password: test
AML 檔案同時給出了 development 和 test 兩個不同的 profile 的配置資訊,這也是 YAML 檔案相對於屬性檔案的優勢之一。除了使用“@Value”註解繫結配置屬性值之外,還可以使用更加靈活的方式。YAML 檔案的 Java 類:
@[email protected](prefix="db")public class DBSettings { private String url; private String username; private String password;}
通過“@ConfigurationProperties(prefix="db")”註解,配置屬性中以“db”為字首的屬性值會被自動繫結到 Java 類中同名的域上,如 url 域的值會對應屬性“db.url”的值。只需要在應用的配置類中新增“@EnableConfigurationProperties”註解就可以啟用該自動繫結功能。
6. @EnableAutoCongiguration配置
從Spring 3.0開始,為了替代繁瑣的XML配置,引入了@Enable...
註解對@Configuration
類進行修飾以達到和XML配置相同的效果。想必不少開發者已經使用過類似註解:
@EnableTransactionManagement
開啟Spring事務管理,相當於XMl中的<tx:*>
@EnableWebMvc
使用Spring MVC框架的一些預設配置@EnableScheduling
會初始化一個Scheduler用於執行定時任務和非同步任務
Spring Boot提供的@EnableAutoCongiguration
似乎功能更加強大,一旦加上,上述所有的配置似乎都被包含進來而無需開發者顯式宣告。它究竟是如何做到的呢,先看看它的定義:
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import({ EnableAutoConfigurationImportSelector.class, AutoConfigurationPackages.Registrar.class })public @interface EnableAutoConfiguration { /** * Exclude specific auto-configuration classes such that they will never be applied. */ Class<?>[] exclude() default {};}
EnableAutoConfigurationImportSelector
使用的是spring-core
模組中的SpringFactoriesLoader#loadFactoryNames()
方法,它的作用是在類路徑上掃描META-INF/spring.factories
檔案中定義的類:
# Initializersorg.springframework.context.ApplicationContextInitializer=\org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\org.springframework.boot.autoconfigure.mongo.MongoTemplateAutoConfiguration,\org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration
實際上這就是Spring Boot會自動配置的一些物件,例如前面提到的Web框架由EmbeddedServletContainerAutoConfiguration
,DispatcherServletAutoConfiguration
, ServerPropertiesAutoConfiguration
等配置完成,而DataSource
的自動配置則是由DataSourceAutoConfiguration
完成。現在我們以Mongo的配置MongoAutoConfiguration
為例,來探索Spring Boot是如何完成這些配置的:
@Configuration@ConditionalOnClass(Mongo.class)@EnableConfigurationProperties(MongoProperties.class)public class MongoAutoConfiguration { @Autowired private MongoProperties properties; private Mongo mongo; @PreDestroy public void close() throws UnknownHostException { if (this.mongo != null) { this.mongo.close(); } } @Bean @ConditionalOnMissingBean public Mongo mongo() throws UnknownHostException { this.mongo = this.properties.createMongoClient(); return this.mongo; }}
首先這是一個Spring的配置@Configuration
,它定義了我們訪問Mongo需要的@Bean
,如果這個@Configuration
被Spring Context掃描到,那麼Context中自然也就有兩個一個Mongo
物件能夠直接為開發者所用。
但是注意到其它幾個Spring註解:
@ConditionOnClass
表明該@Configuration
僅僅在一定條件下才會被載入,這裡的條件是Mongo.class
位於類路徑上@EnableConfigurationProperties
將Spring Boot的配置檔案(application.properties
)中的spring.data.mongodb.*
屬性對映為MongoProperties
並注入到MongoAutoConfiguration
中。@ConditionalOnMissingBean
說明Spring Boot僅僅在當前上下文中不存在Mongo
物件時,才會例項化一個Bean。這個邏輯也體現了Spring Boot的另外一個特性——自定義的Bean優先於框架的預設配置,我們如果顯式的在業務程式碼中定義了一個Mongo
物件,那麼Spring Boot就不再建立。
接下來看一看MongoProperties
:
@ConfigurationProperties(prefix = "spring.data.mongodb")public class MongoProperties { private String host; private int port = DBPort.PORT; private String uri = "mongodb://localhost/test"; private String database; // ... getters/ setters omitted}
顯然,它就是以spring.data.mongodb
作為字首的屬性,然後通過名字直接對映為物件的屬性,同時還包含了一些預設值。如果不配置,那麼mongo.uri
就是mongodb://localhost/test
。
配置通用屬性
Spring Boot application.propertis配置檔案的相關通用屬性
Spring Boot application.yaml配置檔案的相關通用屬性
感謝您的支援,我會繼續努力的! 掃碼打賞,你說多少就多少