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,想要解决它,你只能通过 读取环境变量了。具体请看之后的博文吧。