您可能想查看 Ring 的 Jetty 适配器,以获取 Clojure 中 servlet 实现的示例。源代码可在此处获得(链接到 1.1 版本的源代码)。特别是,在该命名空间中定义的第一个函数proxy-handler
返回一个基于 Jetty 提供的抽象类的处理程序。
如果您选择实现类似的方法(基于提供一些现成方法实现的 Java 类的 servlet),则需要使用proxy
; 如果您只需要实现接口(没有子类化),那么您可能会想要reify
。宏是否有用取决于实现的哪些部分将被修复;Ring 的 Jetty 适配器不会从使用宏中受益,但您可以(例如,如果您希望将类扩展/接口实现为参数,正如问题所表明的那样)。
在任何情况下,您选择实现的任何功能都需要成为接口或协议的一部分。因此,实现javax.servlet.Servlet
加上一个额外的操作foo
可能如下所示:
(import (javax.servlet Servlet ServletRequest ServletResponse))
(defprotocol PFoo
(foo [this x y z]))
(reify
Servlet
(service [this ^ServletRequest req ^ServletResponse res]
...)
;; other Servlet methods here...
PFoo
(foo [this x y z]
...))
然后,您可以将其包装在宏中以提供任何所需的语法糖。请注意,reify
它实际上并不关心您在其主体内交错接口/协议名称和方法定义的方式,因此您可以让您的宏发出
(reify
Servlet PFoo ... ; other interfaces & protocols
(service [...] ...)
(foo [...] ...)
;; other methods
)
如果这样更方便。
一个宏的草图,采用一个 servlet 接口的名称来实现(可能是扩展javax.servlet.Servlet
)并使用一些额外的方法注入一个协议:
(defprotocol PFancyServlet
(do-get [this ...])
(do-post [this ...]))
(defmacro servlet [servlet-iface & meths]
`(reify ~servlet-iface PFancyServlet
~@meths))
meths
将需要包括do-get
和do-post
以及servlet-iface
方法;您可以添加一些参数验证以确保是这种情况。一个示例调用:
(servlet SomeServletInterface
(service [this ...] ...)
;; ...
(do-get [this ...] ...)
(do-post [this ...] ...))