(2) spring-boot配置详解

Spring Boot简化了基于Spring的应用开发,其为spring及第三方平台提供开箱即用的设置,多数Spring Boot应用只需要很少的Spring配置。

spring特性:

  • 为所有Spring开发提供一个从根本上更快,且随处可得的入门体验。
  • 开箱即用,但通过不采用默认设置可以快速摆脱这种方式。
  • 提供一系列大型项目常用的非功能性特征,比如:内嵌服务器,安全,指标,健康检测,外部化配置。
  • 绝对没有代码生成,也不需要XML配置。

1、Spring-Boot核心配置文件

SpringBoot配置文件可以使用yml格式和properties格式,分别的默认命名为:application.yml、application.properties

配置.png

1.1、存放目录

  • 项目根目录下
  • 项目根目录中config目录下
  • 项目的resources目录下
  • 项目resources目录中config目录下
项目.png

1.2、读取顺序

如果在不同的目录中存在多个配置文件,它的读取顺序是:

  1. config/application.properties(项目根目录中config目录下)
  2. config/application.yml
  3. application.properties(项目根目录下)
  4. application.yml
  5. resources/config/application.properties(项目resources目录中config目录下)
  6. resources/config/application.yml
  7. resources/application.properties(项目的resources目录下)
  8. resources/application.yml

注:

1、如果同一个目录下,有application.yml也有application.properties,默认先读取application.properties。
2、如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取到的。
3、创建SpringBoot项目时,一般的配置文件放置在“项目的resources目录下”

1.3、更改默认配置文件位置

如果不喜欢将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

注意:

(1)、在初期需要根据spring.config.name和spring.config.location决定加载哪个文件,所以它们必须定义为environment属性(通常为OS env,系统属性或命令行参数)。
(2)、如果spring.config.location包含目录(相对于文件),那它们应该以/结尾(在被加载前,spring.config.name关联的名称将被追加到后面,包括profile-specific的文件名)。spring.config.location下定义的文件使用方法跟往常一样,没有profile-specific变量支持的属性,将被profile-specific的属性覆盖。
(3)、不管spring.config.location配置什么值,默认总会按照classpath:,classpath:/config,file:,file:config/的顺序进行搜索,优先级由低到高,也就是file:config/获胜。如果你指定自己的位置,它们会优先于所有的默认位置(locations),并使用相同的由低到高的优先级顺序。那样,你就可以在application.properties为应用设置默认值,然后在运行的时候使用不同的文件覆盖它,同时保留默认配置。

2、spring-boot读取配置

spring-boot的核心配置文件为application.properties,同时也可通过注解自定义配置文件。

2.1、使用@Value方式读取核心配置

使用方法:

@Value("${xxx}")

使用示例:

package Solin.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class WebController {
  @Value("${test.msg}")
  private String msg;

  @RequestMapping("/index1")
  public String index1(){
    return "方式一:"+msg;
  }
}

注意事项:

在@Value的${}中包含的是核心配置文件application.properties中的键名。

2.1、使用Environment方式

使用方法:
用注入Environment实例,通过Environment.getProperty("xxx")获取配置信息;

使用示例:

package Solin.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class WebController {
  @Autowired
  private Environment env;

  @RequestMapping("/index2")
  public String index2(){
    return "方式二:"+env.getProperty("test.msg");
  }
}

注意事项:

(1)、这种方式是依赖注入Evnironment来完成,在创建的成员变量private Environment env上加上@Autowired注解即可完成依赖注入,然后使用env.getProperty("键名")即可读取出对应的值。
(2)、Evnironment不仅能获取核心配置application.properties的参数,还能获取应用运行的一些环境参数,例如:env.getProperty("JAVA_HOME"),env.getProperty("CLASSPATH")等;

2.3、使用@ConfigurationProperties读取

@ConfigurationProperties可以读取核心配置application.properties中的配置,也可读取自定义的配置;

使用方法:

使用@Component及@ConfigurationProperties一起生成配置bean;若要读取自定义配置,则还需@PropertySource配合使用;

使用示例:

代码:

@Component
@ConfigurationProperties(value = "my")
@PropertySource("classpath:config/myconfig.properties")

public class TestConfigurationProperties {
private String name;
private int age;
private String sex;

//getter、setter方法
}

myconfig.properties配置:

my.name = zhaozhou
my.age = 20
my.sex = man

说明:

  • 示例中@ConfigurationProperties(value = "my"),设置属性组前缀,与@ConfigurationProperties(prefix= "my")等同;
  • @PropertySource(value="classpath:config/myconfig.properties")加载指定的属性文件,value设置自定义配置文件的位置,此配置可以放在此位置,也可放在其他位置;

3、外化配置

3.1、配置随机值

在注入随机值(比如,密钥或测试用例)时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是最大值(不包含在内)。

3.2、访问命令行属性

默认情况下,SpringApplication会将所有命令行配置参数(以'--'开头,比如--server.port=9000)转化成一个property,并将其添加到Spring Environment中。正如以上章节提过的,命令行属性总是优先于其他属性源。如果不想将命令行属性添加到Environment,你可以使用SpringApplication.setAddCommandLineProperties(false)来禁用它们。

3.3、Profile-specific属性

除了application.properties文件,profile-specific属性也能通过命名惯例application-{profile}.properties定义。Environment(Spring的环境抽象接口)有个默认profiles集合(默认情况为[default]),在没有设置激活的profiles时会被使用(例如,如果没有明确指定激活的profiles,application-default.properties中的属性会被加载)。Profile-specific属性加载路径和标准的application.properties相同,并且profile-specific文件总是会覆盖non-specific文件,不管profile-specific文件是否被打包到jar中。如果定义多个profiles,最后一个将获胜。例如,spring.profiles.active定义的profiles被添加到通过SpringApplicationAPI定义的profiles后面,因此优先级更高。

注意:如果你已经在spring.config.location下定义所有文件(非目录),那些profile-specific的文件将不被考虑。如果想使用profile-specific属性,那就在spring.config.location下使用目录。

3.4、属性占位符

当使用application.properties定义的属性时,Spring会先通过已经存在的Environment查找该属性,所以你可以引用事先定义的值(比如,系统属性):

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

4、类型安全的配置属性

4.1、第三方配置

@ConfigurationProperties不仅可以注解在类上,也可以注解在public @Bean方法上,当你需要为不受控的第三方组件绑定属性时,该方法将非常有用。为了从Environment属性中配置一个bean,你需要使用@ConfigurationProperties注解该bean:

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

所有以foo为前缀的属性定义都会被映射到FooComponent上。

4.2、Relaxed绑定

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

例如,给定以下@ConfigurationProperties类:

@ConfigurationProperties(prefix="person") 
public class OwnerProperties { 
  private String firstName; 
  public String getFirstName() { 
    return this.firstName; 
  } 
  public void setFirstName(String firstName) { 
    this.firstName = firstName; 
  } 
}

下面的属性名都能使用:

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

4.3、属性转换

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

注意:由于该bean在应用程序生命周期的早期就需要使用,所以确保限制你的ConversionService使用的依赖。通常,在创建时期任何你需要的依赖可能都没完全初始化。

4.4、@ConfigurationProperties校验

Spring Boot将尝试校验外部配置,默认使用JSR-303(如果在classpath路径中),你只需要将JSR-303 javax.validation约束注解添加到@ConfigurationProperties类上:

@ConfigurationProperties(prefix="connection") 
public class ConnectionProperties { 
  @NotNull 
  private InetAddress remoteAddress; 

  // ... getters and setters 
}

为了校验内嵌属性的值,你需要使用@Valid注解关联的字段以触发它的校验,例如:

@ConfigurationProperties(prefix="connection") 
public class ConnectionProperties { 
  @NotNull 
  @Valid 
  private RemoteAddress remoteAddress; 
  
  // ... getters and setters 
  public static class RemoteAddress { 
    @NotEmpty 
    public String hostname; 
    // ... getters and setters 
  } 
}

你也可以通过创建一个叫做configurationPropertiesValidator的bean来添加自定义的Spring Validator。@Bean方法需要声明为static,因为配置属性校验器在应用程序生命周期中创建的比较早,将@Bean方法声明为static允许该bean在创建时不需要实例化@Configuration类,从而避免了早期实例化(early instantiation)的所有问题。

4.5、@ConfigurationProperties与@Value对比

@Value是Spring容器的一个核心特性,它没有提供跟type-safe Configuration Properties相同的特性。下面的表格总结了@ConfigurationProperties和@Value支持的特性:

特性 @ConfigurationProperties @Value
Relaxed绑定 Yes No
Meta-data支持 Yes No
SpEL表达式 No Yes

如果你为自己的组件定义了一系列的配置keys,我们建议你将它们以@ConfigurationProperties注解的POJO进行分组。由于@Value不支持relaxed绑定,所以如果你使用环境变量提供属性值的话,它就不是很好的选择。最后,尽管@Value可以写SpEL表达式,但这些表达式不会处理来自Application属性文件的属性。

5、profiles配置

Spring Profiles提供了一种隔离应用程序配置的方式,并让这些配置只在特定的环境下生效。任何@Component或@Configuration都能注解@Profile,从而限制加载它的时机:

@Configuration @Profile("production") 
public class ProductionConfiguration { 
  // ... 
}

以正常的Spring方式,你可以使用spring.profiles.active的Environment属性来指定哪个配置生效。你可以使用通常的任何方式来指定该属性,例如,可以将它包含到application.properties中:

spring.profiles.active=dev,hsqldb

或使用命令行开关:

--spring.profiles.active=dev,hsqldb

5.1、添加激活的配置(profiles)

spring.profiles.active属性和其他属性一样都遵循相同的排列规则,优先级最高的PropertySource获胜,也就是说,你可以在application.properties中指定生效的配置,然后使用命令行开关替换它们。有时,将profile-specific的属性添加到激活的配置中而不是直接替换它们是有好处的。spring.profiles.include属性可以用来无条件的添加激活的配置,而SpringApplication的入口点也提供了一个用于设置其他配置的Java API,通过它设置的active配置优先级高于spring.profiles.active,具体参考setAdditionalProfiles()方法。

例如,当一个应用使用下面的属性,并用--spring.profiles.active=prod开关运行,那proddb和prodmqprofiles也会激活:

--- my.property: fromyamlfile 
--- spring.profiles: prod spring.profiles.include: proddb,prodmq

5.2、以编程方式设置profiles

在应用运行前,你可以通过调用SpringApplication.setAdditionalProfiles(…)方法,以编程的方式设置激活的配置,也可以使用Spring的ConfigurableEnvironment接口激活配置(profiles)。

5.3、Profile-specific配置文件

Profile-specific的配置,不管是application.properties(或application.yml),还是通过@ConfigurationProperties引用的文件都是被当作文件来加载的。

6、@import注解与@ImportResource注解

  • @Import注解就是之前xml配置中的import标签,可以用于依赖第三方包中bean的配置和加载
  • @ImportResource是引入spring配置文件.xml

6.1、@import

import注解主要用在基于java代码显式创建bean的过程中,用于将多个分散的java config配置类融合成一个更大的config类;

代码示例:

package com.yiibai.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({ CustomerConfig.class, SchedulerConfig.class })
public class AppConfig {
}

6.2、@ImportResource

用于导入自定义的xml配置,相当于:

<import resource="applicationContext-democonfig2.xml" />

代码示例:

@Configuration
@ImportResource("classpath:applicationContext-democonfig2.xml")
public class StoreConfig {

  @Value("${url}")
  private String url;

  @Value("${username}")
  private String username;

  @Value("${password}")
  private String password;

  @Bean
  public MyDriverManager myDriverManager() {
    return new MyDriverManager(url, username, password);
  }
}

XML代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">

<context:property-placeholder location="classpath:config4.properties" />
<context:component-scan base-package="com.dxz.imports4"></context:component-scan>
</beans>

<context:property-placeholder location="classpath:config4.properties" />用于指导资源文件位置。

7、Java配置类

Spring Boot提倡基于Java的配置。尽管你可以使用XML源调用SpringApplication.run(),不过还是建议你使用@Configuration类作为主要配置源。通常定义了main方法的类也是使用@Configuration注解的一个很好的替补。

7.1、导入其他配置类

你不需要将所有的@Configuration放进一个单独的类,@Import注解可以用来导入其他配置类。另外,你也可以使用@ComponentScan注解自动收集所有Spring组件,包括@Configuration类。

7.2、导入XML配置

如果必须使用XML配置,建议你仍旧从一个@Configuration类开始,然后使用@ImportResource注解加载XML配置文件。

8、快速查阅

相关阅读:
spring-boot基础环境搭建 【https://www.jianshu.com/p/ee36bb9faa10
spring-boot+druid+mybatis环境搭建【https://www.jianshu.com/p/e6c9e9945e45
spring-boot+logback+log4j2+MDC【https://www.jianshu.com/p/51da61a425ba

参考博客:
https://blog.csdn.net/qq_32786873/article/details/52840745
https://www.jianshu.com/p/60b34464ca58
https://www.cnblogs.com/duanxz/p/3787757.html

参考书籍:
《Spring Boot参考指南》 (https://qbgbook.gitbooks.io/spring-boot-reference-guide-zh/content/III.%20Using%20Spring%20Boot/15.2.%20Importing%20XML%20configuration.html

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

推荐阅读更多精彩内容