附录 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.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."
			}
		]
	}
]}

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

server.port=9090
server.address=127.0.0.1

“组”是更高级别的项目,它们本身并不指定值,而是提供属性的上下文分组。例如,server.portserver.address属性是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.address)。此属性是必需的。
typeString属性的数据类型的完整签名(例如java.lang.String),但也包含完整的通用类型(例如java.util.Map<java.util.String,acme.MyEnum>)。您可以使用此属性指导用户 Importing 的值的类型。为了保持一致性,通过使用包装的对应对象来指定基元的类型(例如boolean变为java.lang.Boolean)。请注意,此类可能是一个复杂的类型,当绑定值时,它会从String转换而来。如果类型未知,则可以省略。
descriptionString可以显示给用户的组的简短描述。如果没有可用的描述,则可以省略。建议使用简短的描述,第一行提供简要的摘要。说明中的最后一行应以句点(.)结尾。
sourceTypeString贡献此属性的源的类名。例如,如果属性来自带有@ConfigurationPropertiesComments 的类,则此属性将包含该类的完全限定名称。如果源类型未知,则可以省略。
defaultValueObject默认值,如果未指定该属性,则使用该默认值。如果属性的类型是数组,则它可以是值的数组。如果默认值未知,则可以省略。
deprecationDeprecation指定是否不推荐使用该属性。如果不建议使用该字段,或者该信息未知,则可以将其省略。下表提供了有关deprecation属性的更多详细信息。

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

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

Note

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

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

@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);
	}
}

Note

无法设置level。始终假定warning,因为代码仍在处理该属性。

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

B.1.3 提示属性

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

NameTypePurpose
nameString该提示所引用的属性的全名。名称以小写的句点分隔(例如spring.mvc.servlet.path)。如果该属性引用了 Map(例如system.contexts),则提示将应用于 Map 的* keys(system.context.keys)或 Map 的* values *(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.1 Value hint

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

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

假定sample.contexts将魔术String值 Map 为整数,如以下示例所示:

@ConfigurationProperties("sample")
public class SampleProperties {

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

魔术值(在此示例中)是sample1sample2。为了提供有关键的其他内容帮助,您可以将以下 JSON 添加到模块的手动元数据

{"hints": [
	{
		"name": "sample.contexts.keys",
		"values": [
			{
				"value": "sample1"
			},
			{
				"value": "sample2"
			}
		]
	}
]}

Tip

我们建议您对这两个值使用Enum。如果您的 IDE 支持,则这是迄今为止最有效的自动完成方法。

B.2.2 Value provider

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

Note

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

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

NameDescription
any允许提供任何附加值。
class-reference自动完成项目中可用的类。通常受target参数指定的 Base Class 的约束。
handle-as就像按强制性target参数定义的类型定义属性一样处理属性。
logger-name自动填写有效的 Logger 名称和logger groups。通常,可以自动完成当前项目中可用的程序包和类名以及定义的组。
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.servlet.jsp.class-name属性:

{"hints": [
	{
		"name": "server.servlet.jsp.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:/sample.properties)

Tip

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

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

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

Logger Name

logger-name 提供程序会自动填写有效的 logger 名称和logger groups。通常,可以自动完成当前项目中可用的包和类名。如果启用了组(默认),并且在配置中标识了自定义记录程序组,则应为其提供自动完成功能。特定框架可能还具有其他可以支持的魔术 Logger 名称。

该提供程序支持以下参数:

ParameterTypeDefault valueDescription
groupbooleantrue指定是否应考虑已知组。

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

以下元数据片段对应于标准logging.level属性。键是* logger 名称*,其值对应于标准日志级别或任何自定义级别。当 Spring Boot 开箱即用地定义一些 Logger 组时,已经为这些 Logger 添加了专用的 Value hint。

{"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 参考

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

Binder 不知道元数据。如果提供了该提示,则仍然需要使用ApplicationContext将 Bean 名称转换为实际的 Bean 引用。

Spring Profile 名称

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 包含一个 Java Comments 处理器,在您的项目被编译时会被调用。要使用处理器,请包括对spring-boot-configuration-processor的依赖。

使用 Maven,应将依赖项声明为可选,如以下示例所示:

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

对于 Gradle 4.5 及更早版本,依赖关系应在compileOnly配置中声明,如以下示例所示:

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

在 Gradle 4.6 及更高版本中,依赖性应在annotationProcessor配置中声明,如以下示例所示:

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

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

compileJava.dependsOn(processResources)

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

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

Note

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

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

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

	public 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完全相同。附加属性文件是可选的。如果没有任何其他属性,请不要添加文件。