10.外化配置

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

  • Spring Boot使用一个非常特别的PropertySource次序来允许对值进行合理的覆盖,需要以下面的次序考虑属性:

  1. 命令行参数
  2. 来自于java:comp/env的JNDI属性
  3. Java系统属性(System.getProperties())
  4. 操作系统环境变量
  5. 只有在random.*里包含的属性会产生一个RandomValuePropertySource
  6. 在打包的jar外的应用程序配置文件(application.properties,包含YAML和profile变量)
  7. 在打包的jar内的应用程序配置文件(application.properties,包含YAML和profile变量)
  8. 在@Configuration类上的@PropertySource注解
  9. 默认属性(使用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中:
  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是什么值,默认的搜索路径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=MyApp
      app.description=${app.name} is a Spring Boot application
    

注:你也能使用相应的技巧为存在的Spring Boot属性创建'短'变量。

使用YAML代替Properties

  • YAML是JSON的一个超集,也是一种方便的定义层次配置数据的格式。无论你何时将SnakeYAML 库放到classpath下,SpringApplication类都会自动支持YAML作为properties的替换。

注:如果你使用'starter POMs',spring-boot-starter会自动提供SnakeYAML。

加载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.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;
          }
      }
    
在Spring环境中使用YAML暴露属性
  • YamlPropertySourceLoader类能够用于将YAML作为一个PropertySource导出到Spring 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文件。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,924评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,781评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,813评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,264评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,273评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,383评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,800评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,482评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,673评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,497评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,545评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,240评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,802评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,866评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,101评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,673评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,245评论 2 341

推荐阅读更多精彩内容