1. 概述
編寫 Spring Boot 應用程序時,將配置屬性映射到 Java Bean 是一種有益的做法。那麼,如何最好地記錄這些屬性呢?
在本教程中,我們將探索 Spring Boot 配置處理器 以及 相關的 JSON 元數據文件,這些文件記錄了每個屬性的含義、約束條件等信息。
2. 配置元數據
我們作為開發人員所接觸的大部分應用程序都需要進行一定程度的配置。然而,通常我們並不真正理解配置參數的作用、是否有默認值、是否已過時,有時甚至不知道該屬性是否存在。
為了幫助我們,Spring Boot 會在 JSON 文件中生成配置元數據,從而提供關於如何使用屬性的有用信息。因此,配置元數據是一個描述性文件,包含與配置屬性交互所需的信息。
這個文件的最棒之處在於,IDE 也可以讀取它,從而提供 Spring 屬性的自動補全功能,以及其他配置提示。
3. 依賴項
為了生成此配置元數據,我們將使用來自 spring-boot-configuration-processor 依賴項 的配置處理器。
因此,我們來添加該依賴項,並將其設置為可選:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>3.1.5</version>
<optional>true</optional>
</dependency>這個依賴項將在我們構建項目時提供一個 Java 註解處理器。稍後我們會更詳細地討論它。
為了在 Maven 中添加依賴項時採用最佳實踐,建議將其標記為 可選的,以防止將 @ConfigurationProperties 應用到我們項目使用的其他模塊。
4. 配置屬性示例
為了觀察處理器在行動中的效果,讓我們假設我們需要將一些屬性包含在我們的 Spring Boot 應用程序中,通過一個 Java Bean:
@Configuration
@ConfigurationProperties(prefix = "database")
public class DatabaseProperties {
public static class Server {
private String ip;
private int port;
// standard getters and setters
}
private String username;
private String password;
private Server server;
// standard getters and setters
}要做到這一點,我們將使用 @ConfigurationProperties 註解。 配置處理器會掃描具有此註解的類和方法,以訪問配置參數並生成配置元數據。
讓我們將幾個這些屬性添加到 properties 文件中。 在這種情況下,我們將它命名為 databaseproperties-test.properties。
#Simple Properties
database.username=baeldung
database.password=password為了確保一切正常,我們還將添加一個測試,以驗證我們是否已就位:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AnnotationProcessorApplication.class)
@TestPropertySource("classpath:databaseproperties-test.properties")
public class DatabasePropertiesIntegrationTest {
@Autowired
private DatabaseProperties databaseProperties;
@Test
public void whenSimplePropertyQueriedThenReturnsPropertyValue()
throws Exception {
Assert.assertEquals("Incorrectly bound Username property",
"baeldung", databaseProperties.getUsername());
Assert.assertEquals("Incorrectly bound Password property",
"password", databaseProperties.getPassword());
}
}我們還添加了嵌套屬性 database.server.id 和 database.server.port,通過內部類 Server 實現。 應該同時添加內部類 Server 以及包含自身 getter 和 setter 的字段。 在我們的測試中,讓我們快速檢查一下,確保我們能夠成功地設置和讀取嵌套屬性:
@Test
public void whenNestedPropertyQueriedThenReturnsPropertyValue()
throws Exception {
Assert.assertEquals("Incorrectly bound Server IP nested property",
"127.0.0.1", databaseProperties.getServer().getIp());
Assert.assertEquals("Incorrectly bound Server Port nested property",
3306, databaseProperties.getServer().getPort());
}現在,我們準備好使用處理器了。
5. 生成配置元數據
我們之前提到,配置處理器會生成一個文件,它使用註解處理來實現這個功能。
因此,在編譯我們的項目後,我們會看到一個名為 spring-configuration-metadata.json 的文件,位於 target/classes/META-INF 目錄下。
{
"groups": [
{
"name": "database",
"type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server",
"type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceMethod": "getServer()"
}
],
"properties": [
{
"name": "database.password",
"type": "java.lang.String",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server.ip",
"type": "java.lang.String",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server"
},
{
"name": "database.server.port",
"type": "java.lang.Integer",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"defaultValue": 0
},
{
"name": "database.username",
"type": "java.lang.String",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties"
}
],
"hints": []
}接下來,讓我們看看修改 Java 豆上的註釋如何影響元數據。
5.1. 關於配置元數據的補充信息
首先,讓我們為 Server 添加 JavaDoc 註釋。
其次,讓我們為 database.server.port 字段設置默認值,並最終添加 @Min 和 @Max 註解。
public static class Server {
/**
* The IP of the database server
*/
private String ip;
/**
* The Port of the database server.
* The Default value is 443.
* The allowed values are in the range 400-4000.
*/
@Min(400)
@Max(800)
private int port = 443;
// standard getters and setters
}如果現在檢查 spring-configuration-metadata.json 文件,我們將會看到這些額外信息被反映出來:
{
"groups": [
{
"name": "database",
"type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server",
"type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceMethod": "getServer()"
}
],
"properties": [
{
"name": "database.password",
"type": "java.lang.String",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server.ip",
"type": "java.lang.String",
"description": "The IP of the database server",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server"
},
{
"name": "database.server.port",
"type": "java.lang.Integer",
"description": "The Port of the database server. The Default value is 443.
The allowed values are in the range 400-4000",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"defaultValue": 443
},
{
"name": "database.username",
"type": "java.lang.String",
"sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties"
}
],
"hints": []
}我們可以通過檢查 database.server.ip 和 database.server.port 字段來驗證差異。 事實上,這些額外信息非常有幫助。 因此,開發人員和 IDE 能夠更輕鬆地理解每個屬性的作用。
我們還應該確保觸發構建以獲取更新後的文件。 在 Eclipse 中,如果選中 Build Automatically 選項,每次保存操作都會觸發構建。 在 IntelliJ 中,我們應該手動觸發構建。
5.2. 理解元數據格式
讓我們更詳細地瞭解 JSON 元數據文件及其組成部分。
<em>組 (Groups)</em> 是更高層次的項目,用於將其他屬性分組,而無需指定其值本身。 在我們的示例中,我們有數據庫 (database) 組,它也是配置屬性的前綴。 我們還有一個 <em>服務器 (server)</em> 組,該組由內部類創建,幷包含ip 和 <em>端口 (port)</em> 屬性。
<em>屬性 (Properties)</em> 是我們可以指定值的配置項。 這些屬性存儲在.properties 或 `.yml 文件中,並且可以包含額外信息,例如默認值和驗證規則,正如我們在上面的示例中看到的。
`提示 (Hints) 是幫助用户設置屬性值的額外信息。 例如,如果對於一個屬性,我們有允許的值集,我們可以提供每個值的描述。 IDE 將為這些提示提供自動補全幫助。
每個配置元數據組件都有自己的 `屬性 (attributes),用於更詳細地解釋配置屬性。
6. 結論
在本文中,我們探討了 Spring Boot Configuration Processor 以及它創建配置元數據的能力。利用這些元數據使得與配置參數的交互變得更加容易。
我們提供了一個生成的配置元數據示例,並詳細解釋了它的格式和組件。
我們還看到了 IDE 自補全支持的實用性。