2024 Clojure 状况调查 中分享您的观点!

欢迎!请参阅 关于 页面以了解更多关于如何使用本平台的信息。

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 个更好函数”。

具体来说,我正在查看如何解析/分组 Web 端点和数据库属性,以便使用某些业务逻辑进行验证。

我已经使用 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")))

将结果映射成 such

{...
  "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 %)})

将结果映射成 such

{....
 :server/port 8080
 ...}
谢谢,@Enzzo,但我更想知道有关如何对地图进行分组的建议,如原始帖子中的`get-endpoints`。
重新阅读问题后,我发现这个问题更像是关于选择数据的函数,而不是与props有关的内容。对不起给了错误的答案。

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

最后,从配置角度来看,我会创建一个显式的app.config.endpoint-props=..service1.endpoint,...service2.endpoint,以避免命名约定。
...