很多人喜欢Rails这种“All in One"的方式, 不过个人更喜欢搭积木的方式。每个小系统专心做好自己的事, 然后大家合作产生具有更强大功能的系统。 从网上收集了一些样本代码, 用SBCL试了下, 感觉不错。

>(ql:quickload "quickproject")

>(quickproject:make-project  "/media/E/RnD/clisp/web/" :depends-on '(hunchentoot cl-who cl-json parenacript css-lite elephant))

web项目的架子就搭好了:

%ls
README.txt  web.db  package.lisp  web.asd  web.lisp

%cat web.asd

(asdf:defsystem :web
  :serial t
  :depends-on (:hunchentoot
               :cl-who
               :cl-json
               :css-lite
               :parenscript
               :elephant)
  :components ((:file "package")
               (:file "web")))

其中各组件的功能,网上一查就知。简单说一下:

cl-who用于产生XHTML;  parenscript用于产生客户端JavaScript;  elephant用于操作数据库。

%cat package.lisp

(defpackage :web
  (:use :cl :cl-who :hunchentoot :parenscript :elephant)
  (:import-from :css-lite :css)
  (:import-from :json :encode-json-to-string))

%cat web.lisp
(in-package #:web)

;;; "web" goes here. Hacks and glory await!

;; 启动WEB服务器
(setf  *web-server*  (start  (make-instance 'hunchentoot:acceptor :port 8000)))

;; 输出所有静态内容
(push (create-static-file-dispatcher-and-handler "/GameVoter.png" "statics/imgs/GameVoter.png")  *dispatch-table*)
(push (create-static-file-dispatcher-and-handler "/site.css" "statics/css/site.css")*dispatch-table*)

;; 启动Elephant
(setf *store* (open-store '(:clsql  (:sqlite3  "/media/E/RnD/clisp/web/web.db"))))

;; 将每一个游戏表示为Elephant持久类的一个实例
(defpclass persistent-game ()
   ((name :reader name :initarg :name :index t)
    (votes :accessor votes :initarg :votes :initform 0 :index t)))

(defmethod vote-for (user-selected-game)
    (incf (votes user-selected-game)))

(defun game-from-name (name)
  (get-instance-by-value 'persistent-game 'name name))

(defun game-stored? (game-name)
  (game-from-name game-name))

(defun add-game (name)
  (with-transaction ()
    (unless (game-stored? name)
      (make-instance 'persistent-game :name name))))

;; 返回以流行程度排序的游戏列表
(defun games ()
  (nreverse (get-instances-by-range 'persistent-game 'votes nil nil)))

;; 对指定URL(加上.htm)自动生成 Hunchentoot 的处理器
(defmacro define-url-fn ((name)  &body body)
  `(progn
     (defun ,name ()
       ,@body)
     (push (create-prefix-dispatcher ,(format nil "/~(~a~)" name) ',name) *dispatch-table*)))

;;标准页面,使网站的风格一致
(defmacro standard-page ((&key title) &body body)
  `(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
     (:html :xmlns "http://www.w3.org/1999/xhtml"  :xml\:lang "en" :lang "en"
       (:head 
         (:meta :http-equiv "Content-Type" :content "text/html;charset=utf-8")
     (:title ,title)
     (:link :type "text/css" :rel "stylesheet" :href "/site.css"))
       (:body 
         (:div :id "header" ; Start all pages with our header.
           (:img :src "/GameVoter.png" :alt "Game Voter Logo" :class "logo")
           (:span :class "strapline" "Vote for your favourite Video Game"))
         ,@body))))

;; 负责产生HTML的函数
(define-url-fn (index)
  (standard-page (:title "Game Voter")
     (:h1 "Vote on your all time favourite games!")
     (:p "Missing a game? Make it available for votes " (:a :href "new-game" "here"))
     (:h2 "Current stand")
     (:div :id "chart" ; Used for CSS styling of the links.
       (:ol
    (dolist (game (games))
     (htm  
      (:li (:a :href (format nil "vote?name=~a" (name game)) "Vote!")
           (fmt "~A with ~d votes" (name game) (votes game)))))))))

(define-url-fn (new-game)
  (standard-page (:title "Add a new game")
     (:h1 "Add a new game to the chart")
     (:form :action "/game-added" :method "post"
        :onsubmit (ps-inline      ; 客户端验证
           (when (= name.value "")
             (alert "Please enter a name.")
             (return false)))
       (:p "What is the name of the game?" (:br)
       (:input :type "text" :name "name" :class "txt"))
       (:p (:input :type "submit" :value "Add" :class "btn")))))

(define-url-fn (game-added)
  (let ((name (parameter "name")))
    (unless (or (null name) (zerop (length name))) ; 万一 JavaScript 关闭了
      (add-game name))
    (redirect "/index")))

(define-url-fn (vote)
  (let ((game (game-from-name (parameter "name"))))
    (if game
    (vote-for game))
    (redirect "/index")))

回到SBCL

>(ql:quickload "web")

在浏览器中访问 http://127.0.0.1:8000/index 试试!

试了下CommonLisp的WEB开发相关推荐

  1. 《Node.js入门》Windows 7下Node.js Web开发环境搭建笔记

    最近想尝试一下在IBM Bluemix上使用Node.js创建Web应用程序,所以需要在本地搭建Node.js Web的开发测试环境. 这里讲的是Windows下的搭建方法,使用CentOS 的小伙伴 ...

  2. Linux 下搭建 Java Web 开发环境

    Linux 下搭建 Java Web 开发环境 我的小站.Github Java Web,是用Java技术来解决相关web互联网领域的技术栈,下方为 Linux 下搭建 Java Web 开发环境教程 ...

  3. ubuntu下搭建java web开发环境的详细步骤

    系统环境:Ubuntu 10.10(linux-kernel 2.6.35-22) 安装版本:apache-tomcat-7.0.29.tar.gz(官方网址:Apache Tomcat) 安装步骤: ...

  4. Web开发技术的演变

    原文出处: WildFly   欢迎分享原创到伯乐头条 受到好文<Web开发的发展史>(英文)激发的灵感,写下我对web开发技术的认识. 1. 静态页面时代 大学时候,上机还得换卡穿拖鞋, ...

  5. Web开发的发展史---Web开发技术的演变

    在接下来的几个月时间里,我打算写一系列关于完整web开发的文章.这第一篇文章虽然有所粗略,但也能够充分概括了在之前15年或者更久的时间里web应用程序如何进行演变.并且最后我会囊括下这段时间内所写的相 ...

  6. ztree树封装 json实例_小白7天入门PHP Web开发 - Day 6[下](综合)个人博客实例讲解用户数据的存储...

    <小白7天入门PHP Web开发>系列文章,面向单纯善良的完全不懂Web开发编程的入门速成课程,小白们如果感兴趣可以研读此系列文章,也可以连线提问.各路大神有何指教还请指点一二.希望各路大 ...

  7. Spring Boot 对基础 Web 开发的支持(下)2-2

    接着上一课我们继续讲解. 数据校验 在很多时候,当我们要处理一个应用程序的业务逻辑时,数据校验是必须要考虑和面对的事情.应用程序必 须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在 Java ...

  8. ubuntu下搭建eclipse+tomcat的web开发环境

    之前是打算给eclipse装上插件变成eclipse for javaEE 的,后来一看过程太麻烦了,直接下载eclipse for java EE 算了.搭建eclipse+tomcat的web开发 ...

  9. eclipse下web开发中缓存问题

    eclipse下web开发中缓存问题 原创 2016年04月06日 17:27:14 标签: eclipse / 缓存 / web开发 2351 问题描述:对web文件无论怎么修改,甚至删除,最后都会 ...

最新文章

  1. 【算法基础】时间复杂度:大O阶方法
  2. Java基础学习总结(6)——面向对象
  3. Java设计模式菜鸟系列(十三)建模和实现状态模式
  4. Tomcat7源码分析学习系列之二-----tomcat的真正的启动脚本catalina.bat解析
  5. 设计模式在vue中的应用(五)
  6. 西南交通大学计算机程序设计实验13,西南交通大学C++实验报告.doc
  7. 《Reids 设计与实现》第十四章 集群(上)
  8. python3 value counts函数_如何将value_counts()输出转换为数据帧?
  9. ubuntu 备份mysql数据库_Ubuntu Server下MySql数据库备份脚本代码
  10. 电脑软件安装手册 2019年4月22日
  11. wpa_supplicant2.9编译过程
  12. chrome 恐龙 html源码,Chrome 恐龙快跑
  13. Hypervisor技术
  14. Prometheus监控
  15. SegmentFault 思否发布开源问答社区软件 Answer
  16. 个人设置微信公众号自定义菜单的初级经验
  17. 微信视频号亮剑,微推贝贝推广引流再次升级
  18. Python中的左斜杠、右斜杠(正斜杠和反斜杠)
  19. java刷新透视表数据源,Excel数据透视表过滤源更新时更改的值
  20. 如何管理好一个工厂?

热门文章

  1. 【Android Protobuf 序列化】Protobuf 使用 ( Protobuf 使用文档 | 创建 Protobuf 源文件 | Protobuf 语法 )
  2. 【运筹学】整数规划 ( 整数规划示例 | 整数规划解决的核心问题 )
  3. FIFO buffer 和普通buffer区别
  4. Android ContentProvider介绍
  5. 【工具推荐】ELMAH——可插拔错误日志工具(转)
  6. movsb movsw movsd 指令详解
  7. 线索二叉树(c/c++)
  8. 使用squid配置透明代理并对上网行为进行控制
  9. 【动态规划】最长公共上升子序列
  10. Ember.js入门教程、博文汇总