January 4, 2021
By: Syh
新手入门clojure开发(本入门为windows10系统)
安装ag
- 打开powershell
- scoop是windows的一款包管理工具
set-executionpolicy remotesigned -scope currentuser
iex (new-object net.webclient).downloadstring('https://get.scoop.sh')
- 第二步会出现 不能访问 https://get.scoop.sh 问题
- 修改host文件(文件目录在 C:\Windows\System32\drivers\etc文件下)
- 点击链接 搜索 raw.githubusercontent.com
- host里面添加 199.232.68.133 raw.githubusercontent.com
环境配置
- 安装jdk8+以上的JDK
- 安装leiningen
- lein version 查看版本
Cljure入门
clojure是一种运行在JVM上的Lisp方言,属于函数式编程范式,它和java可以方便的互相调用,这样开发的程序可以很好的结合java和clojure的优点
Emacs入门
- 下载 配置
- Emacs默认配置在 C:\Users\Administrator\AppData\Roaming下
- Emacs常用命令C(Ctrl) M(Alt) S(Shift)
C-x C-f打开/新建文件C-x C-s保存当前缓冲区C-x b切换BufferM-.跳转到定义(需要cider)M-,从跳转处返回(需要cider)C-=expand-region, 结合+,-可以选中更大的范围和更小的范围C-c C-c执行最外层的s-expressionM-(把当前s-expr放到括号当中, 是paredit中众多功能的一部分, 参见使用paredit编辑clojureM+↑删除上层表达式, 也是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-stringC-q C-m去掉M(如果文件出现M 可用)M-x electric-pair-mode打开括号配对模式M-x color-theme-sanityinc-..-...背景主题颜色,clearcider清空控制台
Cljure 开发
创建项目
- 创建普通项目
lein new app hello
- 创建luminus项目
lein new luminus hello +service +mysql
- 项目结构
- 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 开发
- 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")
运行
- cmd启动
- lein run migrate(初始化数据库)
- lein run (运行)
- repl启动
- lein repl
- (start)
- (migrate)
- 在Emacs启动
- M-x cider-jack-in-clj
- (start)
- cmd启动
开发接口
- 在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)))}}]])
- 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]))
可以修改routes文件夹下的base.clj
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前段
- 启动
- 启动前 yarn 一下
- emacs启动
- M-x cider-jack-in-cljs
- shadow
- :app
- 在localhost:9630 启动start-watch
- localhost:8000
- 前段开发流程
- 在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])