当前位置: 首页 > 知识库问答 >
问题:

如何将复杂的YAML解析成Java对象层次结构(spring boot配置)

席弘图
2023-03-14

我需要定义服务连接属性,这些属性将用于配置用于对spring boot服务进行RESTendpoint调用的resttemplate

注意:将来可能会涉及到服务发现机制,但我被指示暂时不要使用该方法。

服务连接属性:

  • 连接方案-HTTP/HTTPS
  • 主机名
  • 主机端口
  • 连接超时
  • 请求超时
  • 套接字超时
  • 默认保持活动状态
  • 每路由默认最大连接数
  • 最大连接总数

可能的配置(YAML):

services-config:
  global:
    scheme: http|https
    connectionTimeout: <timeout ms>
    requestTimeout: <timeout ms>
    socketTimeout: <timeout ms>
    defaultKeepAlive: <timeout ms>
    defaultMaxConnPerRoute: <count>
    maxTotalConnections: <count>
  services:
    - id: <ID>          [?]
      name: <name>      [?]
      host: localhost|<host>
      port: <port>
    - id: <ID>          [?]
      name: <name>      [?]
      host: localhost|<host>
      port: <port>
    ...

目的是将这些信息放入application.yml文件中,以便在spring应用程序中访问这些信息。

有没有办法将这些信息以YAML格式拉到Java对象层次结构中,如下所示:

class : ServicesConfig
  global : GlobalConnectionProperties
  services : map<String, ServiceConnectionProperties>

class : GlobalConnectionProperties
  scheme : String (maybe enum instead)
  connectionTimeout : int
  requestTimeout : int
  socketTimeout : int
  defaultKeepAlive : int
  defaultMaxConnPerRoute : int
  maxTotalConnections : int

class : ServiceConnectionProperties
  id : String
  name : String
  host : String
  port : int

更新:

尝试了以下操作并取得了部分成功:

ServiceConfiguration.java

@Configuration
public class ServiceConfiguration {

  private ServicesConfig servicesConfig;

  @Autowired
  public ServiceConfiguration(ServicesConfig servicesConfig) {
    this.servicesConfig = servicesConfig;
    System.out.println(servicesConfig);
  }

}

servicesConfig.java:

@ConfigurationProperties(value = "services-config")
@EnableConfigurationProperties(
    value = {GlobalConnectionProperties.class, ServiceConnectionProperties.class})
public class ServicesConfig {

  private GlobalConnectionProperties               globalProps;
  private Map<String, ServiceConnectionProperties> services;

  public GlobalConnectionProperties getGlobalProps() {
    return globalProps;
  }

  public void setGlobalProps(GlobalConnectionProperties globalProps) {
    this.globalProps = globalProps;
  }

  public Map<String, ServiceConnectionProperties> getServices() {
    return services;
  }

  public void setServices(Map<String, ServiceConnectionProperties> services) {
    this.services = services;
  }

  @Override
  public String toString() {
    return "ServicesConfig [globalProps=" + globalProps + ", services=" + services + "]";
  }

}

application.yml:

services-config:
  global:
    scheme: http
    connectionTimeout: 30000
    requestTimeout: 30000
    socketTimeout: 60000
    defaultKeepAlive: 20000
    defaultMaxConnPerRoute: 10
    maxTotalConnections: 200
  services:
    - id: foo
      name: foo service
      host: 192.168.56.101
      port: 8090
    - id: bar
      name: bar service
      host: 192.168.56.102
      port: 9010

省略了GlobalConnectionProperties和ServiceConnectionProperties类,因为它们只包含属性、getter/setter方法和toString()。

当我运行服务时,控制台上会出现以下内容:

ServicesConfig [globalProps=null, services={0=ServiceConnectionProperties [id=foo, name=foo service, host=192.168.56.101, port=8090], 1=ServiceConnectionProperties [id=bar, name=bar service, host=192.168.56.102, port=9010]}]

我实际上很惊讶列表项被解析并插入到映射中。我希望“id”是关键字,而不是默认的整数。奇怪的是,“全局”属性并没有进入地图。

要读取全局对象项,我需要更正什么?

有没有一种方法通过项目“id”属性来关键映射条目?

共有1个答案

笪煌
2023-03-14

要读取全局对象项,我需要更正什么?

属性的绑定遵循Java Bean约定,因此在servicesconfig中,您需要将字段和getters/setter从globalprops重命名为global

https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-typesafe-configuration-properties如注释中链接的更多信息。

有没有一种方法通过项目“id”属性来关键映射条目?

对于映射条目,yaml语法不正确。请参阅https://bitbucket.org/asomov/snakeyaml/wiki/documentation#markdown-header-type-safe-collections中使用:的语法。你的地图

services:
  ? foo
  : { id: foo,
      name: foo service,
      host: 192.168.56.101,
      port: 8090 }
  ? bar
  : { id: bar,
      name: bar service,
      host: 192.168.56.102,
      port: 9010}
 类似资料:
  • 零售商店的正确模式是什么?公司从商店销售产品。 这似乎违反了我对OOP所知的全部知识。通过层次结构向下传递数据的方法--在对象之间复制参数?我错过了什么?

  • 问题内容: 我在 .NET for WinRT(C#)中 ,我想将JSON字符串反序列化为,然后将字典值稍后转换为实际类型。JSON字符串可以包含对象层次结构,我也希望在其中包含子对象。 这是应该能够处理的示例JSON: 我尝试使用 DataContractJsonSerializer 这样做: 实际上,这对于第一个级别是可行的,但是 “父母” 只是一个不能强制转换为的对象: 然后,我尝试使用 J

  • 我在我的应用程序中使用MVVM模式。我有以下(简化版)VM类: 因此,一个Module2601_VM包含几个属性,以及Module2610_VM和ComPort_VM对象的列表。 我有一个MainModule_VM类中Module2601_VM对象的列表。 我想将这个Module2601集合及其子项绑定到树状视图中,并使用以下层次结构: 网关: 网关#0 COM#1 我的问题是,我的层次结构正常,

  • 问题内容: 在“深度”对象层次结构中使用Builder模式的最佳实践是什么?详细地说,我探讨了将Joshua Bloch提出的Builder模式应用于我的XML绑定代码的想法(我使用的是SimpleXML,但是这个问题将适用于任何情况)。我的对象层次结构深达4个级别,具有不同程度的复杂性。我的意思是,在某些级别上,我的对象只有几个属性,而在其他级别上,我最多可以有10个属性。 因此,请考虑以下假设

  • 在Spring-boot应用程序中使用yaml(带有snakeyaml依赖关系1.16),我试图基于application.yml文件创建。我想创建一个像下面的json这样的数据结构,它是一个包含字符串键和数组值的映射。 我已经为我的yaml尝试了以下方法 尝试二 尝试三 如果我将集合更改为一个ArrayList(或List接口),这就可以了,但这不是我想要的。更改为此 但need也不能用于Set

  • 问题内容: 如何将YAML文件解析/读入Python对象? 例如,此YAML: 对于此Python类: 我正在使用PyYAML。 问题答案: 如果您的YAML文件如下所示: 并且您已经这样安装: Python代码如下所示: 变量现在包含带有树数据的字典。如果使用PrettyPrint打印,则会得到类似以下内容的信息: 因此,现在我们已经了解了如何将数据获取到我们的Python程序中。保存数据同样简