为了可以在不一样的环境运行不一样的配置文件,或者有些代码的一些变量是跟随着环境的改变而改变的,这时候就须要在外部作一些配置。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
的参考资料: