爲了可以在不一樣的環境運行不一樣的配置文件,或者有些代碼的一些變量是跟隨着環境的改變而改變的,這時候就須要在外部作一些配置。SpringBoot容許這麼作,而且有一套配置規則。能夠經過@Value註解進行將一些變量動態的取出來。SpringBoot支持多種的外部配置的方式,其中的優先級以下:html
全局的設置在根目錄中(~/.spring-boot-devtools.properties
)java
@TestPropertySource
在Test模塊中的註解web
@SpringBootTest#properties
也是在Test模塊中spring
命令行json
命令行中的SPRING_APPLICATION_JSONJSON
字符串, 例如java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar
數組
ServletConfig
初始化參數,可在代碼進行配置瀏覽器
ServletContext
初始化參數,可在代碼進行配置緩存
來自java:comp/env
的JNDI屬性app
Java系統屬性(System.getProperties()
)框架
操做系統的環境變量
RandomValuePropertySource
配置的random.*
屬性值
jar外部的帶指定profile
的application.yml
,好比application-{profile}.yml
jar內部的帶指定profile
的application.yml
,好比application-{profile}.yml
jar外部的application.yml
jar內部的application.yml
在自定義的@Configuration
類中定於的@PropertySource
啓動的main方法中,定義的默認配置。SpringApplication.setDefaultProperties
下面給出具體的實例:
@SpringBootApplication @RestController public class FirstSpringBootApplication { @Value("${name}") private String name; @RequestMapping("/") String home() { return name; } public static void main(String[] args) { SpringApplication app = new SpringApplication(FirstSpringBootApplication.class); app.run(args); } }
能夠在application.yml或者application.properties配置文件中設置name的值
application.yml
name: 不學無數
注意在name: 的冒號後面要加空格
application.properties
name=不學無數
這樣在啓動項目的時候而後訪問http:localhost:8080就能夠取出了name的值
<center><img src="http://p9jfgo4wc.bkt.clouddn.com/buxuewushu.png"/></center>
當想要一些隨機值的時候SpringBoot也提供了一些方法,隨機數具體有哪些應用呢,例如能夠防止瀏覽器認爲是相同的資源而去讀取緩存,或者是生成驗證碼,在application.properties配置以下
my.secret=${random.value} --生成隨機字符串 my.number=${random.int} --生成隨機數 my.uuid=${random.uuid} --生成uuid my.number.less.than.ten=${random.int(10)} -- 生成10之內的隨機數 my.number.in.range=${random.int[1024,65536]} --生成1024到65536的隨機數
取出的代碼以下:
@Value("${my.secret}") private String secret; @Value("${my.number}") private String number; @Value("${my.uuid}") private String uuid; @Value("${my.number.less.than.ten}") private Integer ten; @Value("${my.number.in.range}") private Integer range; @RequestMapping("/") String home() { StringBuffer stringBuffer=new StringBuffer(); stringBuffer.append("my.secret:"+secret+"<br/>"); stringBuffer.append("my.number:"+number+"<br/>"); stringBuffer.append("my.uuid:"+uuid+"<br/>"); stringBuffer.append("my.number.less.than.ten}:"+ten+"<br/>"); stringBuffer.append("my.number.in.range:"+range+"<br/>"); return stringBuffer.toString(); }
而後訪問http:localhost:8080
能夠查看到以下的頁面
<center><img src="http://p9jfgo4wc.bkt.clouddn.com/suijishu1.png"/></center>
SpingApplication
默認的可以轉變任何命令行的參數而後將其配置在Spring中,例如--server.port=9000
,那麼web啓動的端口號就變爲了9000。
<center><img src="http://p9jfgo4wc.bkt.clouddn.com/%E7%AB%AF%E5%8F%A3.jpeg"/></center>
而後啓動項目就會發現端口號改變了。
若是不想讓命令行的配置加入到Spring環境中的話,能夠
SpringApplication.setAddCommandLineProperties(false)
進行設置
SpringApplication
會從application.properties
進行加載系統的配置,而且將其配置加入到Spring的環境中
你也可使用YAML('.yml')來代替.properties
若是不想使用application.properties做爲配置文件的名字的話,那麼能夠選擇其餘名字的文件做爲配置文件。能夠具體設置spring.config.name環境變量進行設置。也可使用spring.config.location後面跟文件的全路徑名。
$ java -jar myproject.jar --spring.config.name=myproject
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
spring.config.name和spring.config.location這兩個配置由於是要設置哪一個配置文件起做用的,因此必須在程序啓動以前設置,例如設置在系統的環境變量中,或者是設置在啓動的參數中。
不知道該怎麼翻譯,就把英文給加在後面了,以避免誤人子弟。在公司進行開發的過程當中,也許咱們會碰到這種狀況,例如在開發環境中用的一套配置,而在測試環境是另外一套的配置。因此在不一樣的環境須要有不一樣的配置文件。SpringBoot也提供了這樣一套的配置規則。application-{profile}.properties
。其中的profile
]能夠進行配置化,若是沒有配置的話那麼就會以默認的application-default.properties
爲配置文件。其中profile
的屬性能夠在application.properties
進行配置spring.profiles.active
的值。 application.properties
配置以下
spring.profiles.active=test --即加載application-test.properties 或者spring.profiles.active=dev --即加載application-dev.properties
application-test.properties
name=BuXueWuShu---Test
application-dev.properties
name=BuXueWuShu---Dev
這樣在application.properties中就能夠加載不一樣的配置文件
@Value("${name}") private String name; @RequestMapping("/") String home() { return name; }
經過不一樣的環境配置就能夠訪問不一樣值
固然你也能夠經過上一節的spring.config.location這個啓動的環境變量進行設置想要啓動的時候加載具體哪一個配置文件
當在資源文件中定義過一些變量的時候,若是在一樣的資源文件中要複用,那麼也能夠進行引用。
application.properties配置
my.name=BuXueWuShu my.description=My name is ${my.name}
YAML是針對於JSON的一種擴展,因此作配置文件是很是不錯的選擇。而且在SpringApplication
中若是你引入了spring-boot-starter
的包,那麼SpringApplication
會自動的支持YAML。
Spring框架提供了兩個簡便的類可以解析YAML文檔。YamlPropertiesFactor
yBean解析YAML做爲Properties。YamlMapFactoryBean
解析YAML做爲Map。例以下面的YAML文件中
environments: dev: url: http://dev.example.com name: Developer Setup prod: url: http://another.example.com name: My Cool App
剛纔的例子這個YAML將會被解析成
environments.dev.url=http://dev.example.com environments.dev.name=Developer Setup environments.prod.url=http://another.example.com environments.prod.name=My Cool App
YAML列表將會被替代成數組的類型,根據[index]進行取值
my: servers: - dev.example.com - another.example.com
上面的例子將會被解析成下面這種形式的
my.servers[0]=dev.example.com my.servers[1]=another.example.com
若是你想講這些數據進行取出來的話,新建一個配置類,使用SpringBoot提供的@ConfigurationProperties的註解,而後在此類中得有一個List或者Set集合,而後設置get方法就能將值取出來了,具體實現以下:
@ConfigurationProperties(prefix="my") public class Config { private List<String> servers = new ArrayList<String>(); public List<String> getServers() { return this.servers; } }
在講解application.properties
的時候若是想使用多環境的配置那麼就是設置不一樣的application-{profile}.properties
的文件具體哪一個文件生效能夠在application.properties
中設置spring.profiles.active
屬性便可。可是在YAML如何在不一樣的環境中生效呢?固然第一種辦法就是和application.properties
同樣設置不一樣的yml文件,而後進行設置具體哪一個生效便可。YAML也有另外一種的方法。以下所示
server: address: 192.168.1.100 spring: profiles: active:在此設置具體哪一個profiles生效便可(例如此處填寫 test) 就是adress就是192.168.1.120 --- spring: profiles: development server: address: 127.0.0.1 --- spring: profiles: test server: address: 192.168.1.120
經過"---"設置不一樣的環境的配置屬性
若是你在配置文件中沒有設置spring.profiles.active
屬性那麼配置文件就不知道哪一個生效,因此他會找一個默認的進行設置。只須要設置spring.profiles:default
便可
server: port: 8000 --- spring: profiles: default security: user: password: weak
經過@Value("${property}")
能夠將配置中的屬性在類中取出來,這樣是能夠的,可是若是有多個類型要取或者是要取的有着嚴格的等級。那麼取的時候會有些麻煩,SpringBoot提供了一套能夠經過類型匹配在類中寫出熟悉而後加載到配置文件中。而這也是SpringBoot的一項宗旨,儘可能減小xml的配置。
在yml文件中的配置以下
acme: remote-address: 192.168.1.1 security: username: admin roles: - USER - ADMIN
接收這些配置信息的類以下
package com.example.FirstSpringBoot.Configuration; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.ArrayList; import java.util.Collections; import java.util.List; @ConfigurationProperties("acme") public class AcmeProperties { private boolean enabled; private String remoteAddress; private final Security security = new Security(); public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled=enabled; } public String getRemoteAddress() { return remoteAddress; } public void setRemoteAddress(String remoteAddress) { this.remoteAddress=remoteAddress; } public Security getSecurity() { return security; } public static class Security { private String username; private String password; private List<String> roles = new ArrayList<>(Collections.singleton("USER")); public String getUsername() { return username; } public void setUsername(String username) { this.username=username; } public String getPassword() { return password; } public void setPassword(String password) { this.password=password; } public List<String> getRoles() { return roles; } public void setRoles(List<String> roles) { this.roles=roles; } } }
而後再寫一個類將上面的類進行註冊進Spring中
@Configuration @EnableConfigurationProperties(AcmeProperties.class) public class MyConfiguration { }
而後在任何類中就能夠進行配置了
@Service public class MyService { private final AcmeProperties acmeProperties; @Autowired public MyService(AcmeProperties acmeProperties){ this.acmeProperties=acmeProperties; } @PostConstruct public void openConnection() { System.out.println("remote-address:"+acmeProperties.getRemoteAddress()); System.out.println("username:"+acmeProperties.getSecurity().getUsername()); System.out.println("role:"+acmeProperties.getSecurity().getRoles()); } }
這樣就能夠將配置文件中的屬性從bean中取出來,而不是一個一個@Value進行取了。其中@PostConstruct
註解意思是在加載Servlet的時候進行運行,而且只運行一次。
2018-07-18 17:55:51.593 INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2018-07-18 17:55:51.599 INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2018-07-18 17:55:51.599 INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2018-07-18 17:55:51.599 INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*] 2018-07-18 17:55:51.599 INFO 17487 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*] remote-address:192.168.1.1 username:admin role:[USER, ADMIN]
查看啓動信息就能夠知道,他是在加載Servlet的時候運行的。
若是你的配置想要做爲一個jar包供第三方進行使用,那麼能夠在與配置進行類型匹配的類中即上面提到的AcmeProperties類上面加上@Bean註解。這樣就能夠將配置進行打包傳輸了。
@ConfigurationProperties(prefix = "acme") @Bean public class AcmeProperties() { ... }
SpringBoiot提供了一套對資源文件的校驗。假如在資源文件中某個字段是不可或缺的,只要以下配置便可。
@ConfigurationProperties(prefix="acme") @Validated public class AcmeProperties { @NotNull private String remoteAddress; // ... getters and setters }
此時若是資源文件中沒有定義acme.remoteAddress的值的話那麼在項目啓動的時候就會報錯
Description: Binding to target com.example.FirstSpringBoot.Configuration.AcmeProperties@2eadc9f6 failed: Property: acme.remoteAddress Value: null Reason: 不能爲null
當複雜的資源文件想要校驗怎麼辦?就以下配置便可
@ConfigurationProperties(prefix="acme") @Validated public class AcmeProperties { @NotNull private String remoteAddress; @Valid private final Security security = new Security(); // ... getters and setters public static class Security { @NotEmpty public String username; // ... getters and setters } }
固然這個@Validated
註解是SpringMvc中的註解,這裏就不詳細解釋了。關於@Validated
的參考資料: