附录 B.配置元数据

Spring Boot jar 附带有元数据文件,这些文件提供了所有受支持的配置属性的详细信息。这些文件旨在允许 IDE 开发人员在用户处理application.propertiesapplication.yml文件时提供上下文帮助和“代码完成”。

通过处理带有@ConfigurationPropertiesComments 的所有项目,大多数元数据文件会在编译时自动生成。但是,对于极端情况或更高级的用例,可以手动写入部分元数据

B.1 元数据格式

配置元数据文件位于META-INF/spring-configuration-metadata.json下的 jar 内,它们使用简单的 JSON 格式,将项目归类为“组”或“属性”,并将其他 Value hint 归类为“提示”:

{"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.servlet-path",
        "type": "java.lang.String",
        "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
        "defaultValue": "/"
    },
    {
          "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."
            }
        ]
    }
]}

每个“属性”都是用户使用给定值指定的配置项。例如,可以在application.properties中指定server.portserver.servlet-path,如下所示:

server.port=9090
server.servlet-path=/home

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

Note

不需要每个“属性”都有一个“组”,某些属性可能仅凭其自身存在。

最后,“提示”是用于帮助用户配置给定属性的其他信息。配置spring.jpa.hibernate.ddl-auto属性时,工具可以使用它为nonevalidateupdatecreatecreate-drop值提供一些自动完成帮助。

B.1.1 组属性

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

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

B.1.2 属性属性

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

NameTypePurpose
nameString属性的全名。名称采用小写的虚线形式(例如server.servlet-path)。此属性是必需的。
typeString属性数据类型的完整签名。例如,java.lang.String也是完整的通用类型,例如java.util.Map<java.util.String,acme.MyEnum>。此属性可用于指导用户 Importing 的值的类型。为了保持一致性,使用包装的对应对象指定了 Primitives 的类型,即boolean变为java.lang.Boolean。请注意,此类可能是一个复杂类型,当绑定值时,它会从 String 转换而来。如果类型未知,则可以省略。
descriptionString可以显示给用户的组的简短描述。如果没有可用的描述,可以省略。建议描述简短,第一行提供简要的摘要。说明中的最后一行应以句点(.)结尾。
sourceTypeString贡献此属性的源的类名。例如,如果属性来自带有@ConfigurationPropertiesComments 的类,则此属性将包含该类的完全限定名称。如果源类型未知,则可以省略。
defaultValueObject如果未指定该属性,则将使用默认值。如果属性的类型是数组,则也可以是值的数组。如果默认值未知,则可以省略。
deprecationDeprecation指定是否不推荐使用该属性。如果不建议使用该字段,或者该信息未知,则可以省略。请参阅下面的更多细节。

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

NameTypePurpose
levelString弃用级别可以是warning(默认值)或error。当某个属性具有warning弃用级别时,它仍应在环境中绑定。但是,当它具有error弃用级别时,该属性将不再受 Management,也不会被绑定。
reasonString对不推荐使用该属性的原因的简短描述。如果没有理由,可以省略。建议描述简短,第一行提供简要的摘要。说明中的最后一行应以句点(.)结尾。
replacementString属性的全名,该属性“替换”了不推荐使用的属性。如果无法替换此属性,则可以省略。

Note

在 Spring Boot 1.3 之前,可以使用单个deprecated布尔属性代替deprecation元素。仍然以不推荐的方式支持此功能,并且不应再使用它。如果没有原因和可用的替代方法,则应设置一个空的deprecation对象。

通过将@DeprecatedConfigurationProperty注解添加到暴露不推荐使用的属性的 getter 中,也可以在代码中以声明方式指定不推荐使用。例如,假设app.foo.target属性令人困惑,并将其重命名为app.foo.name

@ConfigurationProperties("app.foo")
public class FooProperties {

    private String name;

    public String getName() { ... }

    public void setName(String name) { ... }

    @DeprecatedConfigurationProperty(replacement = "app.foo.name")
    @Deprecated
    public String getTarget() {
        return getName();
    }

    @Deprecated
    public void setTarget(String target) {
        setName(target);
    }
}

Note

由于代码仍在处理该属性,因此始终无法将level设置为warning

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

B.1.3 提示属性

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

NameTypePurpose
nameString该提示所引用的属性的全名。名称采用小写的虚线形式(例如server.servlet-path)。如果属性引用的是 Map(例如system.contexts),则提示将应用于 Map 的键(system.context.keys)或值(system.context.values)。此属性是必需的。
valuesValueHint[]ValueHint对象定义的有效值列表(请参见下文)。每个条目定义值,并可能有描述
providersValueProvider[]ValueProvider对象定义的提供者列表(请参见下文)。每个条目定义提供者的名称及其参数(如果有)。

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

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

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

NameTypePurpose
nameString用于为提示所引用的元素提供附加内容帮助的提供者的名称。
parametersJSON object提供程序支持的任何其他参数(有关更多详细信息,请参阅提供程序的文档)。

B.1.4 重复的元数据项

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

B.2 提供手动提示

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

  • 描述属性的潜在值列表。

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

B.2.1Value hint

每个提示的name属性是指属性的name。在上面的初始示例中,我们为spring.jpa.hibernate.ddl-auto属性提供了 5 个值:nonevalidateupdatecreatecreate-drop。每个值也可以具有描述。

如果您的属性类型为Map,则可以提供键和值的提示(但不提供 Map 本身的提示)。必须使用特殊的.keys.values后缀来分别指代键和值。

假设foo.contexts将魔术字符串值 Map 为整数:

@ConfigurationProperties("foo")
public class FooProperties {

    private Map<String,Integer> contexts;
    // getters and setters
}

魔术值例如是 foo 和 bar。为了提供有关键的其他内容帮助,您可以将以下内容添加到模块的手动元数据

{"hints": [
    {
        "name": "foo.contexts.keys",
        "values": [
            {
                "value": "foo"
            },
            {
                "value": "bar"
            }
        ]
    }
]}

Note

当然,您应该为这两个值使用Enum。如果您的 IDE 支持,这是迄今为止最有效的自动完成方法。

B.2.2Value provider

提供程序是将语义附加到属性的强大方法。我们在下面的部分中定义了您可以用来提供自己提示的官方提供程序。但是请记住,您最喜欢的 IDE 可能不会实现其中一些。它最终也可以提供自己的。

Note

由于这是一项新功能,IDE 供应商将不得不赶上这项新功能。

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

NameDescription
any允许提供任何附加值。
class-reference自动完成项目中可用的类。通常受通过target参数指定的 Base Class 的约束。
handle-as处理属性,就好像它是通过强制性target参数定义的类型定义的一样。
logger-name自动填写有效的 Logger 名称。通常,可以自动完成当前项目中可用的包和类名。
spring-bean-reference自动完成当前项目中的可用 bean 名称。通常受通过target参数指定的 Base Class 的约束。
spring-profile-name自动完成项目中可用的 Spring 概要文件名称。

Tip

对于一个给定的属性,最多只能有一个提供程序是 Active,但是如果它们可以以某种方式全部 Management 该属性,则可以指定多个提供程序。确保将最强大的提供程序放在首位,因为 IDE 必须使用它可以处理的 JSON 部分中的第一个。如果不支持给定属性的提供程序,则也不提供特殊的内容帮助。

Any

any 提供程序允许提供任何其他值。如果支持,则应基于属性类型进行常规值验证。

如果您具有值列表并且任何其他值仍被视为有效,则通常使用此提供程序。

下面的示例提供onoff作为system.state的自动完成值;也可以使用任何其他值:

{"hints": [
    {
        "name": "system.state",
        "values": [
            {
                "value": "on"
            },
            {
                "value": "off"
            }
        ],
        "providers": [
            {
                "name": "any"
            }
        ]
    }
]}

Class reference

类别参考提供程序会自动完成项目中可用的类别。此提供程序支持以下参数:

ParameterTypeDefault valueDescription
targetString ( Class )none应分配给所选值的类的完全限定名称。通常用于过滤非候选类。请注意,可以通过暴露具有适当上限的类来由类型本身提供此信息。
concretebooleantrue指定是否仅将具体类别视为有效候选者。

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

{"hints": [
    {
        "name": "server.jsp-servlet.class-name",
        "providers": [
            {
                "name": "class-reference",
                "parameters": {
                    "target": "javax.servlet.http.HttpServlet"
                }
            }
        ]
    }
]}

Handle As

handle-as 提供程序允许您将属性的类型替换为更高级的类型。当属性具有java.lang.String类型时,通常会发生这种情况,因为您不希望配置类依赖于可能不在 Classpath 中的类。此提供程序支持以下参数:

ParameterTypeDefault valueDescription
targetString ( Class )none要为属性考虑的类型的标准名称。此参数是必需的。

可以使用以下类型:

  • 列出该属性的可能值的任何java.lang.Enum(通过所有方式,请尝试使用Enum类型定义该属性,因为 IDE 不需要其他提示即可自动完成这些值)。

  • 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 的 Resource 抽象,以引用文件系统或 Classpath 上的文件。 (例如classpath:/foo.properties)

Note

如果可以提供多个值,请使用Collection或* Array *类型向 IDE 讲解。

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

{"hints": [
    {
        "name": "liquibase.change-log",
        "providers": [
            {
                "name": "handle-as",
                "parameters": {
                    "target": "org.springframework.core.io.Resource"
                }
            }
        ]
    }
]}

Logger name

Logger 名称提供程序会自动填写有效的 Logger 名称。通常,可以自动完成当前项目中可用的包和类名。特定框架可能还具有其他可能支持的魔术 Logger 名称。

由于 Logger 名称可以是任意名称,因此,此提供程序实际上应该允许任何值,但可以突出显示项目的 Classpath 中不可用的有效包和类名称。

以下元数据代码段对应于标准logging.level属性,键是* logger 名称*,值对应于标准日志级别或任何自定义级别:

{"hints": [
    {
        "name": "logging.level.keys",
        "values": [
            {
                "value": "root",
                "description": "Root logger used to assign the default logging level."
            }
        ],
        "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 参考

spring-bean-reference 提供程序会自动完成在当前项目的配置中定义的 bean。此提供程序支持以下参数:

ParameterTypeDefault valueDescription
targetString ( Class )none应分配给候选者的 Bean 类的完全限定名称。通常用于过滤非候选 bean。

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

{"hints": [
    {
        "name": "spring.jmx.server",
        "providers": [
            {
                "name": "spring-bean-reference",
                "parameters": {
                    "target": "javax.management.MBeanServer"
                }
            }
        ]
    }
]}

Note

绑定程序不了解元数据,因此,如果您提供该提示,则仍然需要使用ApplicationContext将 bean 名称转换为实际的 Bean 引用。

SpringProfile 名称

spring-profile-name **提供程序会自动完成在当前项目的配置中定义的 Spring 概要文件。

以下元数据代码段对应于标准spring.profiles.active属性,该属性定义了要启用的 Spring 配置文件的名称:

{"hints": [
    {
        "name": "spring.profiles.active",
        "providers": [
            {
                "name": "spring-profile-name"
            }
        ]
    }
]}

B.3 使用 Comments 处理器生成自己的元数据

您可以使用spring-boot-configuration-processor jar 从@ConfigurationPropertiesComments 的项目中轻松生成自己的配置元数据文件。该 jar 包含一个 JavaComments 处理器,在您的项目被编译时会被调用。要使用处理器,只需将spring-boot-configuration-processor作为可选依赖项包含在内,例如,对于 Maven,您将添加:

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

使用 Gradle,您可以使用propdeps-plugin并指定:

dependencies {
    optional "org.springframework.boot:spring-boot-configuration-processor"
}

compileJava.dependsOn(processResources)

Note

您需要在构建中添加compileJava.dependsOn(processResources),以确保在编译代码之前已处理资源。如果没有此指令,将不会处理任何additional-spring-configuration-metadata.json文件。

处理器将选择用@ConfigurationPropertiesComments 的类和方法。配置类中字段值的 Javadoc 将用于填充description属性。

Note

您仅应将简单文本与@ConfigurationProperties字段 Javadoc 一起使用,因为在添加到 JSON 之前不会对其进行处理。

属性的发现是通过对集合类型进行特殊处理的标准 getter 和 setter 进行的(即使仅存在 getter 也会被检测到)。Comments 处理器还支持@Data@Getter@Setter lombokComments 的使用。

Note

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

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<proc>none</proc>
</configuration>
</plugin>

B.3.1 嵌套的属性

Comments 处理器将自动将内部类视为嵌套属性。例如,以下类:

@ConfigurationProperties(prefix="server")
public class ServerProperties {

    private String name;

    private Host host;

    // ... getter and setters

    private static class Host {

        private String ip;

        private int port;

        // ... getter and setters

    }

}

将产生server.nameserver.host.ipserver.host.port属性的元数据信息。您可以在字段上使用@NestedConfigurationProperty注解来指示应将常规(非内部)类视为嵌套类。

Tip

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

B.3.2 添加其他元数据

Spring Boot 的配置文件处理非常灵活。通常情况下,可能存在不绑定到@ConfigurationProperties bean 的属性。您可能还需要调整现有键的某些属性。为了支持这种情况并允许您提供自定义“提示”,Comments 处理器将自动将META-INF/additional-spring-configuration-metadata.json中的项目合并到主元数据文件中。

如果引用了已自动检测到的属性,则如果指定,则将覆盖描述,默认值和弃用信息。如果在当前模块中未标识手动属性声明,则将其添加为全新属性。

additional-spring-configuration-metadata.json文件的格式与常规spring-configuration-metadata.json完全相同。附加属性文件是可选的,如果您没有任何其他属性,则只需添加即可。