spring boot 与配置

Spring Boot允许外化(externalize)你的配置,这样你能够在不同的环境下使用相同的代码。你可以使用properties文件YAML文件环境变量命令行参数来外化配置。使用@Value注解,可以直接将属性值注入到你的beans中,并通过Spring的Environment抽象或绑定到结构化对象来访问。
Spring Boot使用PropertySource次序来允许对值进行合理的覆盖,需要以下面的次序考虑属性:

  1. 命令行参数
  2. 来自于java:comp/env的JNDI属性
  3. Java系统属性(System.getProperties()
  4. 操作系统环境变量只有在random.*里包含的属性会产生一个RandomValuePropertySource
  5. 在打包的jar外的应用程序配置文件(application.properties,包含YAML和profile变量)
  6. 在打包的jar内的应用程序配置文件(application.properties,包含YAML和profile变量)
  7. @Configuration类上的@PropertySource注解
  8. 默认属性(使用SpringApplication.setDefaultProperties指定)

例如:

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")。

默认情况下,SpringApplication将任何可选的命令行参数(以'--'开头,比如,--server.port=9000)转化为property,并将其添加到Spring Environment中。如上所述,命令行属性总是优先于其他属性源
如果你不想将命令行属性添加到Environment里,你可以使用SpringApplication.setAddCommandLineProperties(false)来禁止它们。

注意:在命令行添加的参数会添加到Spring Environment。

配置随机值

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是最大的值(不包含在内)。

Application属性

SpringApplication将从以下位置加载application.properties文件,并把它们添加到Spring Environment中:

  1. 当前目录下的一个/config子目录
  2. 当前目录
  3. 一个classpath下的/config
  4. 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+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-{profile}.properties区别不同的运行环境。例如:

  1. application-dev.properties:开发环境
  2. application-test.properties:测试环境
  3. application-prod.properties:生产环境

至于哪个具体的配置文件会被加载,需要在application.properties文件中通过spring.profiles.active属性来设置,其值对应{profile}值,会加载对应的application-{profile}.properties属性文件。例如在application.properties中设置spring.profiles.active=dev,那么就会加载application-dev.properties作为运行属性。

由于命令行属性可覆盖其他情况下设置的属性,所以使用java -jar jarname.jar --spring.profiles.active=prod会覆盖application.properties中设置的spring.profiles.active=dev,会加载application-prod.properties作为运行时属性。

所以,一般在application.properties中设置spring.profiles.active=dev,在线上环境使用命令行配置的方式覆盖profile设置

占位符语法

application.properties里的值被使用时,它们会被存在的Environment过滤,所以你能够引用先前定义的值(比如,系统属性)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application

上述设置中app.description中的值${app.name},会被之前设置的app.name=MyApp替代。

使用YAML替代properties文件

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.com
my.servers[1]=foo.bar.com

使用Spring DataBinder工具绑定属性(这是@ConfigurationProperties做的事),你需要确定目标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;
    }
}

加载

YamlPropertySourceLoader类能够用于将YAML作为一个PropertySource导出到Sprig Environment。这允许你使用熟悉的@Value注解和占位符语法访问YAML属性。

YAML文件不能通过@PropertySource注解加载。所以,在这种情况下,如果需要使用@PropertySource注解的方式加载值,那就要使用properties文件。

multi-profiles YAML文档

你可以在单个文件中定义多个profile配置(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。

类型安全的配置属性-ConfigurationProperties注解

使用@Value("${property}")注解注入配置属性有时可能比较笨重,特别是需要使用多个properties或你的数据本身有层次结构。为了控制和校验你的应用配置,Spring Boot提供一个允许强类型beans的替代方法来使用properties。

示例:

你可以通过在@EnableConfigurationProperties注解中直接简单的列出属性类来快捷的注册@ConfigurationProperties bean的定义。

@Configuration
@EnableConfigurationProperties(ConnectionSettings.class)
public class MyConfiguration {
}
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
    private String username;
    private InetAddress remoteAddress;
    // ... getters and setters
}

@EnableConfigurationProperties注解应用到你的@Configuration时,任何被@ConfigurationProperties注解的beans将自动被Environment属性配置。这种风格的配置特别适合与SpringApplication的外部YAML配置进行配合使用。

# application.yml
connection:
    username: admin
    remoteAddress: 192.168.1.1
# additional configuration as required

使用:为了使用@ConfigurationProperties beans,你可以使用与其他任何bean相同的方式注入它们。

@Service
public class MyService {
    @Autowired
    private ConnectionSettings connection;
     //...
    @PostConstruct
    public void openConnection() {
        Server server = new Server();
        this.connection.configure(server);
    }
}

第三方类属性设置

@ConfigurationProperties可以方便的设置第三方类的属性,该注解由spring-boot-configuration-processor提供。

为了从Environment属性配置一个bean,将@ConfigurationProperties添加到它的bean注册过程:

@ConfigurationProperties(prefix = "foo")
@Bean
public FooComponent fooComponent() {
    ...
}

和上面ConnectionSettings的示例方式相同,任何以foo为前缀的属性定义都会被映射到FooComponent上。

注: 可以在带有@Component的类或者@bean等,定义bean的时候使用@ConfigurationProperties注解,自动从Spring Environment 获取相关的属性。

松散类型

Spring Boot使用一些宽松的规则用于绑定Environment属性到@ConfigurationProperties beans,所以Environment属性名和bean属性名不需要精确匹配。常见的示例中有用的包括虚线分割(比如,context--path绑定到contextPath)和将环境属性转为大写字母(比如,PORT绑定port)。
示例:

@Component
@ConfigurationProperties(prefix="person")
public class ConnectionSettings {
    private String firstName;
}

下面的属性名都能用于上面的@ConfigurationProperties类:

属性说明
person.firstName标准驼峰规则
person.first-name虚线表示,推荐用于.properties和.yml文件
PERSON_FIRST_NAME大写形式,使用系统环境变量时推荐

Spring会尝试强制外部的应用属性在绑定到@ConfigurationProperties beans时类型是正确的。如果需要自定义类型转换,你可以提供一个ConversionService bean(bean id为conversionService)或自定义属性编辑器(通过一个CustomEditorConfigurer bean)。

@ConfigurationProperties校验

Spring Boot将尝试校验外部的配置,默认使用JSR-303(如果在classpath路径中)。你可以轻松的为你的@ConfigurationProperties类添加JSR-303 javax.validation约束注解:

@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {
    @NotNull
    private InetAddress remoteAddress;
    // ... getters and setters
}

你也可以通过创建一个叫做configurationPropertiesValidator的bean来添加自定义的Spring Validator。

转载于:https://my.oschina.net/hgfdoing/blog/740099

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值