Spring Boot jar包含元数据文件,这些文件提供了所有受支持的配置属性的详细信息。这些文件旨在让IDE开发人员在用户使用application.propertiesapplication.yml文件时提供上下文帮助和“代码完成” 。
通过处理带有注释的所有项目,大多数元数据文件会在编译时自动生成@ConfigurationProperties。但是,可以针对极端情况或更高级的用例手动编写部分元数据

1.元数据格式

配置元数据文件位于的jar中META-INF/spring-configuration-metadata.json。他们使用JSON格式,将项目归类为“组”或“属性”,并将其他值提示归类为“提示”,如以下示例所示:

  1. {"groups": [
  2. {
  3. "name": "server",
  4. "type": "org.springframework.boot.autoconfigure.web.ServerProperties",
  5. "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
  6. },
  7. {
  8. "name": "spring.jpa.hibernate",
  9. "type": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate",
  10. "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties",
  11. "sourceMethod": "getHibernate()"
  12. }
  13. ...
  14. ],"properties": [
  15. {
  16. "name": "server.port",
  17. "type": "java.lang.Integer",
  18. "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
  19. },
  20. {
  21. "name": "server.address",
  22. "type": "java.net.InetAddress",
  23. "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
  24. },
  25. {
  26. "name": "spring.jpa.hibernate.ddl-auto",
  27. "type": "java.lang.String",
  28. "description": "DDL mode. This is actually a shortcut for the \"hibernate.hbm2ddl.auto\" property.",
  29. "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate"
  30. }
  31. ...
  32. ],"hints": [
  33. {
  34. "name": "spring.jpa.hibernate.ddl-auto",
  35. "values": [
  36. {
  37. "value": "none",
  38. "description": "Disable DDL handling."
  39. },
  40. {
  41. "value": "validate",
  42. "description": "Validate the schema, make no changes to the database."
  43. },
  44. {
  45. "value": "update",
  46. "description": "Update the schema if necessary."
  47. },
  48. {
  49. "value": "create",
  50. "description": "Create the schema and destroy previous data."
  51. },
  52. {
  53. "value": "create-drop",
  54. "description": "Create and then destroy the schema at the end of the session."
  55. }
  56. ]
  57. }
  58. ]}

每个“属性”都是用户使用给定值指定的配置项。例如,server.port并且server.address可能在中指定application.properties,如下所示:

  1. server.port=9090
  2. server.address=127.0.0.1

“组”是更高级别的项目,它们本身并不指定值,而是提供属性的上下文分组。例如,server.portserver.address属性是该server组的一部分。

不需要每个“属性”都有一个“组”。某些属性可能本身就存在。

最后,“提示”是用于帮助用户配置给定属性的其他信息。例如,当开发人员配置spring.jpa.hibernate.ddl-auto属性,工具可以使用提示提供了一些自动完成的帮助nonevalidateupdatecreate,和create-drop值。

1.1。组属性

groups数组中包含的JSON对象可以包含下表中显示的属性:

姓名 类型 目的
name 细绳 组的全名。此属性是必需的。
type 细绳 组数据类型的类名。例如,如果组基于带注释的类@ConfigurationProperties,则该属性将包含该类的完全限定名称。如果基于@Bean方法,则它将是该方法的返回类型。如果类型未知,则可以省略该属性。
description 细绳 可以显示给用户的组的简短描述。如果没有可用的描述,则可以省略。建议使用简短的描述,第一行提供简要的摘要。说明的最后一行应以句点(.)结尾。
sourceType 细绳 贡献此组的源的类名。例如,如果组基于带有@Bean注释的方法@ConfigurationProperties,则此属性将包含@Configuration包含该方法的类的完全限定名称。如果源类型未知,则可以省略该属性。
sourceMethod 细绳 贡献此组的方法的全名(包括括号和参数类型)(例如,带@ConfigurationProperties注释的@Bean方法的名称)。如果源方法未知,则可以省略。

1.2。属性属性

properties数组中包含的JSON对象可以包含下表中描述的属性:

姓名 类型 目的
name 细绳 属性的全名。名称以小写的句点分隔(例如server.address)。此属性是必需的。
type 细绳 属性的数据类型的完整签名(例如java.lang.String),还包含完整的通用类型(例如java.util.Map<java.lang.String,acme.MyEnum>)。您可以使用此属性指导用户输入的值的类型。为了保持一致性,通过使用原始包装的对应对象来指定原始类型(例如,boolean变为java.lang.Boolean)。请注意,此类可能是一个复杂的类型,当String绑定值时会从转换为此类。如果类型未知,则可以省略。
description 细绳 可以显示给用户的属性的简短描述。如果没有可用的描述,则可以省略。建议使用简短的描述,第一行提供简要的摘要。说明的最后一行应以句点(.)结尾。
sourceType 细绳 贡献此属性的源的类名。例如,如果属性来自带有注释的类@ConfigurationProperties,则此属性将包含该类的完全限定名称。如果源类型未知,则可以省略。
defaultValue 目的 默认值,如果未指定该属性,则使用该默认值。如果属性的类型是数组,则它可以是值的数组。如果默认值未知,则可以省略。
deprecation 弃用 指定是否不推荐使用该属性。如果不建议使用该字段,或者该信息未知,则可以将其省略。下表提供了有关该deprecation属性的更多详细信息。

deprecation每个properties元素的属性中包含的JSON对象可以包含以下属性:

姓名 类型 目的
level 细绳 弃用级别,可以是warning(默认值)或error。当某个属性具有warning弃用级别时,它仍应绑定在环境中。但是,当它具有error弃用级别时,该属性将不再受管理且不受约束。
reason 细绳 关于不推荐使用该属性的原因的简短描述。如果没有理由,则可以省略。建议使用简短的描述,第一行提供简要的摘要。说明的最后一行应以句点(.)结尾。
replacement 细绳 替换此不推荐使用的属性的属性的全名。如果无法替代此属性,则可以省略。
在Spring Boot 1.3之前,deprecated可以使用单个布尔属性代替deprecation元素。仍然以不推荐的方式支持此功能,并且不应再使用它。如果没有原因且无法更换,deprecation则应设置一个空对象。

也可以在代码中以声明方式指定@DeprecatedConfigurationProperty不推荐使用的方式,方法是将注释添加到暴露不推荐使用的属性的getter中。例如,假设该app.acme.target属性令人困惑,并将其重命名为app.acme.name。以下示例显示了如何处理这种情况:

  1. @ConfigurationProperties("app.acme")
  2. public class AcmeProperties {
  3. private String name;
  4. public String getName() { ... }
  5. public void setName(String name) { ... }
  6. @DeprecatedConfigurationProperty(replacement = "app.acme.name")
  7. @Deprecated
  8. public String getTarget() {
  9. return getName();
  10. }
  11. @Deprecated
  12. public void setTarget(String target) {
  13. setName(target);
  14. }
  15. }
无法设置一个levelwarning由于代码仍在处理该属性,因此始终假定使用。

前面的代码确保不推荐使用的属性仍然有效(将其委托给name幕后的属性)。一旦getTargetandsetTarget方法可以从公共API中删除,元数据中的自动弃用提示也将消失。如果要保留提示,请添加具有error弃用级别的手动元数据,以确保仍然向用户通知该属性。当replacement提供a时,这样做特别有用。

1.3。提示属性

hints数组中包含的JSON对象可以包含下表中显示的属性:

姓名 类型 目的
name 细绳 该提示所引用的属性的全名。名称以小写的句点分隔(例如spring.mvc.servlet.path)。如果该属性指向地图(例如system.contexts),则提示将应用于地图的system.contexts.keys)或地图的system.contexts.values)。此属性是必需的。
values ValueHint [] ValueHint对象定义的有效值列表(如下表所述)。每个条目都定义该值,并且可以具有描述。
providers ValueProvider [] ValueProvider对象定义的提供者列表(在本文档的后面描述)。每个条目定义提供程序的名称及其参数(如果有)。

values每个hint元素的属性中包含的JSON对象可以包含下表中描述的属性:

姓名 类型 目的
value 目的 提示所引用元素的有效值。如果属性的类型是数组,则它也可以是值的数组。此属性是必需的。
description 细绳 可以显示给用户的值的简短描述。如果没有可用的描述,则可以省略。建议使用简短的描述,第一行提供简要的摘要。说明的最后一行应以句点(.)结尾。

providers每个hint元素的属性中包含的JSON对象可以包含下表中描述的属性:

姓名 类型 目的
name 细绳 用于为提示所引用的元素提供其他内容帮助的提供者的名称。
parameters JSON对象 提供程序支持的任何其他参数(有关更多详细信息,请参阅提供程序的文档)。

1.4。重复的元数据项

具有相同“属性”和“组”名称的对象可以在元数据文件中多次出现。例如,您可以将两个单独的类绑定到同一前缀,每个类具有可能重叠的属性名称。尽管相同的名称多次出现在元数据中不应该很常见,但元数据的使用者应注意确保他们支持该名称。

2.提供手动提示

为了改善用户体验并进一步帮助用户配置给定属性,您可以提供其他元数据,这些元数据可以:

  • 描述属性的潜在值列表。
  • 关联提供程序,以将定义良好的语义附加到属性,以便工具可以根据项目的上下文发现潜在值的列表。

    2.1。价值提示

    name每个提示的属性均指name属性的。在前面所示的初始例子,我们为提供五个值spring.jpa.hibernate.ddl-auto属性:nonevalidateupdatecreate,和create-drop。每个值也可以具有描述。
    如果您的媒体资源类型为Map,则可以为键和值(而不是地图本身)提供提示。特殊.keys.values后缀必须分别引用键和值。
    假设sample.contexts将魔法String值映射为整数,如以下示例所示:
    1. @ConfigurationProperties("sample")
    2. public class SampleProperties {
    3. private Map<String,Integer> contexts;
    4. // getters and setters
    5. }
    魔术值(在此示例中)是sample1sample2。为了提供有关键的其他内容帮助,您可以将以下JSON添加到模块的手动元数据中
    1. {"hints": [
    2. {
    3. "name": "sample.contexts.keys",
    4. "values": [
    5. {
    6. "value": "sample1"
    7. },
    8. {
    9. "value": "sample2"
    10. }
    11. ]
    12. }
    13. ]}
    | | 我们建议您Enum对这两个值使用代替。如果您的IDE支持,则这是迄今为止最有效的自动完成方法。 | | :—-: | —- |

2.2。价值提供者

提供程序是将语义附加到属性的有效方法。在本节中,我们定义了可用于您自己的提示的官方提供程序。但是,您最喜欢的IDE可能只实现其中一些,也可能不实现。而且,它最终可以提供自己的。

由于这是一项新功能,IDE供应商必须赶上它的工作方式。采用时间自然会有所不同。

下表总结了受支持的提供程序的列表:

姓名 描述
any 允许提供任何附加值。
class-reference 自动完成项目中可用的类。通常受target参数指定的基类约束。
handle-as 处理属性,就好像它是由强制target参数定义的类型定义的一样。
logger-name 自动完成有效的记录器名称和记录器组。通常,可以自动完成当前项目中可用的程序包和类名称以及定义的组。
spring-bean-reference 自动完成当前项目中的可用bean名称。通常受target参数指定的基类约束。
spring-profile-name 自动完成项目中可用的Spring概要文件名称。
对于给定的属性,只有一个提供程序可以处于活动状态,但是如果它们都可以通过某种方式全部管理该属性则可以指定多个提供程序。确保将最强大的提供程序放在首位,因为IDE必须使用它可以处理的JSON部分中的第一个。如果不支持给定属性的提供程序,则也不提供特殊的内容帮助。

2.2.1。任何

特殊的任何提供程序值允许提供任何其他值。如果支持,则应基于属性类型进行常规值验证。
如果您具有值列表,并且任何其他值仍应视为有效,则通常使用此提供程序。
以下示例提供onoff作为自动完成值system.state

  1. {"hints": [
  2. {
  3. "name": "system.state",
  4. "values": [
  5. {
  6. "value": "on"
  7. },
  8. {
  9. "value": "off"
  10. }
  11. ],
  12. "providers": [
  13. {
  14. "name": "any"
  15. }
  16. ]
  17. }
  18. ]}

注意,在前面的示例中,还允许任何其他值。

2.2.2。类参考

类引用项目中可用提供商自动完成课程。该提供程序支持以下参数:

范围 类型 默认值 描述
target StringClass 没有 应分配给所选值的类的完全限定名称。通常用于过滤掉非候选类。请注意,可以通过暴露具有适当上限的类来由类型本身提供此信息。
concrete boolean 真的 指定是否仅将具体类视为有效候选者。

以下元数据片段对应于server.servlet.jsp.class-name定义JspServlet要使用的类名称的standard属性:

  1. {"hints": [
  2. {
  3. "name": "server.servlet.jsp.class-name",
  4. "providers": [
  5. {
  6. "name": "class-reference",
  7. "parameters": {
  8. "target": "javax.servlet.http.HttpServlet"
  9. }
  10. }
  11. ]
  12. }
  13. ]}

2.2.3。处理为

手柄的供应商,您可以替代属性的类型到一个更高层次的类型。当属性具有java.lang.String类型时,通常会发生这种情况,因为您不希望配置类依赖于可能不在类路径中的类。该提供程序支持以下参数:

范围 类型 默认值 描述
target StringClass 没有 要为属性考虑的类型的标准名称。此参数是必需的。

可以使用以下类型:

  • 任意java.lang.Enum:列出属性的可能值。(我们建议使用Enum类型定义属性,因为IDE不需要其他提示即可自动完成值)
  • java.nio.charset.Charset:支持字符集/编码值(例如UTF-8)的自动完成
  • java.util.Locale:自动完成语言环境(例如en_US
  • org.springframework.util.MimeType:支持内容类型值(例如text/plain)的自动完成
  • org.springframework.core.io.Resource:支持自动完成Spring的Resource抽象,以引用文件系统或类路径(例如classpath:/sample.properties)上的文件
    | | 如果可以提供多个值,请使用Collection数组类型向IDE讲解。 | | :—-: | —- |

以下元数据片段对应于标准spring.liquibase.change-log属性,该属性定义要使用的变更日志的路径。它实际上在内部用作a,org.springframework.core.io.Resource但不能这样公开,因为我们需要保留原始的String值以将其传递给Liquibase API。

  1. {"hints": [
  2. {
  3. "name": "spring.liquibase.change-log",
  4. "providers": [
  5. {
  6. "name": "handle-as",
  7. "parameters": {
  8. "target": "org.springframework.core.io.Resource"
  9. }
  10. }
  11. ]
  12. }
  13. ]}

2.2.4。记录仪名称

记录器名提供商自动完成有效的记录名称和记录器组。通常,可以自动完成当前项目中可用的包和类名。如果启用了组(默认),并且在配置中标识了自定义记录程序组,则应为其提供自动完成功能。特定框架可能还具有额外的魔术记录器名称,这些名称也可以得到支持。
该提供程序支持以下参数:

范围 类型 默认值 描述
group boolean true 指定是否应考虑已知组。

由于记录器名称可以是任意名称,因此该提供程序应允许使用任何值,但可以突出显示项目的类路径中不可用的有效程序包和类名称。
以下元数据片段对应于standardlogging.level属性。键是记录器名称,值对应于标准日志级别或任何自定义级别。当Spring Boot开箱即用地定义了一些记录器组时,已经为它们添加了专用的值提示。

  1. {"hints": [
  2. {
  3. "name": "logging.level.keys",
  4. "values": [
  5. {
  6. "value": "root",
  7. "description": "Root logger used to assign the default logging level."
  8. },
  9. {
  10. "value": "sql",
  11. "description": "SQL logging group including Hibernate SQL logger."
  12. },
  13. {
  14. "value": "web",
  15. "description": "Web logging group including codecs."
  16. }
  17. ],
  18. "providers": [
  19. {
  20. "name": "logger-name"
  21. }
  22. ]
  23. },
  24. {
  25. "name": "logging.level.values",
  26. "values": [
  27. {
  28. "value": "trace"
  29. },
  30. {
  31. "value": "debug"
  32. },
  33. {
  34. "value": "info"
  35. },
  36. {
  37. "value": "warn"
  38. },
  39. {
  40. "value": "error"
  41. },
  42. {
  43. "value": "fatal"
  44. },
  45. {
  46. "value": "off"
  47. }
  48. ],
  49. "providers": [
  50. {
  51. "name": "any"
  52. }
  53. ]
  54. }
  55. ]}

2.2.5。Spring Bean参考

弹簧豆参考提供商自动完成当前项目的配置中定义的豆类。该提供程序支持以下参数:

范围 类型 默认值 描述
target StringClass 没有 应分配给候选者的Bean类的完全限定名称。通常用于过滤掉非候选豆。

以下元数据片段对应于标准spring.jmx.server属性,该属性定义了MBeanServer要使用的Bean的名称:

  1. {"hints": [
  2. {
  3. "name": "spring.jmx.server",
  4. "providers": [
  5. {
  6. "name": "spring-bean-reference",
  7. "parameters": {
  8. "target": "javax.management.MBeanServer"
  9. }
  10. }
  11. ]
  12. }
  13. ]}
活页夹不知道元数据。如果提供了该提示,则仍然需要使用by将Bean名称转换为实际的Bean引用ApplicationContext

2.2.6。春季资料名称

弹簧轮廓名提供商自动完成当前项目的配置中定义的春天配置文件。
以下元数据片段对应于标准spring.profiles.active属性,该属性定义了要启用的Spring概要文件的名称:

  1. {"hints": [
  2. {
  3. "name": "spring.profiles.active",
  4. "providers": [
  5. {
  6. "name": "spring-profile-name"
  7. }
  8. ]
  9. }
  10. ]}

3.使用注释处理器生成自己的元数据

您可以@ConfigurationProperties使用spring-boot-configuration-processorjar轻松地从带有注释的项目中生成自己的配置元数据文件。该jar包含一个Java注释处理器,在您的项目被编译时会被调用。

3.1。配置注释处理器

要使用处理器,请包含对的依赖spring-boot-configuration-processor
使用Maven,依赖项应声明为可选,如以下示例所示:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-configuration-processor</artifactId>
  4. <optional>true</optional>
  5. </dependency>

使用Gradle,应在annotationProcessor配置中声明依赖项,如以下示例所示:

  1. dependencies {
  2. annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
  3. }

如果使用additional-spring-configuration-metadata.json文件,compileJava则应将任务配置为依赖于该processResources任务,如以下示例所示:

  1. compileJava.inputs.files(processResources)

这种依赖性确保注释处理器在编译期间运行时,其他元数据可用。

| | 如果在项目中使用AspectJ,则需要确保注释处理器仅运行一次。有几种方法可以做到这一点。使用Maven,您可以maven-apt-plugin显式配置显式并将依赖项仅添加到注释处理器中。您也可以让AspectJ插件运行所有处理并在maven-compiler-plugin配置中禁用注释处理,如下所示:```

org.apache.maven.plugins maven-compiler-plugin none

  1. |
  2. | :---: | --- |
  3. <a name="configuration-metadata-annotation-processor-metadata-generation"></a>
  4. ### 3.2。自动元数据生成
  5. 处理器选择用注释的类和方法`@ConfigurationProperties`。<br />如果该类也用注释`@ConstructorBinding`,则应该使用一个构造函数,并且每个构造函数参数都将创建一个属性。否则,将通过对集合和地图类型进行特殊处理的标准gettersetter来发现属性(即使仅存在getter也会被检测到)。注解处理器还支持使用的`@Data``@Getter``@Setter`Lombok的注释。<br />考虑以下示例:

@ConfigurationProperties(prefix=”server”) public class ServerProperties { /**

  1. * Name of the server.
  2. */
  3. private String name;
  4. /**
  5. * IP address to listen to.
  6. */
  7. private String ip = "127.0.0.1";
  8. /**
  9. * Port to listener to.
  10. */
  11. private int port = 9797;
  12. // ... getter and setters

}

  1. 这暴露了三个属性,其中`server.name`有没有缺省值,`server.ip``server.port`默认为`"127.0.0.1"``9797`分别。字段上的Javadoc用于填充`description`属性。例如,描述`server.ip`为“要收听的IP地址”。
  2. | | 您仅应将纯文本与`@ConfigurationProperties`Javadoc字段一起使用,因为在将纯文本添加到JSON之前不会对其进行处理。 |
  3. | :---: | --- |
  4. 注释处理器应用多种启发式方法从源模型中提取默认值。必须静态提供默认值。特别是不要引用另一个类中定义的常量。另外,注释处理器无法自动检测`Enum`s`Collections`s的默认值。<br />对于无法检测到默认值的情况,应提供[手动元数据](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-configuration-metadata.html#configuration-metadata-additional-metadata)。考虑以下示例:

@ConfigurationProperties(prefix = “acme.messaging”) public class MessagingProperties { private List addresses = new ArrayList<>(Arrays.asList(“a”, “b”)); private ContainerType containerType = ContainerType.SIMPLE; // … getter and setters public enum ContainerType { SIMPLE, DIRECT } }

  1. 为了记录以上类中属性的默认值,您可以将以下内容添加到[模块的手动元数据中](https://docs.spring.io/spring-boot/docs/2.4.3/reference/html/appendix-configuration-metadata.html#configuration-metadata-additional-metadata):

{“properties”: [ { “name”: “acme.messaging.addresses”, “defaultValue”: [“a”, “b”] }, { “name”: “acme.messaging.container-type”, “defaultValue”: “simple” } ]}

  1. | | `name`属性的即可记录现有属性的其他元数据。 |
  2. | :---: | --- |
  3. <a name="configuration-metadata-annotation-processor-metadata-generation-nested"></a>
  4. #### 3.2.1。嵌套属性
  5. 注释处理器自动将内部类视为嵌套属性。除了可以在命名空间的根目录中记录`ip`和之外`port`,我们还可以为其创建一个子命名空间。考虑更新后的示例:

@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.nameserver.host.ipserver.host.port属性。您可以@NestedConfigurationProperty`在字段上使用注释来指示应将常规(非内部)类视为嵌套类。

这对集合和地图没有影响,因为会自动识别这些类型,并为每个集合生成一个元数据属性。

3.3。添加其他元数据

Spring Boot的配置文件处理非常灵活,通常情况下可能存在未绑定到@ConfigurationPropertiesBean的属性。您可能还需要调整现有键的某些属性。为了支持这种情况,并允许您提供自定义的“提示”,注释处理器会自动将项目从其中合并META-INF/additional-spring-configuration-metadata.json到主元数据文件中。
如果引用了已自动检测到的属性,则如果指定,则将覆盖描述,默认值和弃用信息。如果当前模块中未标识手动属性声明,则将其添加为新属性。
additional-spring-configuration-metadata.json文件的格式与常规格式完全相同spring-configuration-metadata.json。附加属性文件是可选的。如果没有任何其他属性,请不要添加文件。