编辑:最后添加了更多信息。另外,还可以通过jetty-runner.jar(不是tomcat)来进行战争
我正在使用boot作为clojure应用程序的构建工具。
这是我在一个项目中使用cljs
,cljc
和clj
代码(以及sass
)编写的第一个应用程序。
我的build.boot
具有以下task-options
(def db-opts (:db (clojure.edn/read-string (slurp "resources/config.edn"))))
(task-options!
pom {:project 'gcr
:version "0.1"}
cljs {:optimizations :simple}
uber {:as-jars true}
war {:file "gcr.war"}
ragtime {:database (str "jdbc:"
(:dbtype db-opts) "://"
(:user db-opts) ":"
(:password db-opts) "@"
(:host db-opts) ":"
(:port db-opts) "/"
(:dbname db-opts))}
test {:include #"gcr.test"
:junit-output-to "junit-out"})
我的build
任务定义如下:
(deftask build
"Builds an uberjar of this project that can be run with java -jar"
[]
(comp
(aot :all true ;; :namespace #{'gcr.server}
)
(pom)
(cljs :optimizations :simple)
(sass)
(uber)
(jar :file "gcr.jar" :main 'gcr.server)
(sift :include #{#"gcr.jar"})
(target)))
当我运行boot build
时,项目会正常运行,没有任何错误。
但是当我运行java -jar target/gcr.jar
我得到以下信息:
$ java -jar target/gcr.jar
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=lcd -Dswing.aatext=true
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
at gcr.server.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: clojure.lang.Var
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
我已经研究了大约24小时,但仍然无法弄清楚如何使其正常工作。 (我终于能够与jetty-runner
进行一场战争,但无法在Tomcat上进行战争)
更多信息:
我的boot.properties
是
BOOT_CLOJURE_NAME=org.clojure/clojure
BOOT_CLOJURE_VERSION=1.10.0
BOOT_VERSION=2.8.2
我正在使用openjdk version "1.8.0_202"
我检查了构建的jar文件是否使用jar tf target/gcr.jar
使用clojure jar,并列出了以下行:
7c506484bc48541ffa5dcb4d9366a8a2-clojure-1.10.0.jar
我的IFDE工作正常,我定义了以下dev
任务,如下所示:
(deftask dev
"Launch Immediate Feedback Development Environment"
[]
(comp
(serve :handler 'gcr.core/app ;; ring handler
:resource-root "public" ;; root classpath
:reload true) ;; reload ns
(watch)
(reload)
(cljs-repl) ;; before cljs task
(cljs)
(sass)
(target :dir #{"public"})))
set-env!
部分如下:
(set-env!
:source-paths #{"src/scss" "src/clj" "src/cljs" "src/cljc"}
:resource-paths #{"html" "resources"}
:dependencies '[[org.clojure/clojure "1.10.0"]
[org.clojure/clojurescript "1.10.520"]
;; server
[compojure "1.6.1"]
[ring/ring-core "1.7.1"]
[ring/ring-jetty-adapter "1.7.1"]
[ring/ring-json "0.4.0"]
[ring-middleware-format "0.7.4"]
;; [javax.servlet/servlet-api "2.5" :scope "test"]
;; [yogthos/config "1.1.1"]
;; java 10 upgrade
[javax.xml.bind/jaxb-api "2.4.0-b180830.0359"]
;; common
[org.clojure/core.async "0.4.490"]
[org.clojars.akiel/async-error "0.3"]
[hickory "0.7.1"]
[instaparse "1.4.10"]
;; clj
[clj-time "0.15.1"]
[clj-http "3.9.1"]
[clout "2.2.1"]
[org.clojure/data.json "0.2.6"]
[org.clojure/data.codec "0.1.1"] ;; Base64
;; cljs
[com.andrewmcveigh/cljs-time "0.5.2"]
[prismatic/dommy "1.1.0"]
[hipo "0.5.2"]
[hodgepodge "0.1.3"]
[cljs-http "0.1.46"]
[com.cemerick/url "0.1.1"]
[reagent "0.8.1"]
;; db
[ragtime "0.8.0"] ;; Migrations
[hikari-cp "2.7.1"] ;; Connection Pooling
[org.clojure/java.jdbc "0.7.9"]
[honeysql "0.9.4"]
[org.postgresql/postgresql "42.2.5"]
;; Authentication framework with JWT
[buddy/buddy-auth "2.1.0"]
[buddy/buddy-core "1.5.0"]
[buddy/buddy-sign "3.0.0"]
;; argon2 for password hashing
[de.mkammerer/argon2-jvm "2.5"]
;; logging
[com.taoensso/timbre "4.10.0"] ;; logging
[com.fzakaria/slf4j-timbre "0.3.12"]
[org.slf4j/log4j-over-slf4j "1.7.26"]
[org.slf4j/jul-to-slf4j "1.7.26"]
[org.slf4j/jcl-over-slf4j "1.7.26"]
;; spec , test & gen
[org.clojure/test.check "0.9.0"]
;; Dependencies for build process
[adzerk/boot-cljs "2.1.5"]
[adzerk/boot-test "1.2.0" :scope "test"]
[pandeiro/boot-http "0.8.3"]
[adzerk/boot-reload "0.6.0"]
[adzerk/boot-cljs-repl "0.4.0"]
[cider/piggieback "0.3.9" :scope "test"]
[nrepl "0.4.5" :scope "test"]
;; [com.cemerick/piggieback "0.2.2" :scope "test"]
[weasel "0.7.0" :scope "test"]
[org.clojure/tools.nrepl "0.2.13" :scope "test"]
[mbuczko/boot-ragtime "0.3.1"]
[deraen/boot-sass "0.3.1"]
[tolitius/boot-check "0.1.12"]])
经过大量的任务处理,我能够构建一个与jetty-runner
配合使用的war文件,并具有以下任务:
(deftask build-war
"Build the target/app.war file"
[]
(comp
(aot :all true)
(web :serve 'gcr.core/app)
(cljs :optimizations :advanced)
(sass)
(sift :move {#"(.*)js$" "public/$1js"
#"(.*)html$" "public/$1html"
#"css/(.*)" "public/css/$1"})
(uber)
(war :file "gcr.war")
(sift :include [#"gcr.war"])
(target)))
使用sift
任务将静态资源移动到public
文件夹是关键,因为我在routes.clj
中将compojure资源定义如下(不包括API和其他路由) )。
(defroutes gen-routes
(GET "/login" [] auth/auth-handler)
(files "/" {:root "public"}) ;; to serve static resources
(resources "/" {:root "public"}) ;; to serve anything else
(not-found "404 Page Not Found")) ;; page not found
但是,这仍然不会产生适用于tomcat的war
文件。也就是说,在部署到tomcat时,所有API路由均可按预期工作,但是静态html文件显示为HTTP / 404。