关于SpringBoot的外部化配置使用记录
声明: 若有任何纰漏、错误请不吝指出!
记录下使用SpringBoot配置时遇到的一些麻烦,虽然这种麻烦是因为知识匮乏导致的。
记录下避免一段时间后自己又给忘记了,以防万一。
如果放到博客里能帮助到遇到同样问题的同志,自是极好!
SpringBoot的外部化配置,主要就是指平时用到的一些配置文件,这些配置由于不是硬编码,放在了配置文件中,所以相对来说是一个外部化的配置Externalized Configuration
SpringBoot官方外部化配置的在线文档
初级用法SpringBoot对配置提供了极大的便利,仅仅需要编写一个Yaml文件或者Properties文件,按照其规定的格式,书写好我们的配置信息,然后编写一个相应的Java类,使用注解@ConfigurationProperties和@Configuration配合使用,或者@Configuration和@Value配合使用,即可将配置的值,映射到我们配置类或者JavaBean中。
有如下Java配置类
@Configuration @ConfigurationProperties(prefix="spring.server") public class AppConfig{ private String name; private String port; public void setName(String name){ this.name = name; } public void setPort(String port){ this.port = port; } }如下配置文件,
Yaml格式配置文件
# application.yml spring: server: name: spring-app port: 9527Properties格式配置文件
# application.properties spring.server.name=spring-app spring.server.port=9237使用@ConfigurationProperties,必须要有Setter方法,绑定时是通过Setter方法绑定的
参见org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor#postProcessBeforeInitialization,这是一个BeanPostProcessor
这样在SpringBoot中,我们就可以将AppConfig这个Bean注入到别的Bean中使用我们的配置了。
以上这些在开发中基本上也就满足需要了,大部分我们的配置都很简单,通常都是数值型的和字符串。
但是,凡事不能绝对。
高级用法以下配置参考这位
Array/List假如有如下需求,应用仅对几个有限的IP开放访问,然后我们想把这几个获得许可的IP地址写在配置文件中。
这个时候如果配置解析仅仅支持字符串和数值型的话,就需要我们自己获取到配置值以后,再去进行一些后续的处理,比如转换成数组或者列表。
好在,优秀的框架,总能满足大部分的需求,SpringBoot是直接配置直接到数组或者列表的映射到
使用方式
Java配置类 @Configuration @ConfigurationProperties(prefix="allows") public class AllowedAccessConfig{ private String[] ipList; // 字段类型可以是 List<String> public void setPort(String[] port){ this.ipList = ipList; } } 配置文件 # application.yml allows: ipList: - 192.168.1.1 - 192.168.1.2 - 192.168.1.3 - 192.168.1.4 # or allows: ipList: 192.168.1.1, 192.168.1.2, 192.168.1.3, 192.168.1.4 # application.properties allows.ipList[0]=192.168.1.1 allows.ipList[1]=192.168.1.2 allows.ipList[2]=192.168.1.3 allows.ipList[3]=192.168.1.4 # or allows.ipList= 192.168.1.1, 192.168.1.2, 192.168.1.3, 192.168.1.4 Map如果数组或者列表不满足需求,需要key-vlaue型的,没问题,SpringBoot也是支持的。
假设一个对接方不同的业务,使用了不同的AES密钥,那么在配置的时候,就要根据业务类型作为key,对应的密钥作为value。
Java配置类 @Configuration @ConfigurationProperties(prefix="aes.keys") public class AesKeyConfig{ private Map<String,String> keys; public void setKeys(Map<String,String> keys){ this.keys = keys; } } 配置文件 # application.yml aes: keys: order: 28jsaS2asf2fSA2 pay: @ra@3safdsR5&sDa # or aes: keys[order]: 28jsaS2asf2fSA2 keys[pay]: @ra@3safdsR5&sDa # application.properties aes.keys.order=28jsaS2asf2fSA2 aes.keys.pay=@ra@3safdsR5&sDa # or aes.keys[order]=28jsaS2asf2fSA2 aes.keys[pay]=@ra@3safdsR5&sDa Enum枚举?那必须支持
不过实际意义不怎么大,如果配置的值要可以转换成枚举值的话,配置的值必须和枚举值的name一致,大小写都不能差,因为SpringBoot实现的配置到枚举的转换,使用的是
/* java.lang.Enum#valueOf */ public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) { // 这里的name就是枚举值的字符表示,一般都是大写的 T result = enumType.enumConstantDirectory().get(name); if (result != null) return result; if (name == null) throw new NullPointerException("Name is null"); throw new IllegalArgumentException( "No enum constant " + enumType.getCanonicalName() + "." + name); }关于这段代码的理解,可以参考另外一片文章深入理解Java枚举
如果枚举还有其他字段的话,就没办法了
JavaBean什么? 还是不能满足?想要直接把配置绑定到一个JavaBean?
干就完事了!
JavaBean @Configuration @ConfigurationProperties(prefix="upload") public class UploadConfig{ private String rootPath; private String fileType; private int fileSize; private boolean rename; // 省略 Setter方法 } 配置文件 # application.yml upload: root-path: /xx/xx/xx file-type: zip fileSize: 1M rename: false # application.properties upload.rootPath=http://www.likecs.com/xx/xx/xx upload.fileType=zip upload.fileSize=1M upload.rename=false以上几种用法,可以组合使用,非常的灵活
不过如果是JavaBean的数组或者List,或者作为Map的value,会发现绑定不上去。
原因在于,绑定默认是基于Setter方法,进行单个字段的绑定,赋值,而这里要的是一个JavaBean,需要创建一个JavaBean对象,再去做属性绑定赋值。
如果按照这两步走,也可以做到成功绑定到一个作为元素的JavaBean对象。