SpringBoot 自定义配置项的玩法:配置文件提示与整合其他项目

415 阅读3分钟

在实际开发中,我们可能需要将一些键值对、属性值抽取出来,写入到配置文件中,方便维护代码。

本文将教会你如何在 Spring Boot 写出合适的配置类对应配置文件中的属性,以及在编写配置文件时,如何让配置文件中的属性具有相应的提示

🚀 引入依赖

为了实现上面所说的功能,我们至少需要两个依赖:

  • lombok 可以让代码更简洁,不必编写 getter / setter
  • spring-boot-configuration-processor 在编译配置类后,可以在配置文件中产生相应的提示
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

🚀 编写配置类

假设现在要引入一个视频点播系统,需要一些配置,例如应用标识、访问密钥等等信息,我们可以编写一个配置类来和配置项一一对应。

首先编写配置属性类:

@ConfigurationProperties(prefix = "vod")// 配置项前缀,类中的属性就是具体的配置项,例如:vod.appId = xxx
@Component	// 标志为组件,可以在应用上下文中获取到这个配置项
@Data
public class VodProperties {

    /**
     * 应用标识
     */
    private String appId;

    /**
     * 凭证key
     */
    private String accessKey;

    /**
     * 凭证密钥
     */
    private String accessSecret;

    /**
     * 签名凭证
     */
    private String signToken;

    @ConfigurationProperties("vod.store")// 层级配置项,例如 vod.store.type = xxx
    @Data
    public static class StoreProperty {

        /**
         * 存储类型,file 本地磁盘和 cloud 远程云端,默认 cloud
         */
        private String type = "cloud";

        /**
         * 存储类型为 file 时配置
         */
        private String url;

        /**
         * 云端 ip
         */
        private String host;

        /**
         * 云端端口
         */
        private String port;
    }

}

随后编写配置类,使用这些配置信息,如果需要用到第三方包的类,还可以使用配置类将其注册到 Spring 容器中:

@Configuration		// 配置类
@ConditionalOnClass(VodClient.class)	// 当存在该类的时候装载
@EnableConfigurationProperties({VodProperties.class, VodProperties.StoreProperty.class})// 配置类使用到的属性
@RequiredArgsConstructor
public class VodConfiguration {

    private final VodProperties vodProperties;
    private final VodProperties.StoreProperty storeProperty;

    @Bean	// 将第三方包的对象注册到容器中
    @ConditionalOnMissingBean	// 当不存在这个 Bean 时执行该方法
    public VodClient vodClient() {
        String appId = vodProperties.getAppId();
        String accessKey = vodProperties.getAccessKey();
        String accessSecret = vodProperties.getAccessSecret();
        String signToken = vodProperties.getSignToken();

        System.out.println("存储配置:" + storeProperty);

        return new VodClient(appId, accessKey, accessSecret, signToken);
    }
}

编写完毕后,在 IDEA 中点击 Ctrl+F9 编译代码,编译完成后查看 /target/classes/META-INF/spring-configuration-metadata.json 文件,可以看到如下信息,这些就是我们编写配置文件时能够提示的关键:

{
  "groups": [
    {
      "name": "vod",
      "type": "com.study.propertydemo.config.VodProperties",
      "sourceType": "com.study.propertydemo.config.VodProperties"
    },
    {
      "name": "vod.store",
      "type": "com.study.propertydemo.config.VodProperties$StoreProperty",
      "sourceType": "com.study.propertydemo.config.VodProperties$StoreProperty"
    }
  ],
  "properties": [
    {
      "name": "vod.access-key",
      "type": "java.lang.String",
      "description": "凭证key",
      "sourceType": "com.study.propertydemo.config.VodProperties"
    },
    {
      "name": "vod.access-secret",
      "type": "java.lang.String",
      "description": "凭证密钥",
      "sourceType": "com.study.propertydemo.config.VodProperties"
    },
    {
      "name": "vod.app-id",
      "type": "java.lang.String",
      "description": "应用标识",
      "sourceType": "com.study.propertydemo.config.VodProperties"
    },
    {
      "name": "vod.sign-token",
      "type": "java.lang.String",
      "description": "签名凭证",
      "sourceType": "com.study.propertydemo.config.VodProperties"
    },
    {
      "name": "vod.store.host",
      "type": "java.lang.String",
      "description": "云端 ip",
      "sourceType": "com.study.propertydemo.config.VodProperties$StoreProperty"
    },
    {
      "name": "vod.store.port",
      "type": "java.lang.String",
      "description": "云端端口",
      "sourceType": "com.study.propertydemo.config.VodProperties$StoreProperty"
    },
    {
      "name": "vod.store.type",
      "type": "java.lang.String",
      "description": "存储类型,file 本地磁盘和 cloud 远程云端,默认 cloud",
      "sourceType": "com.study.propertydemo.config.VodProperties$StoreProperty"
    },
    {
      "name": "vod.store.url",
      "type": "java.lang.String",
      "description": "存储类型为 file 时配置",
      "sourceType": "com.study.propertydemo.config.VodProperties$StoreProperty"
    }
  ],
  "hints": []
}

🚀 编写配置文件

现在编写配置文件,就能够看到自己自定义的配置项展示出提示了:

image-20230301165400126.png

🚀 运行查看效果

启动 SpringBoot 程序,查看效果,main 方法代码如下:

@SpringBootApplication
public class PropertyDemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(PropertyDemoApplication.class, args);
        VodClient vodClient = (VodClient) context.getBean("vodClient");
        System.out.println(vodClient);
    }

}

启动后的打印信息:


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.9)

2023-03-01 16:55:14.917  INFO 28040 --- [           main] c.s.p.PropertyDemoApplication            : Starting PropertyDemoApplication using Java 1.8.0_281 on 2210NB8448 with PID 28040 (D:\project\property-demo\target\classes started by admin in D:\project\property-demo)
2023-03-01 16:55:14.919  INFO 28040 --- [           main] c.s.p.PropertyDemoApplication            : No active profile set, falling back to 1 default profile: "default"
存储配置:VodProperties.StoreProperty(type=file, url=test, host=null, port=null)
2023-03-01 16:55:15.405  INFO 28040 --- [           main] c.s.p.PropertyDemoApplication            : Started PropertyDemoApplication in 0.855 seconds (JVM running for 1.583)
VodClient(appId=appId, accessKey=123456, accessSecret=abcdef, signToken=a1b2c3)

可以看到配置信息都能够在应用中正常工作。