深入理解 spring boot 自定义属性

application.properties 这个文件在 spring boot 开发中最常见,本文围绕它展开,包括 自定义属性,以及 动态属性,环境切换。通过本文,你一定能够更好的开发 spring boot 应用,这里所谓的更好的,主要是指 环境切换、自定义属性及其高级用法。

spring boot 开发、正式 环境切换

这个话题我相信一定是很多人遇到的,我就从这里开始说起,默认情况下 application.properties 是空白的,spring boot 很多配置都是默认的,且默认配置并不差,所以才如此。比如你如果想要换个端口,你得 在 application.properties 里新增一行:server.port=8282 ,这样子将监听在 8282 端口而非 8080 端口,但是,如果你将很多配置都丢在这个文件里,那坏处也是很明显的,第一,很乱,第二,不适合复用,试想下,假设你有多个项目,那么你的配置文件如何共享,假设你用了 druid 然后配置有点问题,你可能在一个项目里改了,另一个项目里忘了等等,假设你的 druid 配置文件统一写在 application-druid.properties 里,那么最差的情况是都复制一遍,而如果所有的配置都丢在 application.properties 里,那么要找到某个配置并不容易哈。

spring.profiles.active 与 spring.profiles.include 登场

你可以在 application.properties 里只写两行,即:

spring.profiles.active=test
spring.profiles.include=default,druid

此时,等于你同时配置了 application-test.properties、application-default.properties、application-druid.properties 三个文件,即除了 application.properties 你应该额外再创建刚才提到的这三个文件,将 druid 的配置写到 application-druid.properties 里,将测试环境的配置写到 application-test.properties 将 其他配置写到 application-default.properties 当然,你可以再细分,但是 active 最后会覆盖 include,即你在 上面的 application-test.properties 里的配置如果和另外两个配置里的某项冲突,将采用 test 里的配置。

另外,你也可以在命令行传参,比如:

java -Xms1024m -Xmx3096m -jar ./xxx.jar --server.port=8182

或者

java -Xms1024m -Xmx3096m -jar ./xxx.jar --spring.profiles.active=product

现在,我想你已经知道该怎么做了,即,用多个配置文件,另外,将因为环境不一样而导致的配置不同的项写到类似 application-test.properties、application-product.properties 然后通过修改 application.properties 里的 spring.profiles.active 或者 启动的时候 --spring.profiles.active 来切换。

cannot resolve configuration property xxxx

如果你试图在 application.properties 里写入一个不存在的配置项,idea 会报上面的警告,同时文件里也显示警告,要解决它,你首先得添加依赖,即在 pom.xml 里新增:

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

然后有两个解决方案,第一个是在 resources 目录下新建一个文件夹:META-INF,然后在 META-INF 下面新建一个文件:additional-spring-configuration-metadata.json ,然后光标移到黄色警告上,按下 alt + enter 选择第一项,create configuration key xxx 即可,也可以自己写入,比如我在 application-test.properties 里新增了一行:dynamic.datasource.name=test,然后在 additional-spring-configuration-metadata.json 里写入了如下内容:

{
  "properties": [
    {
      "name": "dynamic.datasource.name",
      "type": "java.lang.String",
      "description": "Description for dynamic.datasource.name."
    }
  ]
}

然后删除 target 目录,最后重新运行项目,警告就没了,你可能也会遇到

re-run spring boot configuration annotation processor to update generated metadata

解决之道已经说了,删除 target 目录,然后重新运行即可。当然,这种办法是最笨的,你也可以采用下面的第二种办法,使用 @ConfigurationProperties 注解,比如:

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@ConfigurationProperties(prefix = "dynamic.datasource")
@Setter
@Getter
public class DbNameConfig {

    private List<String> name;
}

这里,lombok 是第三方包,同时需要安装 idea 插件 lombok 依赖你可以在 pom 里新增:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

至于插件,自行安装吧,如果下载慢,那你就忍着吧,也可以删除 @Getter 和 @Setter 以及 import lombok 语句,然后手动写 getter 和 setter 方法,当然 idea 也能给你自动生成。如果这里你删除了 @Component 注解,你会遇到 :

not registered via @enableconfigurationproperties or marked as spring component

解决办法就是 添加 @Component 注解,这也是我推荐的做法,或者 在 xxxApplication.java 上添加 @EnableConfigurationProperties 注解,比如:

@EnableConfigurationProperties({DbConfig.class, DbNameConfig.class})

无论是新建 additional-spring-configuration-metadata.json 还是 新建类并 添加 @ConfigurationProperties 注解,spring-boot-configuration-processor 这个依赖你得添加,同时 target 目录得删除,然后重新运行。

spring boot 自定义 动态属性 - spring boot configure dynamic properties

无论是上面说的第一种还是第二种办法,目前都不能动态的添加属性不是吗,你都得提前定义好。其实,你完全可以通过 map 做到自定义动态属性,比如:

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "dynamic", ignoreInvalidFields = true)
@Setter
@Getter
public class DbConfig {

    private final Map<String, DbInfo> datasource = new HashMap<>();
}

然后,你就可以在 application.properties 文件里添加如下的配置了:

dynamic.datasource.test.password=123456
dynamic.datasource.chun.user=123456
dynamic.datasource.kpromise.password=123456

这里,当你输入 dynamic.datasource 时,idea 不会提示可选的项,即不会自动完成,因为这里的 datasource 其实指上面 java 文件里的 map,它的 key 自然是没法预测的,也就没法自动完成了,但是当你输入 dynamic.datasource.kpromise 时,如果你按下英文的点(即 .),又会自动提示了,这里,test、chun、kpromise 则是动态的内容了,你没有新建这些类的,不是吗?或许你会问这有啥用?其实用处大了去了,可以实现 动态数据库,或者说 spring boot 使用 动态数据库 技术时,这个动态的自定义属性将非常有用。如果你以为万事大吉了,那就错了,此时,你没法通过 @Value 去读取这里的 dynamic.datasource,想要解决它,你只能通过 读取环境变量了。具体请看之后的博文吧。

本博客若无特殊说明则由 full-stack-trip 原创发布
转载请点名出处:编程生涯 > 深入理解 spring boot 自定义属性
本文地址:https://www.kpromise.top/deep-into-spring-boot-custom-properties/

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注