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个函数"。

具体来说,我希望建立网络端点和数据库属性的分隔,以便使用一些业务逻辑进行验证。

我已经使用了 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,以避免命名约定。
...