# SpringBoot 配置文件 自定义配置参数

# 简介

SpringBoot 通过对 Spring 的封装, 让你在项目中几乎看不到 .xml 文件, 那我们的配置放在哪儿呢? 放在了 src/main/resources 下的 application.properties 文件中. 除了 .properties 文件, SpringBoot 还支持 .yml 文件, 个人比较推荐使用 .yml 格式的文件. 因为他结构清晰, 不需要重复的写相同的头信息.

# 格式差别

.properties 文件示例:

# 设置端口为 8080
spring.port=8080
# 使用 random 配置文件
spring.profiles.active=random

先不要太在意代码中配置的含义, 只看上面两行配置的结构, 都有 spring 前缀, 但是都要再写一遍

.yml 文件示例:

spring:
	# 设置端口为 8080
	port: 8080
	prifiles:
		# 使用 random 配置文件
		active: random

通过和 .properties 文件的对比, 很容易就发现了两者的不同, .yml 文件的可读性更强一些, 而且不需要重复的写含有相同前缀的头信息.

# HelloWorld @Value

# 创建项目 & 编码

简介好像说的有点多了, 下面我们就来写一个 HelloWorld 实际练一下, 新建一个项目, 不需要引额外的包.

直接上代码

application.yml 文件

# 测试中使用的作者信息
author:
  # 姓名
  name: summer
  # 年龄
  # age: 18
  # 性别
  gender: man

创建实体 AuthorValue.java 代码如下:

/**
 * @author summer
 * @date 2018/4/12 下午3:32
 * 配置文件对应的实体
 */
@Component
public class AuthorValue {
    /**
     * 用户名
     */
    /*
     * 通过 value 注解获取 properties 文件中的内容
     * ${属性的全称}
     */
    @Value("${author.name}")
    private String name;
    /*
     * 若配置文件中没有配置相应的属性, 而在类中又通过 @Value的形式获取, 系统启动时会报错
     * 所以, 我们可以通过设定默认值的形式避免这样的问题
     */
    @Value("${author.age:10}")
    private Integer age;

    // getter and setter
}

创建测试类 AuthorValueTest.java 代码如下:

/**
 * @author summer
 * @date 2018/4/12 下午3:34
 * 通过 value 的方式获取配置文件内容的测试方法
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class AuthorValueTest {

    @Autowired
    private AuthorValue authorValue;

    @Test
    public void getUserMessage(){
        Integer age = 10;
        Assert.assertEquals(authorValue.getName(), "summer");
        Assert.assertEquals(authorValue.getAge(), age);
    }
}

运行测试代码, 发现完美运行.

到此, 我们的 HelloWorld 就开发完成了. What ? 发生了什么? 开发完成了? 其实通过查看代码中的注解, 也能看出相关的逻辑, 接下来我们再做一些补充

# 代码解释

# application.yml

配置文件中我们自己定义了一组属性, 这里的 author, namegender 都是我们自己定义的.

注意: 这里使用的是 yml, 他的语法是用冒号 : 和缩进来确定上下级关系的.

# AuthorValue. java

代码中, 我们通过 @Value("${author.name}") 的方式获取了 application.yml 中的 author.name 的值. 值得注意的是, 我们使用 @Value 的方式获取相应的配置参数时, 如果配置文件中没有设置相应的值, 则会报错. 我们可以通过 @Value(参数名:默认值) 的方式给相应的配置加上默认值. 例如示例中的 age 字段.

# 通过前缀 @ConfigurationProperties 直接封装对象

# 编码

application.yml 文件内容如下

# 测试中使用的作者信息
author:
  # 姓名
  name: summer
  # 年龄
  age: 18
  # 性别
  gender: man

  # Map 的测试数据
  wife[name]: lili
  wife[age]: 19

  # List 的测试数据
  books[0]: spring
  books[1]: java

新建 AuthorObject.java 内容如下

/**
 * @author summer
 * @date 2018/4/12 下午3:32
 * 配置文件对应的实体
 */
@Component
@ConfigurationProperties(prefix = "author")
public class AuthorObject {
    /**
     * 用户名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 妻子信息, 主要用来演示 map
     */
    private Map<String, Object> wife;
    /**
     * 出品的书籍 用于演示 list
     */
    private List<String> books;

    /**
     * 简介信息, 用于测试配置文件间的参数调用
     */
    private String introduce;
    
    // getter and setter
}

新建测试类 AuthorObjectTest.java 内容如下

/**
 * @author summer
 * @date 2018/4/12 下午3:34
 * 通过 value 的方式获取配置文件内容的测试方法
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class AuthorObjectTest {

    @Autowired
    private AuthorObject authorObject;

    @Test
    public void getUserMessage(){
        Integer age = 18;
        Assert.assertEquals(authorObject.getName(), "summer");
        Assert.assertEquals(authorObject.getAge(), age);
        Assert.assertFalse(authorObject.getWife().isEmpty());
        Assert.assertFalse(authorObject.getBooks().isEmpty());
        Assert.assertNotNull(authorObject.getIntroduce());

        System.out.println("user wife name: " + authorObject.getWife().get("name"));
        System.out.println("user wife name: " + authorObject.getWife().get("age"));

        System.out.println("first boot: " + authorObject.getBooks().get(0));

        System.out.println(authorObject.getIntroduce());
    }
}

# 代码解释

可能大家已经注意到了, 在 AuthorObject.java 上有个注解 @ConfigurationProperties(prefix = "author") , 这是什么意思呢? 意思就是从 application.yml 文件中查找以 author 开头的自定义配置. 然后封装成对象, 类中的属性名, 需要和配置文件的自定义配置的名称(author下)一致.

除了基础数据类型以外, 我们也可以封装 MapList

封装 Map 的语法: 对应的属性名[Map的Key]:Value

封装 List 的语法: 对应的属性名称[Index]:Value

# 小结

通过上面两个例子, 我们分别用 @Value@ConfigurationProperties(prefix = "prefix") 的方式获取配置文件中的参数, 在开发过程中大家也应该可以明显的感觉到 @ConfigurationProperties 的便捷. 值得一提的是, 使用后一种方式封装参数时, 即便是配置文件中没有定义相应的属性, 在加载时也不会报错.

# 多环境配置

在开发过程中, 开发者之间, 为了适应本地环境, 经常要修改配置. 从开发发布到生产服务器的时候, 很多时候也要修改配置, 你也改, 我也改. 不出问题就见鬼了.

SpringBoot 提供了怎样的解决方案呢? 没错, 多环境配置, 每人一个配置文件, 生产服务有自己专门的配置, 这样开发的时候互相之间就不会有影响了. 是不是很爽? 接下来, 我们就看一下多环境是如何实现的.

# 编码

resources 下新建文件 application-random.yml 内容如下:

author:
  property:
    # 随机字符串
    value: ${random.value}
    # 随机 int
    number: ${random.int}
    # 随机 long
    bignumber: ${random.long}
    # 10 以内的随机数
    number1: ${random.int(10)}
    # 10-20的随机数
    number2: ${random.int[10,20]}

application.yml 中添加配置如下

spring:
  profiles:
    # 设置使用的配置文件为 random 后缀的
    active: random

新建 JavaRandomValue.java 内容如下:

/**
 * @author summer
 * @date 2018/4/12 下午5:28
 */
@Component
public class RandomValue {
    @Value("${author.property.value}")
    private String value;
    @Value("${author.property.number}")
    private Integer number;
    @Value("${author.property.bignumber}")
    private Long bignumber;
    @Value("${author.property.number1}")
    private Integer number1;
    @Value("${author.property.number2}")
    private Integer number2;
    
    // getter and setter 
}

新建测试类 RandomValueTest.java 内容如下

/**
 * @author summer
 * @date 2018/4/12 下午3:34
 * 通过 value 的方式获取配置文件内容的测试方法
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class RandomValueTest {

    @Autowired
    private RandomValue randomValue;

    @Test
    public void getUserMessage(){
        Assert.assertNotNull(randomValue.getValue());
        Assert.assertNotNull(randomValue.getNumber());
        Assert.assertNotNull(randomValue.getBignumber());
        Assert.assertNotNull(randomValue.getNumber1());
        Assert.assertNotNull(randomValue.getNumber2());

        System.out.println(randomValue.getValue());
    }
}

右击运行测试类, 完美运行

# 代码解释

多环境配置时, 我们首先建了一个 application-random.yml 命名规则是 application(默认)-环境名(可自定义).yml

然后在 application.yml 中设置激活的环境为 random . 值得注意的是在指定环境后, 主配置文件 application.yml 中的属性也依旧会有效, 如果出现了重复配置, 主配置文件中的内容会被覆盖.

# 随机数 random

上一小节"多环境配置"中,我们的 application-random.yml 文件里使用了 ${random.value} 用以获取随机数. random 我们都用过. 但是这里是设么意思呢, 这是一种参数间引用. 例如:

# 测试中使用的作者信息
author:
  # 姓名
  name: summer
  # 年龄
  age: 18
  # 性别
  gender: man

  # 参数间的引用
  introduce: Name:${author.name},Age:${author.gender}

我们自己定义了 author namegender 下面 introduce 参数的值, 通过 ${参数名} 的方式引用了上面提到的值. 同理 ${random.value} 也是同样的道理, 不同的是后者引用的不是一个固定的参数, 而是生成一个随机字符串的方法. 除了 random 之外, SpringBoot 还提供了其他的很多常用参数, 例如: os (用于获取系统信息), idea (用于获取开发工具信息), pom (用于获取 maven 配置信息), file 文件的相关处理等等.

# 项目源码

SpringBoot 教程: https://github.com/lixian13149999/spring-boot-learn

对应示例项目: properties

# 总结

使用 application.yml 文件可以很容易实现自定义参数配置, 在获取的时候也是相当的简便. 另外, 其提供的多环境配置也是团队开发者的福音, 不用再为 谁改了我的配置! 而苦恼!

有问题可以在留言区留言, 转发请注明出处, 谢谢

上次更新时间: 2020/6/17 下午5:44:30