How to define constraints of yml configuration items in Spring boot environment

  经常使用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;

    @Data
    public static class Download {
        /**
         * 数据抓取
         */
        private Fetch fetch;

        /**
         * 可供文件下载的资源文件目录
         */
        private String path;
    }

    @Data
    public 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;
            }
        }
    }

    @Data
    public 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 {

    @Bean
    public SimagouAppProperties getLabelAppProperties() {
        SimagouAppProperties properties = new SimagouAppProperties();
        properties.setDownload(getDownload());
        properties.setUpload(upload());
        return properties;
    }

    @Bean
    public SimagouAppProperties.Upload upload() {
        SimagouAppProperties.Upload upload = new SimagouAppProperties.Upload();
        return upload;
    }

    @Bean
    public SimagouAppProperties.Fetch getFetch() {
        SimagouAppProperties.Fetch fetch = new SimagouAppProperties.Fetch();
        return fetch;
    }

    @Bean
    public 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: 200
          max-records: 100000
          max-columns: 200
        path: ${user.home}/.app/label/download
      upload:
        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);

    @Autowired
    private 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!"
    }
}

  怎么样,是不是很简单呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qwfys200

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值