??经常使用Spring boot项目的小伙伴们可能会发现,当我们使用spring boot标准组件的配置项的时候,IDE无论是IDEA还是Eclipse都能够给出提示。那么,IDE是怎么知道Spring boot标准组件的配置项的元信息的呢,大家可能会说,IDE自动下载了Spring boot标准组件配置项的元信息,所以能给出提示了。那么,Spring boot标准组件配置项的元信息是以什么样的格式存放的,它放在什么地方呢?今天,我们就一起了解一下。
??根据Spring boot官方文档附件二配置元数据项的介绍,我们可以了解到配置元数据文件位于 META-INF/spring-configuration-metadata.json 下的 jars中,它们使用 JSON 格式,项目归类为“组”或“属性”,附加值提示归类为“提示”。
??接下来,我们创建一个用于演示的项目,项目结构如下:
lwk@harbin:~/Public/project/default/simagou$ tree
.
├── mvnw
├── mvnw.cmd
├── pom.xml
├── README.md
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── qwfys
│ │ │ └── app
│ │ │ └── simagou
│ │ │ ├── config
│ │ │ │ ├── SimagouAppConfig.java
│ │ │ │ ├── SimagouAppProperties.java
│ │ │ ├── controller
│ │ │ ├── SimagouApplication.java
│ │ │ │ ├── HelloController.java
│ │ │ ├── SimagouApplication.java
│ │ └── resources
│ │ ├── application.yml
│ │ └── META-INF
│ │ ├── additional-spring-configuration-metadata.json
lwk@harbin:~/Public/project/default/simagou$
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.8</version><relativePath/></parent><groupId>com.qwfys.app</groupId><artifactId>simagou</artifactId><version>0.0.1-SNAPSHOT</version><name>simagou</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
- SimagouAppProperties
package com.qwfys.app.simagou.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;@Data
@ConfigurationProperties(prefix = SimagouAppProperties.FILE_SERVICE_PREFIX, ignoreUnknownFields = true)
public class SimagouAppProperties {
public static final String FILE_SERVICE_PREFIX = "simagou.file.service";/*** 下载*/private Download download;/*** 上传*/private Upload upload;@Datapublic static class Download {
/*** 数据抓取*/private Fetch fetch;/*** 可供文件下载的资源文件目录*/private String path;}@Datapublic static class Fetch {
/*** 每次迭代数*/private int recordsOnce = 500;/*** 最大记录数,取值为0代表不做限制*/private int maxRecords = 0;/*** 最大列数,取值为0代表不做限制*/private int maxColumns = 0;/*** 感应数大小*/private ContainerType containerType = ContainerType.TINY;public enum ContainerType {
/*** 极小*/TINY(200, "TINY"),/*** 小*/SMELL(500, "SMELL"),/*** 中*/MIDDLE(1000, "MIDDLE"),/*** 大*/BIG(5000, "BIG"),/*** 极大*/GREAT(10000, "GREAT"),;int code;String label;private ContainerType(int code, String label) {
this.code = code;this.label = label;}public int getCode() {
return code;}public String getLabel() {
return label;}}}@Datapublic static class Upload {
/*** 标签系统可供文件上传的资源文件目录*/private String path;}
}
- LabelAppConfig
package com.qwfys.app.simagou.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class SimagouAppConfig {
@Beanpublic SimagouAppProperties getLabelAppProperties() {
SimagouAppProperties properties = new SimagouAppProperties();properties.setDownload(getDownload());properties.setUpload(upload());return properties;}@Beanpublic SimagouAppProperties.Upload upload() {
SimagouAppProperties.Upload upload = new SimagouAppProperties.Upload();return upload;}@Beanpublic SimagouAppProperties.Fetch getFetch() {
SimagouAppProperties.Fetch fetch = new SimagouAppProperties.Fetch();return fetch;}@Beanpublic SimagouAppProperties.Download getDownload() {
SimagouAppProperties.Download download = new SimagouAppProperties.Download();download.setFetch(getFetch());return download;}
}
??这个时候,我们进入项目根目录,执行打包命令:
mvn clean package -Dmaven.test.skip=true
??我们发现在目录target/classes/META-INF/中生成了配置元数据文件spring-configuration-metadata.json。观察后发现,生成的文件中,部分属性项没有默认值提示,属性可选项列表也没有。根据官网文档,缺失的这些内容需要我们手动添加到文件src/main/resources/META-INF/additional-spring-configuration-metadata.json中。接下来,我们就手动补充一些属性项的相关配置信息吧。
- additional-spring-configuration-metadata.json
src/main/resources/META-INF/additional-spring-configuration-metadata.json
{
"properties": [{
"name": "simagou.file.service.download.fetch.records-once"},{
"name": "simagou.file.service.download.fetch.container-type","defaultValue": "TINY"}],"hints": [{
"name": "simagou.file.service.download.fetch.records-once","type": "java.lang.Integer","values": [{
"value": 200},{
"value": 500},{
"value": 1000}]},{
"name": "simagou.file.service.download.fetch.container-type","values": [{
"value": "TINY","description": "极小"},{
"value": "SMELL","description": "小"},{
"value": "MIDDLE","description": "中"},{
"value": "BIG","description": "大"},{
"value": "GREAT","description": "极大"}]}]
}
??接下来,我们继续用maven命令打包,命令同上,即:
mvn clean package -Dmaven.test.skip=true
??这个时候,我们接着进入目录target/classes/META-INF/打开文件spring-configuration-metadata.json就会看到上面我们手动添加的属性项已经补充到该文件中了,内容如下所示:
- spring-configuration-metadata.json
target/classes/META-INF/spring-configuration-metadata.json
{
"groups": [{
"name": "simagou.file.service","type": "com.qwfys.app.simagou.config.SimagouAppProperties","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties"},{
"name": "simagou.file.service.download","type": "com.qwfys.app.simagou.config.SimagouAppProperties$Download","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties"},{
"name": "simagou.file.service.download.fetch","type": "com.qwfys.app.simagou.config.SimagouAppProperties$Fetch","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties$Download"},{
"name": "simagou.file.service.upload","type": "com.qwfys.app.simagou.config.SimagouAppProperties$Upload","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties"}],"properties": [{
"name": "simagou.file.service.download.fetch.container-type","type": "com.qwfys.app.simagou.config.SimagouAppProperties$Fetch$ContainerType","description": "感应数大小","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties$Fetch","defaultValue": "TINY"},{
"name": "simagou.file.service.download.fetch.max-columns","type": "java.lang.Integer","description": "最大列数,取值为0代表不做限制","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties$Fetch","defaultValue": 0},{
"name": "simagou.file.service.download.fetch.max-records","type": "java.lang.Integer","description": "最大记录数,取值为0代表不做限制","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties$Fetch","defaultValue": 0},{
"name": "simagou.file.service.download.fetch.records-once","type": "java.lang.Integer","description": "每次迭代数","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties$Fetch","defaultValue": 500},{
"name": "simagou.file.service.download.path","type": "java.lang.String","description": "可供文件下载的资源文件目录","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties$Download"},{
"name": "simagou.file.service.upload.path","type": "java.lang.String","description": "标签系统可供文件上传的资源文件目录","sourceType": "com.qwfys.app.simagou.config.SimagouAppProperties$Upload"}],"hints": [{
"name": "simagou.file.service.download.fetch.container-type","values": [{
"value": "TINY","description": "极小"},{
"value": "SMELL","description": "小"},{
"value": "MIDDLE","description": "中"},{
"value": "BIG","description": "大"},{
"value": "GREAT","description": "极大"}]},{
"name": "simagou.file.service.download.fetch.records-once","values": [{
"value": 200},{
"value": 500},{
"value": 1000}]}]
}
??这个时候IDE根据项目类路径目录就会探测到刚刚生成的文件spring-configuration-metadata.json,进而就可以在我们编辑application.properties或者application.yml的时候给出提示。
- application.yml
simagou:file:service:download:fetch:records-once: 200max-records: 100000max-columns: 200path: ${
user.home}/.app/label/downloadupload:path: ${
user.home}/.app/label/upload
- HelloController
package com.qwfys.app.simagou.controller;import com.qwfys.app.simagou.config.LabelAppProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.RestController;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/hello")
public class HelloController {
private static final Logger logger = LoggerFactory.getLogger(HelloController.class);@Autowiredprivate LabelAppProperties labelAppProperties;@GetMapping("/index")public String sayHello() {
final LabelAppProperties.Fetch fetch = labelAppProperties.getDownload().getFetch();final int maxRecords = fetch.getMaxRecords();logger.info("maxRecords:{}",maxRecords)return "Hello,Welcome to Hangzhou!"}
}
??怎么样,是不是很简单呢?