`

用clojure编写rest风格的xml服务

 
阅读更多

 

一、准备
目标:为报表服务开发一个REST风格的xml的数据源。当以http GET方式访问url时,根据url解析出要执行的oracle存储过程和要传递给它的参数,从过程的out参数中取出xml结果作为响应。url格式如:/xml/pkgname.procname/param1,param2,param3,这里xml为url前缀。pkgname.procname为要调用的oracle存储过程的名称,这个过程的第一个参数固定为out clob类型,param1,param2等参数为存储过程的第二个参数以后的参数,全部为varchar2类型。上面的url实际调用的存储过程为pkgname.procname(p_xml out clob,param1 varchar2,param2 varchar2,param3 varchar2)。

工具:clojure 1.3.0、Leiningen 1.7.1、emacs

配置clojure emacs开发环境请参考swank-clojure

使用lein创建新工程,工程定义如下:
(defproject cljxxbixml "1.0.0-SNAPSHOT"
  :description "调用pl/sql过程,以text/xml形式将结果输出"
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [compojure "1.1.0"]
                 [org.clojure/java.jdbc "0.1.3"]
                 [com.oracle/ojdbc14 "10.2.0.3.0"]
                 [com.h2database/h2 "1.3.167"]
                 [c3p0/c3p0 "0.9.1.2"]]
  :dev-dependencies [[lein-ring "0.7.1"]
                     [ring-server "0.2.3"]]
  :plugins [[lein-ring "0.7.1"] [lein-swank "1.4.4"]]
  :ring {:handler cljxxbixml.core/app})

lein-ring 插件是用于开发基于ring的web应用程序的,同时也提供了将应用程序打包成war的功能。

初次使用clojure开发web应用程序可以参考compojure的wiki

二、web层
web层主要使用了compojure来处理rest风格的请求并产生响应。

;; # -*- coding: utf-8 -*-

(ns cljxxbixml.core
  (:use compojure.core cljxxbixml.db)
  (:require [compojure.route :as route]
            [compojure.handler :as handler]))

(defn xml-response [data & [status]]
  "用于生成utf-8 xml响应"
  {:status (or status 200)
   :headers {"Content-Type" "text/xml; charset=utf-8"}
   :body data})

(defn main-page []
  "首页"
  (xml-response "<data>Hello World1! 汉字</data>"))

(defn xml-page [proc param]
  "生成xml数据"
  (xml-response
   (gen-xml proc
            (drop-last
             (clojure.string/split
              ;; 防止,,,,之类的字符串split之后数组长度为0
              (str param ",EOF") #",")))))

(defn parse-uri [uri]
  "获取uri中第二个/开始的以/分割的Seq"
  (nnext (clojure.string/split uri #"\/")))

(defroutes main-routes
  "请求地址映射"
  (GET "/" []
       (main-page))
  (GET "/xml/*" {:keys [uri]}
       (apply xml-page (parse-uri uri)))
  (GET "*" {:keys [scheme server-name server-port uri]}
       (str (name scheme) "://" server-name ":" server-port uri)))

(def app
  "主handler"
  (handler/site main-routes))

为了便于在lein swank下进行增量开发。可以将下面的代码直接放到repl中执行。

;; # -*- coding: utf-8 -*-

;; slime里用于交互式调试
(require '[ring.server.standalone :as rserver])
(require '[cljxxbixml.core :as bi])
;; 仅定义一次,route修改时不会发生作用
;;(defonce server (rserver/serve bi/app))
;;(.stop server)
;;(.start server)
(def server (rserver/serve bi/app))

这里的通过(.stop server)和(.start server)可以停止或启动嵌入的web服务器。

三、数据访问
数据访问这部分主要使用了java.jdbc这个程序库。这个程序库的示例中都是直接使用jdbc连接而没有使用数据库连接池,使用的示例中也基本只有crud之类的操作,没有找到如何调用oracle存储过程,一翻google之后我找到了使用连接池调用oracle存储过程 的方法。

;; # -*- coding: utf-8 -*-

(ns cljxxbixml.db
  (:require [clojure.java.jdbc :as sql])
  (:import com.mchange.v2.c3p0.ComboPooledDataSource
           java.sql.Types))

;; ===连接池使用的数据源===
(def db-spec
  "数据源定义"
  {:classname "oracle.jdbc.driver.OracleDriver"
   :subprotocol "oracle:thin"
   :subname "@//bieedb.dtsxpower.com:1521/biee"
   :user "biee"
   :password "biee"})

(defn pool [spec]
  "连接池"
  (let [cpds (doto (ComboPooledDataSource.)
               (.setDriverClass (:classname spec))
               (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
               (.setUser (:user spec))
               (.setPassword (:password spec))
               ;; expire excess connections after 30 minutes of inactivity:
               (.setMaxIdleTimeExcessConnections (* 30 60))
               ;; expire connections after 3 hours of inactivity:
               (.setMaxIdleTime (* 3 60 60)))]
    ;; with-connection可以使用:datasource
    ;; 参见:http://clojure.github.com/java.jdbc/index.html#clojure.java.jdbc/with-connection
    {:datasource cpds}))                

(def pooled-db (delay (pool db-spec)))

(defn db-connection [] @pooled-db)

;; ===不使用连接池===
(def db {:classname "oracle.jdbc.driver.OracleDriver" ; must be in classpath
         :subprotocol "oracle:thin"
         :subname "@10.232.234.50:1609:TEMP"
         ;; Any additional keys are passed to the driver
         ;; as driver-specific properties.
         :user "apps"
         :password "apps" })

(defn connection-test []
  "测试数据库连接"
  (sql/with-connection (db-connection)
    (sql/with-query-results res
      ["select 1 from dual"]
      (doseq [rec res]
        (println rec)))))

(defn gen-xml [procName params]
  "调用过程生成xml数据"
  (sql/with-connection (db-connection)
    (with-open [stmt (.prepareCall
                      (sql/connection)
                      (str "{call " procName "(?"
                           (clojure.string/join (map (fn [v] ",?") params))
                           ")}"))]
        (.registerOutParameter stmt 1 Types/CLOB)
        (doseq [[index param] (map vector (iterate inc 0) params)]
          (.setString stmt (+ index 2) param))
        (.execute stmt)
      (let [content (.getClob stmt  1)]
        (.getSubString content 1 (.length content ))))))
分享到:
评论

相关推荐

    tools.analyzer, 用于Clojure代码的分析器,用Clojure编写,并在EDN中生成 AST.zip

    tools.analyzer, 用于Clojure代码的分析器,用Clojure编写,并在EDN中生成 AST tools.analyzer主机无关Clojure代码的分析器,用Clojure编写,并在EDN中生成 AST 。我在 2015年12月的ClojureX上讨论了 tools.analyzer...

    tools.analyzer:使用Clojure编写并在EDN中生成AST的Clojure代码分析器

    工具分析器用于主机不可知的Clojure代码的分析器,用Clojure编写,并在EDN中产生AST。 我介绍了tools.analyzer [.jvm]在ClojureX谈话在2015年12月视频蒂莫西·鲍德里奇了在Clojure中/西tools.analyzer [.jvm]谈话三...

    cloj:完全用 Clojure 编写的网站应用程序

    css 是用 Clojure 编写的。 前端是用 ClojureScript 编写的,它编译成 JS。下一步实现 Friend 或 Sandbar 并进行用户身份验证。启动并运行安装。 最简单的方法是在 Mac 上使用 Homebrew。 祝你在 Windows 上好运......

    lazybot:一个用 Clojure 编写的 IRC 机器人

    是一个用 Clojure 编写的 IRC 机器人。 在,它使用与 IRC 交谈。 该机器人可以通过插件高度扩展。 插件使用 Clojure 编写,使用轻量级 DSL。 已经有很多插件了,包括 Haskell 和 Clojure 代码评估、谷歌搜索以及使用...

    pink:用Clojure编写的音乐系统开发库

    粉色的 用Clojure编写的音乐系统开发库。介绍该库为开发音乐系统提供了基础。 它的设计还可以根据用户需求扩展,无论他们是在探索和设计低级信号处理算法,开发预先编写的合成文件还是创建交互式实时系统。 它提供了...

    rinok:一个用Clojure编写的非常简单的匹配引擎

    一个用Clojure编写的非常简单的匹配引擎 用法 您可以克隆项目并运行: lein run 这是一个非常简单的例子: ( ns rinok.core ( :require [rinok.engine :as eng])) ( defn -main [] ( let [engine ( eng/-&gt;...

    crud:使用clojure,rest,ring,hiccup,mysql的示例Crud项目

    粗鲁的沙盒CRUD项目,使用clojure,ring,compojure,hiccup,rest,mysql,bootstrap,jQuery 想法是创建一个web.project,您可以在其中更改代码后在浏览器中按f5键。 无需手动编译或构建。先决条件您将需要安装 ...

    Programming Clojure 英文电子版

    本书详细介绍了如何使用Clojure编写程序,并涵盖了从基础语法到高级主题的各个方面。书中通过丰富的示例代码展示了如何利用Clojure的各种特性来解决实际问题。此外,《Programming Clojure》还讨论了Clojure的开发...

    clojure-rest-api

    Clojure-REST-API Clojure REST Api基于(本文)[ ] 路线: GET / api / v1 / todos 开机自检/ api / v1 / todos GET / api / v1 / todos /:id 放置/ api / v1 / todos /:id 删除/ api / v1 / todos /:id ...

    Lacinia纯Clojure实现的GraphQL

    2. **定义GraphQL Schema**:使用Clojure编写GraphQL类型和字段的定义,这些定义会转换成Lacinia可以理解的结构。 3. **创建解析器**:为每个GraphQL字段创建对应的Clojure函数,这些函数将作为查询的实际执行者。 ...

    clojure-scripting:使用JVM Clojure编写脚本的第一步

    标题“clojure-scripting:使用JVM Clojure编写脚本的第一步”暗示了我们将探讨如何使用Clojure来编写脚本,并且是在JVM环境下,而不是传统的JavaScript环境。这通常涉及到利用GraalVM的特性,它允许Clojure Script...

    restful-clojure:一个用 Clojure 编写的 RESTful 购物清单应用程序后端示例,伴随着 kendru.github.io 上的教程系列

    这个项目旨在为开发者提供一个学习Clojure和构建RESTful服务的实例,同时也配合了在kendru.github.io上发布的教程系列,使学习过程更具实践性。 Clojure是一种现代的、静态类型的函数式编程语言,它运行在Java...

    italianquiz:用Clojure编写的交互式测验应用程序

    它是用Clojure编写的,Clojure是在Java虚拟机(JVM)上运行的Lisp。 语法和词汇形式主义基于如书中所述[波拉德和1994凹陷。 入门 WARNING: these instructions are out of date. eugenekontzspro:italianquiz ...

    todo.clj:用Clojure编写的Todo Web应用

    用clojure编写。 先决条件 您需要安装 1.7.0 或更高版本。 用于本地测试的 postgresql 用于部署的 当地的 创建 postgresql 数据库 创建本地 postgresql 数据库 $ cd path/to/todo.clj $ initdb pg $ postgres -D ...

    Clojure Data Analysis Cookbook

    - **数据结构和序列操作**:解释 Clojure 中常用的数据结构,如列表、向量、集合和映射,并展示如何使用这些结构进行数据处理。 - **函数式编程**:探讨 Clojure 如何支持纯函数式编程风格,包括高阶函数、闭包和...

    dpgurl:用clojure编写的expirale url缩短器

    【标题】:“dpgurl:用Clojure编写的Expirable URL缩短器” 【描述】:dpgurl是一个使用Clojure编程语言实现的URL缩短器,具有URL过期功能。这个项目旨在提供一种高效且安全的方式来缩短长URL,并在设定的时间后...

    Clojure编程乐趣]+clojure_programming.pdf

    在“Clojure编程乐趣”这本书中,你将学习到如何使用Clojure进行函数式编程,如何利用Clojure的强大工具处理数据,以及如何构建并发和分布式系统。此外,书中可能还会介绍Clojure社区的一些最佳实践和常用库,例如...

    Practical Clojure.pdf

    使用Clojure编程,随着程序的增长,并不会变得更复杂难以理解,反而会变得更简单、表达性更强。Clojure鼓励开发者尝试在其他语言中过于复杂而通常不会尝试的事情,例如并发编程、不可变性和惰性数据结构。因为...

    clojure eclipse

    Clojure 是一种基于 Lisp 语法的现代函数式编程语言,它运行在 Java 虚拟机(JVM)上,并且充分利用了 Java 的生态系统。...通过熟练掌握Clojure和Eclipse的使用,开发者可以提高生产力,编写出高效、可维护的代码。

Global site tag (gtag.js) - Google Analytics