目前,我正在使用 hunchentoot 为我自己的需要开发 2 个基于 Web 的工具。
在开始 hunchentoot 之前,我想用 let 设置一些特殊变量,以便在 hunchentoot 运行时可以使用这些值。
像 :
(let ((*db-path* "my-db-file"))
(start-hunchentoot))
但是,一旦处理程序收到发票,它们就不会再出现在 let 中,并且 db-path 会回退到其全局状态(即 nil)。
目前我正在通过在每个处理程序中编写 let 来解决这个问题。
但是,我想要一种更通用的方法,以便能够在一个运行时运行具有不同 db-path 的两个应用程序。
是否可以以某种方式设置 db-path,使其对 hunchentoot 的一个实例有效,而对另一个实例无效?
使用的环境是 Debian Jessie 上的 SBCL 1.2.4。
最佳答案
绕法
添加 db-path
作为接受器中的插槽可能是一个合适的选择。但是,您也可以写一个 around
handle-request
的方法.假设 *my-acceptor*
是全局绑定(bind)的:
(defmethod hunchentoot:handle-request :around ((acceptor (eql *my-acceptor*)) request)
(let ((*db-path* "my-db-file"))
(call-next-method)))
当然,你不需要专门研究
EQL
,您可以改为定义自己的子类。与在类实例中存储配置变量相比,around 方法的优点是您保留了使用特殊变量的好处,即绑定(bind)在动态范围内的任何地方都是可见的。这是文档字符串的内容,在 Lispdoc 上可见, 说
handle-request
(强调我的):This function is called once the request has been read and a REQUEST object has been created. Its job is to actually handle the request, i.e. to return something to the client.
Might be a good place for around methods specialized for your subclass of ACCEPTOR which bind or rebind special variables which can then be accessed by your handlers.
我鼓励你阅读 Hunchentoot's documentation .
特殊变量和线程
您观察到的行为是因为:
The interaction of special variables with multiple threads is mostly as one would expect, with behaviour very similar to other implementations.
- global special values are visible across all threads;
- bindings (e.g. using LET) are local to the thread;
- threads do not inherit dynamic bindings from the parent thread
如果您创建自己的线程,则可以构建一个闭包,根据需要绑定(bind)变量。您还可以依靠可移植 bordeaux-threads库,它采用绑定(bind)列表在线程内有效。
关于common-lisp - hunchentoot 中的特殊变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40190532/