Clojure 2024 年调查 中分享您的想法!

欢迎!请参阅 关于 页面以了解该平台的一些更多信息。

0
Clojure

描述

大家好!我在解析一个 Spring Boot 配置文件。值并不重要

server.port: 8000
spring.application.name: some application
spring.datasource.driver-class-name: org.whatever.Driver
spring.datasource.password: some_password
spring.datasource.platform: postgres
spring.datasource.url: jdbc:postgresql:does_not_matter
spring.datasource.username: some_username
spring.jpa.database: POSTGRESQL
some.service.endpoint: http://whatever
some.other.service.endpoint: http://something_else

我正在尝试提取 / 组合该文件的各个部分,并在希望寻找建议 / 习惯的做法。我在尝试遵循“数据 > 函数 > 宏”习惯用法以及“一个数据结构 的 100 个更好的函数”。

具体来说,我希望能解析 / 组合网络端点,然后是数据库属性,以便使用一些业务逻辑进行验证。

我已经使用 java.util.Properties 解析了该文件,所以这在此处不感兴趣。上述文件已被转换为映射。

解决方案 1

为每个“分组”创建一个单独的函数,解析我想要的,并返回一个新的映射,其中仅包含我想要的数据。

  • defn get-endpoints [props] 返回

`

{
    "some.service.endpoint" "http://whatever",
    "some.other.service.endpoint" "http://something_else"
}

`

  • defn get-database-properties [props] 等。

解决方案 2

添加额外的键到原始映射,以分组我想要的内容。

defn parse-groupings [props] 返回

    {
        "server.port" "8000",
        "spring.application.name" "some application",
        "spring.datasource.driver-class-name" "org.whatever.Driver",
        ;; the rest of the original properties
       :groupings {
            :web-endpoints {
               ;; web endpoints go here
           },
           :database-props {
             ;; database properties get embedded here
           }

    }

解决方案 ???

当然还有很多其他的解决方案,但我想知道社区的建议。

谢谢!

1 答案

0

您可以对简单的

(doto (Properties.)
  (.load (io/reader "props.properties")))

它将产生一个像这样的映射

{...
  "server.port" "8080"
 ...}

并作为字符串访问这些值 (get props-map "server.port")

我更喜欢这种方法,因为它更容易用 git grep 搜索值。

对于更“习惯”的解决方案,您可以这样做:

(defn parse-props
  [in & {:keys [handlers default-handler]
         :or   {default-handler identity}}]
  (into {}
    (map (fn [[k v]]
           (let [[kw-name & ns-parts] (reverse (string/split k #"\."))
                 kw (keyword (string/join "." ns-parts)
                      kw-name)
                 f (get handlers kw default-handler)]
             [kw (f v)])))
    (doto (Properties.)
      (.load (io/reader in)))))
(parse-props "props.properties"
  :handlers {:server/port #(Long/parseLong %)})

它将产生一个像这样的映射

{....
 :server/port 8080
 ...}
谢谢,@Enzzo,但我对把地图分组,比如在OP中的`get-endpoints`的建议更感兴趣。
现在重新阅读问题,我发现它更像是选择数据的功能,而不是与props相关的东西。对不起给出了错误的答案。

关于“get-endpoints”,从代码的角度来看,我可能会写(defn find-endpoints [config] (into {} (filter #(string/ends-with? % ".endpoint")) config))这样的东西。
如果需要,我们可以将其关联回配置映射中。
我认为不需要花太多时间在“设计”这个函数上。它是一个简单的函数,可能只会被调用10次左右。它可能不会随着时间而改变。

最后关于配置的评论,我会在app.config.endpoint-props=..service1.endpoint,...service2.endpoint中创建显式的,以避免命名约定。
...