目前,我正在为hunchentoot开发2个基于网络的工具 在开始hunchentoot之前,我想用let设置一些特殊变量,这样在hunchentoot运行时就会有值。
喜欢:
(let ((*db-path* "my-db-file"))
(start-hunchentoot))
但是,一旦处理程序开具发票,它们就不会再接合,并且 db-path 会回落到其全局状态(这是零)。
目前我通过在每个处理程序中编写let来解决这个问题 但是,我想要一个更通用的方法,这样我就可以在一个运行时中运行具有不同 db-path 的两个应用程序。
是否可以以某种方式设置 db-path ,以便它对一个hunchentoot实例有效而不是另一个实例?
Debian Jessie使用的环境是SBCL 1.2.4。
答案 0 :(得分:7)
在接受器中添加db-path
作为插槽可能是一个合适的选项。但是,您也可以为around
编写handle-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's documentation。
您观察到的行为是因为:
动态绑定是每个线程的本地,如in the manual所述:
特殊变量与多个线程的交互大多是人们所期望的,其行为与其他实现非常相似。
- 所有线程都可以看到全局特殊值;
- 绑定(例如使用LET)是线程的本地;
- 线程不从父线程继承动态绑定
如果你创建自己的线程,你可以构建一个闭包,根据需要绑定变量。您还可以依赖可移植的bordeaux-threads库,该库将一个绑定列表在一个线程内有效。