clojure-api:用于多个API处理程序的单个主要clj

时间:2017-07-07 13:04:04

标签: clojure clojure-contrib

以下是我的app project.clj

(defproject clojure-my-app-api "0.1.0-SNAPSHOT"
      :description "FIXME: write description"
      :url "http://example.com/FIXME"
      :license {:name "Eclipse Public License"
                :url "http://www.eclipse.org/legal/epl-v10.html"}
      :ring {:handler clojure-my-app-api.core/app} 
      :dependencies [[org.clojure/clojure "1.8.0"]
                     [metosin/compojure-api "1.1.10"]
                     [ring/ring-core "1.4.0"]
                     [ring/ring-jetty-adapter "1.4.0"]]
      :main clojure-my-app-api.core)

我的app core.clj是

(ns clojure-my-app-api.core
  (:require [ring.adapter.jetty :as jetty])
  (:require [compojure.api.sweet :refer :all])
  (:require [ring.util.http-response :refer :all]))

(defapi app
  (GET "/hello" []
    :query-params [name :- String]
    (ok {:message (str "Dear " name ", Hello I am here ")})))

(jetty/run-jetty app {:port 3000})

我的疑问是,如果我们有多个类来处理多个API请求,是否必须在每个clj类中放置(jetty/run-jetty app {:port 3000})

请你帮我解决一下多个clj类处理不同API路径的单一主类机制。

我修改了我的代码。

project.clj

(defproject clojure-dauble-business-api "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :ring {:handler {clojure-dauble-business-api.core/app 
                  clojure-dauble-business-api.test/test1}}
  :repl-options {:init-ns clojure-dauble-business-api.user}
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [metosin/compojure-api "1.1.10"]
                 [ring/ring-core "1.4.0"]
                 [ring/ring-jetty-adapter "1.4.0"]]
  :main clojure-dauble-business-api.user)

user.clj

(ns clojure-dauble-business-api.user
  (:require [ring.adapter.jetty :as jetty])
  (:require [compojure.api.sweet :refer :all])
  (:require [ring.util.http-response :refer :all])
  (:require [clojure-dauble-business-api.core :as core])
  (:require [clojure-dauble-business-api.test :as test]))

(jetty/run-jetty (list core/app test/test) {:port 3000})

core.clj

(ns clojure-dauble-business-api.core
  (:require [ring.adapter.jetty :as jetty])
  (:require [compojure.api.sweet :refer :all])
  (:require [ring.util.http-response :refer :all]))

(defapi app
  (GET "/hello" []
    :query-params [name :- String]
    (ok {:message (str "Dear " name ", Hello I am here ")})))

test.clj

(ns clojure-dauble-business-api.test
  (:require [ring.adapter.jetty :as jetty])
  (:require [compojure.api.sweet :refer :all])
  (:require [ring.util.http-response :refer :all]))

(defapi test
  (GET "/ping" []
    :query-params [name :- String]
    (ok {:message (str "Dear " name ", Hello I am here ")})))

在Postman中运行http://localhost:3000/hello?name=acbd端点时出错

2017-07-08 10:46:34.413:WARN:oejs.HttpChannel:qtp191004666-15: /hello?name=abcd
java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
    at ring.adapter.jetty$proxy_handler$fn__1401.invoke(jetty.clj:24)
    at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle(Unknown Source)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:497)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Thread.java:745)

2 个答案:

答案 0 :(得分:2)

您的任何命名空间都不应该有(jetty/run-jetty (list core/app test/test) {:port 3000})。 (在user.clj中使用它可以用于REPL工作)。

通常,您有一个处理程序路由,您将其传递给响铃以处理您的应用程序。

例如,我通常有一个routes命名空间,我通过其他命名空间的路由组合。

所以,从你的例子开始。

(ns clojure-dauble-business-api.routes
    :require [compojure.core :refer :all]
             (clojure-dauble-business-api [core :as core]
                                          [test :as t]))
(def app
 (routes core/app t/test))

这是您可以传递到Jetty的内容,或者在:ring的{​​{1}}条目中引用。

project.clj

您收到错误,因为:ring {:handler clojure-dauble-business-api.routes} 必须传递一个函数,但您要将其传递给列表(因为您尝试使用run-jetty

我还会将插件lein-ring添加到您的项目中,然后删除(list core/app test/test)条目。您还必须如上所述更正项目中的:main条目。

答案 1 :(得分:0)

我也是新手,但希望这会有所帮助:

这就是我实施的方式。有一个名为user.clj的文件有
(jetty/run-jetty app {:port 3000})

以及您可以在main中指定的其他常用函数,然后在project.clj中指定  :repl-options {:init-ns user}

您也可以使用注入来加载命名空间,但我从未使用它们。