January 4, 2021
By: Syh

新手入门clojure开发(本入门为windows10系统)

  1. 安装ag
  2. 环境配置
  3. Cljure入门
  4. Emacs入门
  5. Cljure 开发
  6. CljureScript前段

安装ag

  1. 打开powershell
  2. scoop是windows的一款包管理工具
set-executionpolicy remotesigned -scope currentuser
iex (new-object net.webclient).downloadstring('https://get.scoop.sh')
  1. 第二步会出现 不能访问 https://get.scoop.sh 问题
    • 修改host文件(文件目录在 C:\Windows\System32\drivers\etc文件下)
    • 点击链接 搜索 raw.githubusercontent.com
    • host里面添加 199.232.68.133 raw.githubusercontent.com

环境配置

  1. 安装jdk8+以上的JDK
  2. 安装leiningen
    • 可以创建两个bin和self-installs文件夹
      • 下载 lein.bat 放到bin文件下
      • 下载 leiningen-2.8.1-standalone.zip 后缀名改成.jar 放到self-installs文件下
  3. lein version 查看版本

Cljure入门

clojure是一种运行在JVM上的Lisp方言,属于函数式编程范式,它和java可以方便的互相调用,这样开发的程序可以很好的结合java和clojure的优点

学习基本语法

Emacs入门

  1. 下载 配置
  2. Emacs默认配置在 C:\Users\Administrator\AppData\Roaming下
  3. Emacs常用命令C(Ctrl) M(Alt) S(Shift)
    • C-x C-f 打开/新建文件
    • C-x C-s 保存当前缓冲区
    • C-x b 切换Buffer
    • M-. 跳转到定义(需要cider)
    • M-, 从跳转处返回(需要cider)
    • C-= expand-region, 结合+, -可以选中更大的范围和更小的范围
    • C-c C-c 执行最外层的s-expression
    • M-( 把当前s-expr放到括号当中, 是paredit中众多功能的一部分, 参见使用paredit编辑clojure
    • M+↑ 删除上层表达式, 也是paredit模式众多功能中的一个
    • C-c p s s 使用ag查找文本, projectile模式中众多功能中的一个
    • C-c p f 查找文件, projectile模式中众多功能中的一个
    • C-M-b 跳到表达式开始
    • C-M-f 跳到表达式结束
    • M-w 复制标记区内容
    • C-y 帖粘
    • C-w 剪贴
    • C-x 0 关闭当前窗口
    • C-x 2 水平分割窗格
    • C-x 3 垂直分割窗格
    • C-S - 撤销
    • C-p 上一行
    • C-n 下一行
    • M-S < 文件头
    • M-S > 文件尾
    • M-S { 函数头
    • M-S } 函数尾
    • M-x cnfonts-decrease-fintsize 字体变小
    • M-x cnfonts-increase-finteize 字体变大
    • M-x replace-string C-q C-m 去掉M(如果文件出现M 可用)
    • M-x electric-pair-mode 打开括号配对模式
    • M-x color-theme-sanityinc-..-... 背景主题颜色
    • ,clear cider清空控制台

Cljure 开发

创建项目

  1. 创建普通项目
lein new app hello
  1. 创建luminus项目
lein new luminus hello +service +mysql
  1. 项目结构
    • project.clj 后端依赖
    • package.json 前端导包依赖
    • shadow-cljs.edn 前端配置
    • dev-config.edn 用于本地开发配置-后端配置
    • src
      • clj 编写后端代码
      • cljs 编写前段代码
    • src/clj
      • middleware.clj 包含应用程序的自定义中间件的名称空间
      • core.clj 用于容纳与数据库交互的功能
    • src/clj/routes 命名空间就是对我们的家庭和对页面的路线和控制器的位置
    • resources
      • public 存放静态文件(css,img)
      • sql 放sql(用到的框架hugsql)
      • migrations 放sql 都是成对的 .down(删除表) .up(创建表)
    • 创建migrations

(create-migration "add-del-name-table") ```

Cljure 开发

  1. clojure创建项目
    • 创建项目
    • 导入依赖
    • 在dev-config.edn配置数据库连接
:database-url "jdbc:log4jdbc:mysql://localhost:3306/demo?user=root&password=root&useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Hongkong"
- 创建migrations
- 创建后分为两个sql文件 xx.up.sql(创建表语句) xx.down.sql(删除表语句)
- 引入日志(在db.core下)
(Class/forName "net.sf.log4jdbc.DriverSpy")
  1. 运行

    • cmd启动
      • lein run migrate(初始化数据库)
      • lein run (运行)
    • repl启动
      • lein repl
      • (start)
      • (migrate)
    • 在Emacs启动
      • M-x cider-jack-in-clj
      • (start)
  2. 查看localhost:3000

  3. 开发接口

    • 在resources\sql编写sql
-- :name query-get-many :? :*
-- :doc 查询
select * from demo;
- 创建xxx_db.clj
(ns backend.modules.demo-db
    (:require [conman.core :as conman]
            [backend.db.core :refer [*db*]]))
(conman/bind-connection *db*
                        "sql/demo.sql")
当修改sql语句要重新加载xxx_db.clj文件  C-c C-c或  C-c C-e
- 创建xxx_service.clj
(ns project.modeules.demo-service
    (:require [project.modeules.demo-db :as db]
            [clojure.string :as string]))

(defn get-lists
  []
  (db/query-get-many))
- 创建xx_routes.clj
(ns project.modeules.demo-routes
  (:require [project.modeules.demo-service :as service]
            [project.common.result :refer [ok]]
            [clojure.spec.alpha :as s]
            [spec-tools.core :as st]
            [spec-tools.data-spec :as ds]))

(defn test []
  ["/test"
   {:swagger {:tags ["测试"]}}

   ["/list"
    {:get {:summary "查询测试"
           :handler (fn [_]
                      (ok
                       (service/get-lists)))}}]])
  1. spec数据校验 spec库主要是用来定义数据的结构和类型,并对其数据类型进行校验,并且可以根据spec生成对应的校验数据。要使用clojure.spec库,必须依赖最新的alpha版本的clojure:
    • 有默认值的
[clojure.spec.alpha :as s]
[spec-tools.core :as st]
[spec-tools.data-spec :as ds]
(s/def ::page
    (st/spec
   {:spec            int?
    :description     "页码,从0开始"
    :swagger/default "0"
    :reason          "页码参数不能为空"}))
- 可以为空的
(def xw-params
    {(ds/opt :id) (s/nilable int?)
   :company_name string?
   (ds/opt  :company_code) (s/nilable string?)
   (ds/opt :into_name) (s/nilable string?)
   (ds/opt :small_micro) (s/nilable string?)})
    ```

    - 嵌套多个list
    ```clojure
(s/def ::office-ui
    (s/keys :opt-un [::id ::investment_company  ::investment_amount]))
     (s/def ::list (s/coll-of ::office-ui))
     (s/def ::office-up-ins (s/keys :req-un [::list ::company_id]))
  1. 可以修改routes文件夹下的base.clj

  2. handler.clj引入写的路由

[project.modeules.demo-routes :refer [test]]

(mount/defstate app-routes
  :start
  (ring/ring-handler
   (ring/router
    [(conj
      (services/service-routes)
      (services/swagger-routes)
      (test))])
   (ring/routes
    (ring/create-resource-handler{:path "/"})
    (wrap-content-type (wrap-webjars (constantly nil)))
    (ring/create-default-handler))))

CljureScript前段

  1. 启动
    • 启动前 yarn 一下
    • emacs启动
      • M-x cider-jack-in-cljs
      • shadow
      • :app
      • 在localhost:9630 启动start-watch
      • localhost:8000
  2. 前段开发流程
    • 在url.cljs添加后端接口
(ns legal-affairs.url
    (:require
   [legal-affairs.config :refer [domain]]))

;;信息维护url
(def  message-small
  {:small-list (str domain "/api/haier/samlls")})
- 创建events层
(ns legal-affairs.haier.small.small-events
  (:require [ajax.core :as http]
            ["antd" :as ant]
            [kee-frame.core :as kf]
            [re-frame.core :as rf]
            [legal-affairs.url :refer [message-samll]]))
;;controller 请求路径等于/haier/small 的时候启动start里面是事件
(kf/reg-controller
 ::small-controller
 {:params (fn [route]
            (when (-> route :path-params :path (= "/haier/small")) true))
  :start (fn []
           (rf/dispatch [:small/fetch-list]))
  :stop (fn []
          (rf/dispatch [clear-fetch-list]))}
 )
;; reg-event-fx 一个事件 处理分页请求
(kf/reg-event-fx
 :small/fetch-list
 (fn [{:keys [db]} [query]]
   (let [params (if query query {:page 0 :size 10})]
     {:db (update-in db [:small :data]
                     #(assoc % :loading true :query query))
      :dispatch [:request/get
                 {:url  (:samll-list message-samll)
                  :params params
                  :callback-event :small/fetch-list-success}]})))
(kf/reg-event-fx
 :small/fetch-list-success
 (fn [{:keys [db]} [data]]
   {:db (update-in
         db
         [:small :data]
         #(assoc % :loading false
                 :data (:small data)
                 :pagination {:total (:total data)
                              :pageSize (:size data)
                              :current (inc (:page data))}))}))
;; 获取页面db中的值
(rf/reg-sub
 :small/fetch-list-info
 (fn [db [_]]
   (get-in db [:small :data])))
        ;;在视图引入获取数据
		(rf/subscribe [:small/fetch-list-info])
Tags: clojure