Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将ConfigurationProperties绑定到<;枚举、Pojo>;_Java_Spring Boot - Fatal编程技术网

Java 将ConfigurationProperties绑定到<;枚举、Pojo>;

Java 将ConfigurationProperties绑定到<;枚举、Pojo>;,java,spring-boot,Java,Spring Boot,说明 我正在尝试用我的组件类绑定以下配置- platform: service: config: guard: hostname: fancy-host1.kiki.com resources: - name: bark api-path: dog/alert/bark/{dog-id} - name: bite api-path: dog/alert/bite/{

说明 我正在尝试用我的组件类绑定以下配置-

platform:
  service:
    config:
      guard:
       hostname: fancy-host1.kiki.com
       resources:
         - name: bark
           api-path: dog/alert/bark/{dog-id}
         - name: bite
           api-path: dog/alert/bite/{dog-id}
           json-path: $..kill-mode
      play:
        hostname: fancy-host2.kiki.com
        resources:
         - name: lick
           api-path: dog/chill/lick/{dog-id}
           json-path: $..cute-mode
我的组件类看起来像这样-

@Component
@ConfigurationProperties(prefix = "platform.service")
public class DogConfig
{
    @Getter
    @Setter
    public class Resource
    {
        private String name;
        private String apiPath;
        private String jsonPath;
    }

    @Getter
    @Setter
    public class APIConfig
    {
        private String hostname;
        private List<Resource> resources = new ArrayList<>();
    }

    private Map<ServiceType, APIConfig> config = new LinkedHashMap<>();

    public Map<ServiceType, APIConfig> getConfig()
    {
        return config;
    }

    public void setConfig(Map<ServiceType, APIConfig> config)
    {
        this.config = config;
    }
}
@组件
@配置属性(前缀=“platform.service”)
公共类DogConfig
{
@吸气剂
@塞特
公共类资源
{
私有字符串名称;
私有字符串路径;
私有字符串jsonPath;
}
@吸气剂
@塞特
公共类APIConfig
{
私有字符串主机名;
private List resources=new ArrayList();
}
私有映射配置=新建LinkedHashMap();
公共映射getConfig()
{
返回配置;
}
公共无效设置配置(映射配置)
{
this.config=config;
}
}
在上面的代码中,ServiceType是一个具有值GUARD和PLAY的枚举

问题 虽然我的spring引导应用程序在初始化时没有抛出任何错误,但它没有将我的YAML绑定到DogConfig类。我不确定我到底错过了什么

我迄今为止的故障排除工作
我依赖于,将我的配置外部化。我知道@ConfigurationProperties是类型安全的,并且已经单独测试了枚举、映射和POJO的绑定。但是同时拥有这三个资源是我无法实现的。

请在资源和APIConfig的内部类中添加static 例如:

public static class Resource {
    private String name;
    private String apiPath;
    private String jsonPath;
}
您可以这样做:

  • 创建如下所示的POJO:

    @Getter
    @Setter
    @ConfigurationProperties("platform.service")
    public class DogProperties {
    
        private Map<String, APIConfig> config;
    
    }
    

  • 如果你看这个例子,secret是一个Map属性,你可以用一个带有密钥保护的Map进行解析,或者使用APIConfig进行游戏。

    编辑:

    您可以使用ConstructorBinding注释(请参见)将属性绑定到构造函数,如下所示,以使用以下方法将字符串键转换为枚举键:

    @组件
    @配置属性(前缀=“platform.service”)
    @构造绑定
    公共类DogConfig{
    DogConfig(地图配置){
    this.config=config.entrySet().stream().collect(
    汤姆(
    e->ServiceType.valueOf(e.getKey()),
    Map.Entry::getValue
    )
    );
    }
    ...
    
    或者,通过另外使用ObjectMapper将具有额外映射值类型的有线映射转换为具有pojo值类型的有线映射:

    @Component
    @ConfigurationProperties(prefix = "platform.service")
    @ConstructorBinding
    public class DogConfig {
    
        DogConfig(Map<ServiceType, Map<String,Object> > config) {
           this.config = config.entrySet().stream().collect(
                            Collectors.toMap(
                               Map.Entry::getKey,
                               e -> (new ObjectMapper()).convertValue(e.getValue(),APIConfig.class)
                            )
                    );
        }
    
    ...
    
    @组件
    @配置属性(前缀=“platform.service”)
    @构造绑定
    公共类DogConfig{
    DogConfig(地图配置){
    this.config=config.entrySet().stream().collect(
    汤姆(
    Map.Entry::getKey,
    e->(新的ObjectMapper()).convertValue(e.getValue(),apicConfig.class)
    )
    );
    }
    ...
    

    正如已经暗示的那样,在映射中同时使用Enum和Pojo似乎不起作用。您可能需要将两种可能的结构之一转换为所需的结构。

    将用于访问整个结构的主类: 平台配置容器

    import java.util.Map;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    @Data
    @AllArgsConstructor
    @ConfigurationProperties(prefix = "platform.service")
    @Component
    public class PlatformConfigContainer {
      private final Map<ConfigType, ServiceConfig> config;
    }
    
    ServiceConfig

    import java.util.List;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class ServiceConfig {
      private String hostname;
      private List<NamedApiPath> resources;
    }
    
    import java.util.List;
    导入lombok.allargsconstuctor;
    导入龙目数据;
    导入lombok.noargsconstuctor;
    @资料
    @诺尔格构装师
    @AllArgsConstructor
    公共类ServiceConfig{
    私有字符串主机名;
    私人名单资源;
    }
    
    namedapath

    import java.util.Optional;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class NamedApiPath {
    
      private String name;
    
      private String apiPath;
    
      private Optional<String> jsonPath = Optional.empty();
    }
    
    import java.util.Optional;
    导入lombok.allargsconstuctor;
    导入龙目数据;
    导入lombok.noargsconstuctor;
    @资料
    @AllArgsConstructor
    @诺尔格构装师
    公共类名称dappath{
    私有字符串名称;
    私有字符串路径;
    private Optional jsonPath=Optional.empty();
    }
    

    使用Spring Boot 2.3.7进行测试。发布版

    请您逐步分享解决方案,另外如何在代码中调用相同的函数以获得更好的想法这将有助于其他人理解其他人根据您的解决方案实现相同的功能,并且可能会以更具描述性的方式提供更好的帮助。完成。如果我理解正确,请提供f基本java和spring引导基础仍然缺失,因此交付:)
    public enum ConfigType {
      guard, play
    }
    
    import java.util.List;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class ServiceConfig {
      private String hostname;
      private List<NamedApiPath> resources;
    }
    
    import java.util.Optional;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class NamedApiPath {
    
      private String name;
    
      private String apiPath;
    
      private Optional<String> jsonPath = Optional.empty();
    }