6

目前,我正在使用 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。

4

1 回答 1

7

绕法

在接受器中添加db-path一个插槽可能是一个合适的选择。但是,您也可以aroundhandle-request. 假设*my-acceptor*是全局绑定的:

(defmethod hunchentoot:handle-request :around ((acceptor (eql *my-acceptor*)) request)
  (let ((*db-path* "my-db-file"))
    (call-next-method)))

当然,您不需要专门研究EQL,您可以定义自己的子类。与在类实例中存储配置变量相比,around 方法的优势在于您保留了使用特殊变量的好处,即绑定在动态范围内的任何地方都是可见的。这是Lispdoc上可见的文档字符串所说的handle-request(强调我的):

一旦读取请求并创建了 REQUEST 对象,就会调用此函数。它的工作是实际处理请求,即向客户端返回一些东西。

可能是为您的 ACCEPTOR 子类专门的方法的好地方,这些方法绑定或重新绑定特殊变量,然后您的处理程序可以访问这些变量。

我鼓励您阅读Hunchentoot 的文档

特殊变量和线程

您观察到的行为是因为:

  • 服务器正在另一个线程中运行。
  • 动态绑定对于每个线程都是本地的,如手册中所述

    特殊变量与多个线程的交互大多如预期的那样,其行为与其他实现非常相似。

    • 全局特殊值在所有线程中可见;
    • 绑定(例如使用 LET)是线程本地的;
    • 线程不从父线程继承动态绑定

如果您创建自己的线程,则可以构建一个闭包,根据需要绑定变量。您还可以依赖可移植的bordeaux-threads库,该库采用绑定列表在线程内有效。

于 2016-10-22T11:10:03.587 回答