我看到 Pavel 的关于使用 CL 和RESTAS作为框架编写 Web 应用程序的教程。虽然简单的例子有效。我无法运行第 4 章中的博客示例。Hello, World!
使用(restas:debug-mode-on)我最终得到以下回溯:
invalid number of arguments: 0
[Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]
Restarts:
0: [ABORT] abort thread (#<THREAD "hunchentoot-worker-127.0.0.1:59876" RUNNING {1009975FD3}>)
Backtrace:
0: (BLOGDEMO::HTML-FRAME) [tl,external]
1: (RESTAS::ROUTE-RENDER-METHOD #<RESTAS:ROUTE {100A16FE53}>)
2: ((:METHOD RESTAS:PROCESS-ROUTE (RESTAS:ROUTE T)) #<RESTAS:ROUTE {100A16FE53}> NIL) [fast-method]
3: ((FLET CALL-NEXT-METHOD :IN "C:/Users/martin_b/portacle/quicklisp/dists/quicklisp/software/restas-20170124-git/src/route.lisp"))
4: ((:METHOD RESTAS:PROCESS-ROUTE :AROUND (ROUTES:BASE-ROUTE T)) #<RESTAS:ROUTE {100A16FE53}> NIL) [fast-method]
5: (RESTAS::RESTAS-DISPATCH-REQUEST #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<RESTAS::RESTAS-REQUEST {1003E5B383}>)
6: ((:METHOD HUNCHENTOOT:ACCEPTOR-DISPATCH-REQUEST (RESTAS:RESTAS-ACCEPTOR T)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
7: ((:METHOD HUNCHENTOOT:HANDLE-REQUEST (HUNCHENTOOT:ACCEPTOR HUNCHENTOOT:REQUEST)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
8: ((:METHOD HUNCHENTOOT:PROCESS-REQUEST (T)) #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
9: ((FLET CALL-NEXT-METHOD :IN "C:/Users/martin_b/portacle/quicklisp/dists/quicklisp/software/restas-20170124-git/src/hunchentoot.lisp"))
10: ((:METHOD HUNCHENTOOT:PROCESS-REQUEST :AROUND (RESTAS::RESTAS-REQUEST)) #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
11: ((LAMBDA NIL :IN HUNCHENTOOT:PROCESS-CONNECTION))
12: (HUNCHENTOOT::DO-WITH-ACCEPTOR-REQUEST-COUNT-INCREMENTED #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<CLOSURE (LAMBDA NIL :IN HUNCHENTOOT:PROCESS-CONNECTION) {1003C3439B}>)
13: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION (HUNCHENTOOT:ACCEPTOR T)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<USOCKET:STREAM-USOCKET {1009971333}>) [fast-method]
14: ((FLET CALL-NEXT-METHOD :IN "C:/Users/martin_b/portacle/quicklisp/dists/quicklisp/software/hunchentoot-1.2.35/acceptor.lisp"))
15: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION :AROUND (HUNCHENTOOT:ACCEPTOR T)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<USOCKET:STREAM-USOCKET {1009971333}>) [fast-method]
16: ((FLET HUNCHENTOOT::PROCESS-CONNECTION% :IN HUNCHENTOOT::HANDLE-INCOMING-CONNECTION%) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<USOCKET:STREAM-USOCKET {1009971333}>)
17: ((:METHOD HUNCHENTOOT::HANDLE-INCOMING-CONNECTION% (HUNCHENTOOT:ONE-THREAD-PER-CONNECTION-TASKMASTER T)) #<HUNCHENTOOT:ONE-THREAD-PER-CONNECTION-TASKMASTER {10081F24C3}> #<USOCKET:STREAM-USOCKET {1009..
18: ((LAMBDA NIL :IN HUNCHENTOOT:CREATE-REQUEST-HANDLER-THREAD))
19: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS))
20: ((FLET #:WITHOUT-INTERRUPTS-BODY-1169 :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
21: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
22: ((FLET #:WITHOUT-INTERRUPTS-BODY-359 :IN SB-THREAD::CALL-WITH-MUTEX))
23: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE) {6DAFB4B}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THREAD "..
24: (SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE #<SB-THREAD:THREAD "hunchentoot-worker-127.0.0.1:59876" RUNNING {1009975FD3}> NIL #<CLOSURE (LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS) {..
25: ("foreign function: #x42BEFC")
26: ("foreign function: #x4038C1")
27: ("foreign function: #x447080")
Run Code Online (Sandbox Code Playgroud)
显然,函数期望的参数数量html-frame和调用它的参数数量之间存在问题render-method之间存在问题。我检查了源代码和 RESTAS 文档(似乎有点过时),但不明白要更改什么。
有人用RESTAS吗?还有其他最新的现实生活例子可以学习吗?我对 Cliki 的印象是,周围有几个网络框架,但我发现很难看出哪些是实际使用和维护的。
我通过改回他的来解决这个问题:
(defun start-blogdemo (&optional (port 8080))
(start '#:blogdemo :port port :render-method 'html-frame))
Run Code Online (Sandbox Code Playgroud)
到:
(defun start-blogdemo (&optional (port 8080))
(start '#:blogdemo :port port))
Run Code Online (Sandbox Code Playgroud)
在util.lisp。
然后你需要让你的每条路线都blogdemo.lisp不像:
(define-route home ("")
(list :title "Blogdemo"
:body (mapcar #'render-post *posts*)))
Run Code Online (Sandbox Code Playgroud)
但相反,像:
(define-route home ("")
(html-frame
(list :title "Blogdemo"
:body (mapcar #'render-post *posts*))))
Run Code Online (Sandbox Code Playgroud)
这个解决方案的起源是我并不完全理解他所做的抽象的正确性(并且在 p37 上争论了很多,他也在此处讨论了),所以我颠倒了它并且它起作用了。
另请注意,路由add应如下所示(表单:requirement需要位于 html-frame 之前,后者是最后一个表单,因此是返回值)。
(define-route add ("add")
(:requirement #'logged-on-p)
(html-frame
(list :title "Add a blog post"
:body (add-post-form))))
Run Code Online (Sandbox Code Playgroud)
同样,:sift-variables 表单也应该排在author&post路线的前面,就像 一样:requirement。那么整个应用程序应该适合您。