SpringBoot 干货教程 | 第四章:SpringBoot 配置详解

原创 springboot

基于 SpringBoot 的约定优于配置的原则,在多数情况下,启动一个应用时,基本上无需做太多的配置,应用就能正常启动。

但在大部分开发环境下,添加额外配置是无所避免的,比如自定义应用端口号、mq 的服务地址、缓存服务的服务地址、数据库的配置等,都或多或少的需要一些外部的配置项。

配置文件简述

SpringBoot 默认的全局配置文件名为 application.properties 或者 application.yml (Spring 官方推荐使用的格式是 .yml 格式,目前官网都是实例都是使用 yml 格式进行配置讲解的),应用启动时会自动加载此文件,无需手动引入。

但是在 Initializr 或者 IDEA 生成工程的时候都是生成了 application.properties 配置文件,可能还是考虑到大多数人的使用习惯。其实都是一样的东西,没什么好纠结的,喜欢用哪一种配置文件就选择哪一种。

配置文件编码

由于 SpringBoot 在读取 properties 文件时,使用的是 PropertiesPropertySourceLoader 类进行读取,默认读取的编码是 ISO8859-1,故在默认的配置文件中使用中文时,会出现乱码,此时可以将中文转成 Unicode 编码或者使用 yml 配置格式(yml 默认支持 utf-8)。

或者可以将作为配置写入到一个自定义配置文件,利用 @PropertySource 注解的 encoding 属性指定编码,假如你的配置文件编码为 GBK

@SpringBootApplication
@PropertySource(value={ "classpath:blog.properties" }, encoding="GBK")
public class SpringbootConfigApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SpringbootConfigApplication.class, args);
    }
}

如果必须使用 properties 文件,我们的教程就是这样使用的。在 IDEA 中,选择菜单 File->Settings->Editor->File encodings,在 Properties Files (*.properties) 配置中,在 Default encoding for properties files 后面选择 UTF-8,勾选 Transparent native-to-ascii conversion。如下图所示:

注意,如果你已经写好了配置文件,并且包含中文,那么在上述配置前先复制一份配置内容,在配置好后重新粘贴进来,因为在上述配置后中文转换编码会变成乱码。

自定义属性值配置

application.properties 配置文件支持自定义属性的支持,比如:

blog.address=https://www.daimafans.com
blog.author=谦谦君子
blog.desc=代码饭 www.daimafans.com 全面、专业的源代码分享网站,编程技术分享网站

然后可通过 Spring @value 注解 @Value("${blog.author}") 的形式获取属性值。

@RestController
public class ConfigController {
    @Value("${blog.address}")
    String address;

    @Value("${blog.author}")
    String author;

    @Value("${blog.desc}")
    String desc;

    @RequestMapping("/")
    public String blog()
    {
        return address + "<br>" + author + "<br>" + desc;
    }
}

现在启动项目,访问 http://127.0.0.1:8080/

工程中自定义属性时,特别是一些公共包,建议在 /src/main/resources/META-INF 下创建 spring-configuration-metadata.json 属性元文件。

这样在 IDEA 中使用时,输入的时候会进行联想提示,包括属性名和属性说明,这样也方便调用者询问属性名和属性含义。

需要注意的是,想要顺利的使用这个特性,需要加入 spring-boot-configuration-processor 依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

有关 configuration metadata 的介绍可以回顾教程 SpringBoot 干货教程 | 第一章:教程目录大纲和前戏 小节 “starter 与 metadata”,更详细的内容可以参阅官方文档 Appendix B. Configuration Metadata

属性引用

在配置文件中,一个属性的值可以引用另外一个属性的值,例如:

blog.address=https://www.daimafans.com
blog.author=谦谦君子
blog.desc=代码饭 www.daimafans.com 全面、专业的源代码分享网站,编程技术分享网站
blog.info=${blog.address}<br>${blog.author}<br>${blog.desc}

修改 ConfigController 类为:

@RestController
public class ConfigController
{
    @Value("${blog.address}")
    String address;

    @Value("${blog.author}")
    String author;

    @Value("${blog.desc}")
    String desc;

    @Value("${blog.info}")
    String info;

    @RequestMapping("/")
    public String blog()
    {
        // return address + "<br>" + author + "<br>" + desc;
        return info;
    }
}

重启工程,再次访问 http://127.0.0.1:8080/,和我们上面得到的结果一样!

随机数

SpringBoot 的属性配置文件中可以通过 ${random} 来产生 intlongstring 等值,来支持属性的随机值。

# 随机字符串
.random.value=${random.value}
# 随机 int
.random.number=${random.int}
# 随机 long
.random.bignumber=${random.long}
# 10 以内的随机数
.random.test1=${random.int(10)}
# 1-20 的随机数
.random.test2=${random.int[1,20]}

我们在 ConfigController 新增 random 方法:

@RestController
public class ConfigController
{
    @Value("${.random.test2}")
    int test2;

    @RequestMapping(value = "random", method = RequestMethod.GET)
    public String random()
    {
        return String.valueOf(test2);
    }
}

重启工程,现在访问 http://127.0.0.1:8080/random,得到一个随机数,在 1 到 20 之间,需要注意,这个配置文件中的随机数实在工程启动的时候生成的,之后不会再变化,除非重新启动工程。

不知道你有没有这个疑问,上面的随机数配置属性的键名是以 . 开头的,这是为什么呢?如果不添加的话会是什么样子的呢?

其实没什么特别的玄妙之处,就是我们不小心用到了不该用的配置名称,具体可以查看 org.springframework.boot.env.RandomValuePropertySource 源码:

public class RandomValuePropertySource extends PropertySource<Random> {
    public static final String RANDOM_PROPERTY_SOURCE_NAME = "random";
    private static final String PREFIX = "random.";
    // 省略其它
}

我们使用的键名前缀和 RandomValuePropertySource 环境变量名称前缀重复了,所以我们在使用 @value 标签取值的时候,取回来的是一个 32 位的 uuid。我们把随机数配置部分的键名前缀修改为其它字符串,比如 rnd

# 随机字符串
rnd.value=${random.value}
# 随机 int
rnd.number=${random.int}
# 随机 long
rnd.bignumber=${random.long}
# 10 以内的随机数
rnd.test1=${random.int(10)}
# 1-20 的随机数
rnd.test2=${random.int[1,20]}

自定义配置文件

在多数情况下,配置信息基本上都是放入 application.properties 文件中。

但在一些场景下,比如某个配置项比较多时,为了分开存放,也可自定义配置文件,如 blog.properties

由于自定义的文件,系统不会自动加载,这个时候就需要手动引入了。

利用 @PropertySource 注解可以引入单个或多个配置文件,在查分为多个配置文件的时候,需要引入多个配置文件,可使用 @PropertySources 设置配置文件数组,引入多个文件。

@SpringBootApplication
@PropertySource(value="classpath:blog.properties", encoding="utf-8")
public class SpringbootConfigApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SpringbootConfigApplication.class, args);
    }
}

可以看到,我们把 @PropertySource 注解作用在 SpringBoot 启动入口类上,指定的配置文件为 blog.properties,在当前工程的 classes 下加载,文件的编码为 utf-8。正如上面所说的配置文件编码问题,一般正常情况下新建的 properties 文件的编码都是操作系统本地编码,我们的中文电脑都是 gbk,如果你不想或不便在 IDEA 中设置编码转换,可以在这里指定文件编码格式。

如果有多个配置文件,可以使用数组的方式引入文件。

@SpringBootApplication
@PropertySource(value={ "classpath:blog.properties", "classpath:redis.properties" }, encoding="utf-8")
public class SpringbootConfigApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SpringbootConfigApplication.class, args);
    }
}

配置绑定对象

虽然使用 @Value() 方式能方便的引入自定义的属性值,但在多某个配置项属于某一配置集合时,希望对应到一个实体配置类中,SpringBoot 对这种场景也提供了支持。利用 @ConfigurationProperties 属性,即可完成 properties 配置的映射:

config.number=1
config.name=谦谦君子
config.hobby[0]=编程
config.hobby[1]=小姐姐

实体类:

@Component
@ConfigurationProperties(prefix="config")
// @EnableConfigurationProperties(value= {Config.class})
public class Config {
    private String number;
    private String name;
    private List<String> hobby;
    // 省略 setter/getter
}

这里可直接加入 @Component 注解使 Config 在启动时被自动扫描到,或者使用 @EnableConfigurationProperties 注解注册此实体 bean。

其次,在引入 @ConfigurationProperties 时,如果你前面没有加,这里 IDE 会再次提示你引入 spring-boot-configuration-processor 依赖,前面提到,在自定义属性时,创建 spring-configuration-metadata.json 可进行属性提示,而此依赖功能类似,会编译时自动生成 spring-configuration-metadata.json 文件,此文件主要给 IDE 用于提示使用。添加后在配置文件点击属性时,会自动跳转到对应绑定的实体类中。

我们这里增加一个 /config 请求:

@RestController
public class ConfigController
{
    @Autowired
    Config config;

    @GetMapping(value = "config")
    public Config config()
    {
        return config;
    }
}

重启工程,访问 http://127.0.0.1:8080/config


本文收录在 SpringBoot 干货系列教程:SpringBoot 干货教程 | 第一章:教程目录大纲和前戏

教程代码下载:https://github.com/liuqianfei/springboot-course-code

如果觉得这对你有用,请随意赞赏,给与作者支持
评论 0
最新评论