如何绑定动态变量?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何绑定动态变量?相关的知识,希望对你有一定的参考价值。

如何在compojure中绑定动态变量?请参阅下面的示例,这里request-id是为每个api请求生成的唯一uuid。我希望能够在后续的日志记录方法中访问此请求ID。我尝试使用绑定函数,但仍然无法访问some-page/some-method中的request-id。

handler.clj

(ns some_app.handler
  (:require
    [compojure.api.sweet :refer :all]
    [compojure.route :as route]
    [some_api.some_page :as some-page]))

(def ^:dynamic *request-id*
  nil)

(defn ^:private generate-request-id []
  (str (java.util.UUID/randomUUID)))

(def app
  (binding [*request-id* (generate-request-id)]
    (api
      (context "/api" [] (GET "/some-page" [] (some-page/some-method))))))

一些-page.clj

(ns some_app.some_page
(:require
        [clojure.tools.logging :as log]))

(def some-method []
  (log/info {:request-id *request-id*}))
答案

这里对绑定的调用是在错误的地方。处理请求时绑定应该有效,而不是在构建app / api时。

你想要一些中间件来做到这一点:

(defn with-request-id 
  [f]
  (fn [request]
    (binding [*request-id* (generate-request-id)]
      (f request)))

(def app
  (with-request-id
    (api ... ))

另见Ring Concepts

另一答案

在你的some_app.some_page命名空间中,你需要require声明*request-id*的命名空间。就像是:

(ns some_app.some_page
  (:require
    [clojure.tools.logging :as log]
    [some_app.handler :as hndlr))

然后你可以参考*request-id*像:

(def some-method []
  (log/info {:request-id hndlr/*request-id*}))
另一答案

动态绑定是一种很好的方法,随着时间的推移,它可以随着代码库的增长而不受欢迎地增长,至少与在请求中自己存储有关请求的数据相比。

环模型鼓励将关于请求的内容直接存储在请求中作为数据,而不是在元数据或环境中存储诸如绑定变量之类的东西。

(defn with-request-id 
  [f]
  (fn [request]
      (f (assoc request :request-id (generate-request-id)))

那么您不必担心线程绑定的保留位置或其他此类问题。

以上是关于如何绑定动态变量?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle - 如何使用动态绑定参数定义动态 SQL?

WPF 如何动态绑定static成员变量 并实现INOTIFYPROPERTYCHANGED方法

Oracle - 如何使用动态绑定参数定义动态SQL?

wpf checkbox 如何绑定变量

Kotlin Android Studio - setContenView - 绑定(片段)

动态 SQL 中绑定变量的限制