SpringBoot 配置提示功能
目的
配置自动提示的辅助功能可以让配置写起来更快,准确率大大提高。
springboot jar 包含提供所有支持的配置属性细节的元数据文件。文件的目的是为了让 ide 开发者在用户使用
application.properties
或application.yml
文件时提供上下文帮助和代码补全。
大多数元数据文件是在编译时通过处理用@configurationproperties
注释的所有项自动生成的。也可以手动编写部分元数据。
版本
参考 springboot
2.2.0.release
文档
文件
jar包中的 meta-inf/spring-configuration-metadata.json
(自动生成)或 meta-inf/additional-spring-configuration-metadata.json
(手动添加)
实战
<!-- 引入相关依赖 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-configuration-processor</artifactid> <optional>true</optional> </dependency>
@configuration @configurationproperties(prefix = "file.upload") public class fileuploadconfig { /** maximum number of bytes per file */ private string maxsize = "1024m"; /** 不允许的文件后缀 */ private string rejectsuffix; //注意:使用的时候必须要有getter/setter,否则不会自动生成该属性对应的提示 //此处因为篇幅原因省略 getter/setter }
@configuration @configurationproperties("map.test") public class maptestconfig { /** 测试map类型数据的提示 */ private map<string, object> data; //注意:使用的时候必须要有getter/setter,否则不会自动生成该属性对应的提示 //此处因为篇幅原因省略 getter/setter }
中文注释会乱码,以上故意用中文注释的地方,会在下面文件中指定对应的描述,看是否会覆盖。
additional-spring-configuration-metadata.json
{ "properties": [ { "name": "file.upload.reject-suffix", "type": "java.lang.string", "defaultvalue": "exe,jar", "description": "the file suffix is not allowed.", "sourcetype": "com.lw.metadata.config.fileuploadconfig" }, { "name": "map.test.data", "type": "java.util.map", "description": "tips for testing map type data.", "sourcetype": "com.lw.metadata.config.maptestconfig" } ], "hints": [ { "name": "map.test.data.keys", "values": [ { "value": "name", "description": "the name of the person." }, { "value": "sex", "description": "the sex of the person." } ] } ] }
maven compile 之后,生成的 additional-spring-configuration-metadata.json
与源码中的一样,生成的 spring-configuration-metadata.json
如下:
{ "groups": [ { "name": "file.upload", "type": "com.lw.metadata.config.fileuploadconfig", "sourcetype": "com.lw.metadata.config.fileuploadconfig" }, { "name": "map.test", "type": "com.lw.metadata.config.maptestconfig", "sourcetype": "com.lw.metadata.config.maptestconfig" } ], "properties": [ { "name": "file.upload.max-size", "type": "java.lang.string", "description": "maximum number of bytes per file", "sourcetype": "com.lw.metadata.config.fileuploadconfig", "defaultvalue": "1024m" }, { "name": "file.upload.reject-suffix", "type": "java.lang.string", "description": "the file suffix is not allowed.", "sourcetype": "com.lw.metadata.config.fileuploadconfig", "defaultvalue": "exe,jar" }, { "name": "map.test.data", "type": "java.util.map<java.lang.string,java.lang.object>", "description": "tips for testing map type data.", "sourcetype": "com.lw.metadata.config.maptestconfig" } ], "hints": [ { "name": "map.test.data.keys", "values": [ { "value": "name", "description": "the name of the person." }, { "value": "sex", "description": "the sex of the person." } ] } ] }
效果
由此可以看到以下现象:
- 代码中的默认值会自动生成到提示文件中,如:fileuploadconfig#maxsize
- 代码中的注释会自动生成到提示文件中,如:fileuploadconfig#maxsize
- additional-spring-configuration-metadata.json 文件中存在的提示会覆盖自动生成的对应属性,若自动生成的没有此属性则自动增加。
手动写提示文件
示例
{ "groups": [ { "name": "server", "type": "org.springframework.boot.autoconfigure.web.serverproperties", "sourcetype": "org.springframework.boot.autoconfigure.web.serverproperties" }, { "name": "spring.jpa.hibernate", "type": "org.springframework.boot.autoconfigure.orm.jpa.jpaproperties$hibernate", "sourcetype": "org.springframework.boot.autoconfigure.orm.jpa.jpaproperties", "sourcemethod": "gethibernate()" } ], "properties": [ { "name": "server.port", "type": "java.lang.integer", "sourcetype": "org.springframework.boot.autoconfigure.web.serverproperties" }, { "name": "server.address", "type": "java.net.inetaddress", "sourcetype": "org.springframework.boot.autoconfigure.web.serverproperties" }, { "name": "spring.jpa.hibernate.ddl-auto", "type": "java.lang.string", "description": "ddl mode. this is actually a shortcut for the \"hibernate.hbm2ddl.auto\" property.", "sourcetype": "org.springframework.boot.autoconfigure.orm.jpa.jpaproperties$hibernate" } ], "hints": [ { "name": "spring.jpa.hibernate.ddl-auto", "values": [ { "value": "none", "description": "disable ddl handling." }, { "value": "validate", "description": "validate the schema, make no changes to the database." }, { "value": "update", "description": "update the schema if necessary." }, { "value": "create", "description": "create the schema and destroy previous data." }, { "value": "create-drop", "description": "create and then destroy the schema at the end of the session." } ] } ] }
groups
分组,将配置类分组。
可以按照文件来分组,即:将同一个配置文件的所有属性放在同一个组
属性 | 类型 | 是否必须 | 用途 |
---|---|---|---|
name | string | y | 分组的完整名称 |
type | string | n | 分组数据类型的类名(如:使用@configurationproperties注释的完整类名、使用@bean注释的方法返回类型) |
description | string | n | 分组的简短描述。 |
sourcetype | string | n | 提供分组来源的类名。 |
sourcemethod | string | n | 提供分组的方法,包含括号和参数类型。 |
properties
提示主体,必须
属性 | 类型 | 是否必须 | 用途 |
---|---|---|---|
name | string | y | 属性的完整名称。名称采用小写句点分隔格式,如:server.address
|
type | string | n | 属性数据类型的完整签名(如:java.lang.string )或完整的泛型类型(如:java.util.map<java.util.string,acme.myenum> )。此属性提示用户输入值得类型。原生类型在此处使用其包装类型(如:boolean 使用java.lang.boolean )。 |
description | string | n | 分组的简短描述。 |
sourcetype | string | n | 提供分组来源的类名。 |
defaultvalue | object | n | 默认值。当属性为指定时使用。 |
deprecation | deprecation | n | 指定属性是否已弃用。 |
deprecation属性如下:
属性 | 类型 | 是否必须 | 用途 |
---|---|---|---|
level | string | n | 弃用级别,可以是 warning (默认值) 或 error 。warning :属性应该仍然可以使用;error :属性不保证可以使用 |
reason | string | n | 属性弃用的简短原因。 |
replacement | string | n | 替换此弃用属性的新属性全名。可为空 |
注意:spring boot 1.3 版本之前,是使用 boolean 类型的
deprecated
。
以下示例来源于官方文档,展示了如何处理这种场景:
@configurationproperties("app.acme") public class acmeproperties { private string name; public string getname() { ... } public void setname(string name) { ... } @deprecatedconfigurationproperty(replacement = "app.acme.name") @deprecated public string gettarget() { return getname(); } @deprecated public void settarget(string target) { setname(target); } }
一旦
gettarget
和settarget
方法从公共 api 中删除,元数据中的自动弃用提示也会消失。 如果要保留提示,则添加具有error
弃用级别的手动元数据可以确保用户仍然了解该属性。在提供替代品时,这样做特别有用。
hints
辅助提示,非必须
属性 | 类型 | 是否必须 | 用途 |
---|---|---|---|
name | string | y | 提示关联的属性的完整名称。名称是小写句点分隔格式(如:spring.mvc.servlet.path ),如果属性关联map类型(如:system.contexts ),提示可以关联map的键(system.contexts.keys )或者值(system.contexts.values )。 |
values | valuehint[] | n | 有效值集合。(下表详述) |
providers | valueprovider[] | n | 提供者集合。(下表详述) |
values
属性如下:
属性 | 类型 | 是否必须 | 用途 |
---|---|---|---|
value | object | y | 提示引用元素的有效值。如果属性是数组,value和description也可以是数组。 |
description | string | n | value 对应的简短描述 |
### valuehint
对于map类型的支持如下:
@configurationproperties("sample") public class sampleproperties { private map<string,integer> contexts; // getters and setters }
{"hints": [ { "name": "sample.contexts.keys", "values": [ { "value": "sample1" }, { "value": "sample2" } ] } ]}
提示是对map内每一对 key-value 的提示。
.keys
和.values
前缀必须分别关联 map 的 keys 和 values。
providers
属性如下:
属性 | 类型 | 是否必须 | 用途 |
---|---|---|---|
name | string | n | 用于为提示所引用的元素提供其他内容帮助的 provider 的名称。 |
parameters | json object | n | provider 所支持的任何其他参数(有关详细信息,请查看 provider 的文档)。 |
valueprovider
一般用不到,建议跳过
下表总结了支持的 providers 列表:
属性 | 描述 |
---|---|
any | 允许提供任何附加值。 |
class-reference | 自动完成项目中可用的类。通常由目标参数指定的基类约束。 |
handle-as | 处理属性,就像它是由必须的 target 参数定义的类型定义的一样。 |
logger-name | 自动完成有效的记录器名称和记录器组。通常,当前项目中可用的包和类名可以自动完成,也可以定义组。 |
spring-bean-reference | 自动完成当前项目中可用的bean名称。通常由 target 参数指定的基类约束。 |
spring-profile-name | 自动完成项目中可用的 spring 配置文件名称。 |
any
符合属性类型的所有值。
{"hints": [ { "name": "system.state", "values": [ { "value": "on" }, { "value": "off" } ], "providers": [ { "name": "any" } ] } ]}
class-reference
提供以下参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
target | string(class) | 无 | 分配给值的类的全限定类名。通常用于筛选非候选类。 |
concrete | boolean | true | 指定是否仅将具体类视为有效候选。 |
{"hints": [ { "name": "server.servlet.jsp.class-name", "providers": [ { "name": "class-reference", "parameters": { "target": "javax.servlet.http.httpservlet" } } ] } ]}
handle-as
允许您将属性的类型替换为更高级的类型。
这通常在属性具有 java.lang.string
类型时发生,因为您不希望配置类依赖于不在类路径上的类。
参数 | 类型 | 默认值 | 描述 | |
---|---|---|---|---|
target | string(class) | 无 | y | 为属性考虑的类型的完全限定名。 |
可用的值如下:
- 任何
java.lang.enum
: 列出属性的可能值。 -
java.nio.charset.charset
: 支持自动完成字符集/编码值(如utf-8
) -
java.util.locale
:自动完成区域设置(如:en_us
) -
org.springframework.util.mimetype
:支持自动完成 content-type 值(如:text/plain
) -
org.springframework.core.io.resource
: 支持自动完成spring的资源抽象以引用文件系统或类路径上的文件 (如:classpath:/sample.properties
)
注意:如果要提供多个值,用
collection
或 数组类型
{"hints": [ { "name": "spring.liquibase.change-log", "providers": [ { "name": "handle-as", "parameters": { "target": "org.springframework.core.io.resource" } } ] } ]}
logger-name
logger-name
provider 自动完成有效的记录器名称和记录器组。 通常,当前项目中可用的包和类名可以自动完成。 如果组已启用(默认),并且配置中标识了自定义记录器组,则应提供该组的自动完成。
支持以下参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
group | boolean | true | 指定是否应考虑已知组。 |
由于记录器名称可以是任意名称,此 provider 应允许任何值,但可以突出显示项目的类路径中不可用的有效包和类名。
以下是 logging.level
属性。keys 是 logger 名,values 关联标准的 log levels 或 自定义的 level,
{"hints": [ { "name": "logging.level.keys", "values": [ { "value": "root", "description": "root logger used to assign the default logging level." }, { "value": "sql", "description": "sql logging group including hibernate sql logger." }, { "value": "web", "description": "web logging group including codecs." } ], "providers": [ { "name": "logger-name" } ] }, { "name": "logging.level.values", "values": [ { "value": "trace" }, { "value": "debug" }, { "value": "info" }, { "value": "warn" }, { "value": "error" }, { "value": "fatal" }, { "value": "off" } ], "providers": [ { "name": "any" } ] } ]}
spring-bean-reference
此 provider 自动完成在当前项目的配置中定义的bean。 支持以下参数:
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
target | string(class) | 无 | 应该分配给候选对象的bean类的完全限定名。通常用于筛选非候选bean。 |
以下示例表示:spring.jmx.server
属性定义了使用 mbeanserver
{"hints": [ { "name": "spring.jmx.server", "providers": [ { "name": "spring-bean-reference", "parameters": { "target": "javax.management.mbeanserver" } } ] } ]}
spring-profile-name
此 provider 自动完成在当前项目的配置中定义的spring配置文件。
以下示例表示:spring.profiles.active
属性可启用的配置文件名称。
{"hints": [ { "name": "spring.profiles.active", "providers": [ { "name": "spring-profile-name" } ] } ]}
可重复的元数据项
具有相同“property”和“group”名称的对象可以在元数据文件中多次出现。 例如,可以将两个单独的类绑定到同一前缀,每个类都有可能重叠的属性名。 虽然多次出现在元数据中的相同名称不应是常见的,但元数据的使用者应注意确保他们支持该名称。
自动生成提示文件
通过使用
spring-boot-configuration-processor
jar,您可以从用@configurationproperties
注释的类中轻松生成自己的配置元数据文件。 jar包含一个java注释处理器,在编译项目时调用它。 用此处理器,需要引入spring-boot-configuration-processor
依赖。<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-configuration-processor</artifactid> <optional>true</optional> </dependency>
处理器获取用@configurationproperties注释的类和方法。 配置类中字段值的 javadoc 用于填充 description 属性。
注意:仅仅只应将简单文本与@configurationproperties字段javadoc一起使用,因为在将它们添加到json之前不会对它们进行处理。
如果类有一个“至少一个参数”的构造函数,则为每个构造函数参数创建一个属性。 否则,通过标准getter和setter来发现属性,这些getter和setter对集合类型进行了特殊处理(即使只有getter存在,也会检测到)。
注解处理器还支持使用@data、@getter和@setter 的 lombok 注解。
注解处理器无法自动检测
enum
和collections
的默认值。在集合或枚举属性具有非空默认值的情况下,应提供手动元数据。
@configurationproperties(prefix="acme.messaging") public class messagingproperties { private list<string> addresses = new arraylist<>(arrays.aslist("a", "b")) ; private containertype = containertype.simple; // ... getter and setters public enum containertype { simple, direct } }
为了提示上述属性的默认值,应该手动添加如下元数据:
{"properties": [ { "name": "acme.messaging.addresses", "defaultvalue": ["a", "b"] }, { "name": "acme.messaging.container-type", "defaultvalue": "simple" } ]}
注意: 如果在项目中使用 aspectj,则需要确保注解处理器只运行一次。 使用 maven 时, 可以显式地配置
maven-apt-plugin
插件,并仅在那里向注解处理器添加依赖项。 还可以让 aspectj 插件运行于所有的处理且在maven-compiler-plugin
的configuration
中禁用注解处理,如下:<plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <configuration> <proc>none</proc> </configuration> </plugin>
绑定属性
注解处理器自动将内部类视为嵌套属性。
@configurationproperties(prefix="server") public class serverproperties { private string name; private host host; // ... getter and setters public static class host { private string ip; private int port; // ... getter and setters } }
上述示例生成
server.name
、server.host.ip
和server.host.port
属性的元数据信息。 可以在字段上使用@nestedconfigurationproperty 注解来指示应将常规(非内部)类视为嵌套类。
注意: 这对集合和映射没有影响,因为这些类型是自动标识的,并且为每个类型生成一个元数据属性。
添加额外的元数据
spring boot 的配置文件处理非常灵活,通常情况下,可能存在不绑定到
@configurationproperties
bean的属性。 您还可能需要调整现有key的某些属性,为了支持这种情况并让您提供自定义的“提示”,注解处理器会自动将meta-inf/additional-spring-configuration-metadata.json
中的提示项合并到主要元数据文件(spring-configuration-metadata.json)中。如果引用已自动检测到的属性,则将覆盖描述、默认值和弃用信息(如果指定)。 如果当前模块中没有标识手动属性中的声明,则将其作为新属性添加。
additional-spring-configuration-metadata.json
文件的格式与spring-configuration-metadata.json
文件一样。 附加属性文件是可选的。如果没有任何其他属性,就不要添加文件。
参考资料
springboot 配置提示官方文档
公众号:逸飞兮(专注于 java 领域知识的深入学习,从源码到原理,系统有序的学习)