我們在引用spring官方start庫或者第三方start庫時,在寫配置檔案時idea總是能精準的提示,並且滑鼠可以點過去看具體屬性或者類,而自己寫的配置檔案idea只會有“Cannot resolve configuration property ...”這樣的提示。
我們現在也去配置我們自己的配置檔案讓idea知道這些配置檔案是幹什麼的。
一、需要的註解
- @ConfigurationProperties 配置屬性檔案,需要指定字首 prefix
- @EnableConfigurationProperties 啟用配置,需要指定啟用的配置類
- @NestedConfigurationProperty 當一個類中引用了外部類,需要在該屬性上加該註解
二、POM依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
複製程式碼
三、配置類
@Data
public class School {
private Integer no;
private String name;
private String address;
}
複製程式碼
@Data
@ConfigurationProperties(prefix = "jiuxian")
public class JiuxianProperties {
private String name;
private String nameCn;
private String nameEn;
private String[] hobbies;
private SexEnum sexEnum;
private boolean single;
private School school;
private City city;
enum SexEnum {
MAN, WOMAN
}
@Data
static class City {
private String no;
private String name;
}
}
複製程式碼
這個時候@ConfigurationProperties(prefix = "jiuxian") 註解會報錯not registered via @EnableConfigurationProperties or marked as Spring component。這需要加上@EnableConfigurationProperties就可以了
@EnableConfigurationProperties({ JiuxianProperties.class })
@SpringBootApplication
public class SpringbootYmlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootYmlApplication.class, args);
}
}
複製程式碼
四、看效果
然後輸入 mvn clean package
這個時候properties和yml檔案已經可以提示了,不過有一些會有問題,比如jiuxian.school,這是一個物件,idea並不能解析,而因為City物件是個內部類是可以解析的。
如圖:
如何處理呢? 只需要加上 @NestedConfigurationProperty註解即可
@NestedConfigurationProperty
private School school;
複製程式碼
然後輸入命令 mvn clean package
警告消失(會有一點延遲)
五、為什麼
為什麼一定要打包編譯後才可以呢?
看一下打包過後的結構,如圖:
idea之所以會程式碼提示就是因為這個spring-configuration-metadata.json json檔案。這個檔案的生成依據的就是我們上面的配置。
六、進階配置
如果想在配置檔案中能夠提示該欄位描述,以及該欄位可選引數,是否棄用等資訊時,需要加額外的配置
1. 在resources目錄下新建META-INF資料夾,加一個additional-spring-configuration-metadata.json 配置檔案
(1)該配置檔案的節點資訊
- groups 有以下屬性:
- name group的全名,該屬性必須
- type group資料型別的類名。例如,如果group是基於一個被@ConfigurationProperties註解的類,該屬性將包含該類的全限定名。如果基於一個@Bean方法,它將是該方法的返回型別。如果該型別未知,則該屬性將被忽略
- description 一個簡短的group描述,用於展示給使用者,要.點結尾。如果沒有可用描述,該屬性將被忽略
- sourceType 來源類名。例如,如果組基於一個被@ConfigurationProperties註解的@Bean方法,該屬性將包含@Configuration類的全限定名,該類包含此方法。如果來源型別未知,則該屬性將被忽略
- sourceMethod 該組的方法的全名(包含括號及引數型別)。例如,被@ConfigurationProperties註解的@Bean方法名。如果源方法未知,該屬性將被忽略
"groups"是高階別的節點,它們本身不指定一個值,但為properties提供一個有上下文關聯的分組。例如,server.port和server.servlet-path屬性是server組的一部分。
注:不需要每個"property"都有一個"group",一些屬性可以以自己的形式存在。
-
properties
- name 屬性全名,格式為小寫虛線分割的形式(jiuxian.name-en).必須要有的
- type 屬性資料型別,java.lang.Boolean。型別未知可忽略
- description 該屬性的描述
- sourceType 來源型別,例如,如果property來自一個被@ConfigurationProperties註解的類,該屬性將包括該類的全限定名。如果來源型別未知則該屬性會被忽略
- defaultValue 定義輸入時的預設值,只是提示,並不是真正的預設值,可忽略
- deprecated 是否廢棄 boolean 值
- level 級別 error,warning
- reason 廢棄原因
- replacement 替代屬性,為properties 全名
-
hints 可以給屬性提供可選的值,以級描述
- name 屬性全名,不能為空
- values 可選的值
詳細看示例
{
"groups": [
{
"name": "jiuxian",
"sourceType": "com.jiuxian.config.JiuxianProperties",
"type": "com.jiuxian.config.JiuxianProperties"
},
{
"name": "jiuxian.school",
"sourceType": "com.jiuxian.config.School",
"type": "com.jiuxian.config.School",
"sourceMethod": "getSchool()"
}
],
"properties": [
{
"name": "jiuxian.name",
"sourceType": "com.jiuxian.config.JiuxianProperties",
"type": "java.lang.String",
"deprecation": {
"level": "error",
"reason": "replacement nameCn.",
"replacement": "jiuxian.name-cn"
}
},
{
"name": "jiuxian.name-cn",
"sourceType": "com.jiuxian.config.JiuxianProperties",
"type": "java.lang.String",
"defaultValue": "jiuxian"
}
],
"hints": [
{
"name": "jiuxian.sex-enum",
"values": [
{
"value": "man",
"description": "man."
},
{
"value": "woman",
"description": "woman."
}
]
},
{
"name": "jiuxian.single",
"values": [
{
"value": true,
"description": "yes."
},
{
"value": false,
"description": "no."
}
]
}
]
}
複製程式碼
idea 提示:
(2) 如何廢棄某個欄位,可以用程式碼來註解
@Deprecated
private String name;
@Deprecated
public String getName() {
return getNameCn();
}
@DeprecatedConfigurationProperty(replacement = "jiuxian.name-cn", reason = "replacement nameCn")
public void setName(String name) {
setNameCn(name);
}
複製程式碼
七、更多詳細介紹請參閱官網
八、本文示例程式碼
【注】以上程式碼基於Springboot 2.0