用Emacs進行Java開發
Table of Contents
1 效果(Ensime做后端,使用JavaFx開發界面)
2 Java開發的IDE
2.1 Eclipse和IntelliJ IDEA
Java開發的兩個常用IDE是Eclipse和IntellJ IDEA。其中,Eclipse是一個免費和開源的版本,其他的很多語言的IDE也是使用它,然后,進行修改的。IntelliJ IDEA是一個收費的IDE,據說比Eclipse好用很多。這兩個我都用的不多,Eclipse相對而言還要多一點。
3 Java開發的構建工具
什么是構建工具呢?
最早期的時候,是單文件的項目,根本不需要構建工具,直接編譯那個單文件就可以。當項目變大,變復雜,項目的文件越來越多,然后,出現第一個構建工具:Make,后來,其發展為GNU Make。但是,由於需求的不斷涌現,項目不僅僅只需要編譯,還需要測試、部署等各種任務,各種語言出現了各種各樣的構建工具。
當前,JVM生態圈由三大構建工具所統治:
- Ant
- Maven
- Gradle
3.1 Ant
ANT是最早的構建工具,基於idea,好象是2000年有的,當時是最流行java構建工具,不過它的XML腳本編寫格式讓XML文件特別大。對工程構建過程中的過程控制特別好。
3.2 Maven
Maven它是用來給Ant補坑的,Maven第一次支持了從網絡上下載的功能,仍然采用xml作為配置文件格式,它的問題是不能很好的相同庫文件的版本沖突。Maven專注的是依賴管理,構建神馬的並不擅長。
3.3 Gradle
Gradle屬於結合以上兩個的優點,它繼承了Ant的靈活和Maven的生命周期管理,它最后被google作為了Android御用管理工具。它最大的區別是使用groovy語言作為配置文件格式,不用XML進行配置,使得腳本更加簡潔。
4 既有IDE,何需構建工具?
我們一直搞不懂,既然,已經有Eclipse、IntelliJ IDEA等IDE工具,開發起來,創建項目,然后,點一下run就可以了,非常方便了,還要弄一堆的構建工具出來,麻不麻煩?為什么呢?
覺得應該很多同學有和我一樣的疑惑,所以分享下
1.使用github上的開源項目時是不是經常發現有個叫maven的東西?
2.第一次使用Android studio時是不是要下載一個gradle的玩意?
折騰了一天,想導入下github的客戶端源碼。當然現在還沒成功…各種看不懂的錯誤。郁悶為什么他們弄這些高端玩意干嘛,我們平時eclipse里面不一樣的好好的開發嗎。
作者:Antsdot蟻點
鏈接:https://zhuanlan.zhihu.com/p/23634332
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
同樣,這里也有一個回答:
“一般而言,一個比較正規的項目都不會基於IDE進行構建…一般會用ant, maven, gradle , 為什么不用IDE呢?
首先,是IDE的選擇,有人喜歡,用Vim,Eclipse,IntelliJ IDEA,收費的,免費的.
特別是公開的項目,你用什么IDE 相當於為這個IDE 打廣告了..
所以,一般而言都是用構建工具,而不是IDE .實際上各種IDE 也是基於各種構建系統,也正是不同的IDE,它們的構建方式不同,所以要讓不同的IDE間能一起開發,於是需要一個統一的構建工具,只是你平時不關注而已..
扯到構建工具, 一般c/c++ 項目用make,或者 premake. 而Java 一般是ant,ivy,gradle,maven,還有直接的shell, 是不是很多沒聽說過呢?
所以,去看開源項目就是長見識的時候了…”
所以,可以這么理解,構建工具是必須的。IDE只是內置了某些構建工具,但是這個工具不一定具有通用性,或者工具的功能不一定強大。為了統一,開發了一套獨立的標准和工具,就是我們所說的構建工具。這些工具,各個IDE也可以使用。
更多構建工具的比較:
http://ensime.org/build_tools/
5 使用Maven進行Java開發
maven 使用 pom.xml 配置文件來進行項目的配置。
所有的庫的最新配置信息,可以從這個網站上查詢到:
https://mvnrepository.com
6 使用Gradle進行Java開發
從上面這么多內容,我們可以知道,從長遠的角度來看,要想項目能夠在更大的范圍內擴展,特別是開源的項目,最好是使用獨立的構建工具來構建項目,那么,Ant、Maven和Gradle應該選哪個呢?
當然是選Gradle了,這個既具有了Ant的靈活性和強大功能,又有Maven的依賴和庫管理,語言groovy又比XML要簡潔和靈活得多。所以,Gradle必然會把這兩個取代,盡管目前,Maven可能還是主流,但不久,應該就是Gradle了。
6.1 Gradle基礎入門
6.2 Eclipse中使用Gradle
6.3 Emacs中的Gradle集成
- 首先,可以創建一個yasnippet:
# -*- mode: snippet -*- # name: build.gradle for springboot # key: springboot # -- buildscript { ext { springBootVersion = '${1:1.5.3.RELEASE}' } repositories { // mavenCentral() maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:$\{springBootVersion\}") // classpath('se.transmode.gradle:gradle-docker:1.2') } } allprojects { repositories { // mavenCentral() maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'org.springframework.boot' group = '${2:com.example}' jar { baseName = '${3:`(file-name-base (directory-file-name (file-name-directory (buffer-file-name))))`}' version = '0.1.0' } sourceCompatibility = ${4:1.8} targetCompatibility = $4 dependencies { compile("org.springframework.boot:spring-boot-starter${5:-web}") // compile("org.springframework.boot:spring-boot-starter-data-jpa") // compile("org.springframework.boot:spring-boot-starter-thymeleaf") // compile("com.h2database:h2") // compile("mysql:mysql-connector-java") testCompile('org.springframework.boot:spring-boot-starter-test') compile("org.springframework.boot:spring-boot-devtools") compile("junit:junit") } eclipse { classpath { containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8' } }
- 然后,就可以這eshell中,執行
gradle bootrun
來進行執行了。
- 自動編譯
其中,有一點非常有趣,就是自動編譯,當我們做了修改之后,自動編譯,這樣,我們就不需要反復的啟動了。這個這Maven中是可以通過devtools來實現的,但是gradle不支持。后來,中google上找了很久,發現gradle有一個–continuous選項是做這個事情的。
gradle -t classes processResources
-t 也可以是 –continuous
7 使用sbt進行Scala/Java開發
7.1 安裝
然后,在sbt的配置文件夾~/.sbt/中添加文件結構示例(需要手動添加文件夾或者文件):
[-] .sbt |--[-] 0.13 | |--[-] plugins | | `----- plugins.sbt | `----- global.sbt `----- repositories
7.2 在sbt中安裝sbt-ensime插件
編輯 ~/.sbt/0.13/plugins/plugins.sbt
,並添加:
addSbtPlugin("org.ensime" % "sbt-ensime" % "1.12.5")
7.3 為sbt支持開發版的ensime
編輯 ~/.sbt/0.13/global.sbt
:
import org.ensime.EnsimeCoursierKeys._ ensimeServerVersion in ThisBuild := "2.0.0-SNAPSHOT"
7.4 在sbt中安裝coursier (有兼容性問題,暫時不用)
7.5 由於大陸連接官方maven庫速度很慢,需要使用國內的鏡像
在~/.sbt/下創建repositories文件,並輸入:
[repositories] local # osc: http://maven.oschina.net/content/groups/public/ # 已經不能使用了,使用阿里雲替代 aliyun:http://maven.aliyun.com/nexus/content/groups/public/ maven-central:http://repo1.maven.org/maven2/ store_2:http://repo2.maven.org/maven2/ uk_mir:http://uk.maven.org/maven2/ store_mir:http://mirrors.ibiblio.org/maven2/ typesafe: http://dl.bintray.com/typesafe/ivy-releases/,[organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly sbt-releases-repo:http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] sbt-plugins-repo:http://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
這樣速度就會快一些。
7.6 Emacs中安裝插件sbt-mode
(use-package sbt-mode :commands sbt-start sbt-command :init (setq sbt:prefer-nested-projects t sbt:scroll-to-bottom-on-output nil sbt:default-command ";compile ;test:compile ;it:compile") :config ;; WORKAROUND: https://github.com/hvesalai/sbt-mode/issues/31 ;; allows using SPACE when in the minibuffer (substitute-key-definition 'minibuffer-complete-word 'self-insert-command minibuffer-local-completion-map) (bind-key "C-c c" 'sbt-command sbt:mode-map) (bind-key "C-c e" 'next-error sbt:mode-map))
7.7 在eshell中鍵入 sbt
,然后,鍵入 ensimeConfig
,創建 .ensime
7.8 在Emacs中執行 ensime
命令就可以啟動后端 ensime server
了
7.9 自己編譯 ensime server
- 獲取源代碼
git clone https://github.com/ensime/ensime-server.git
- 然后,cd 到ensime-server文件夾中
- 運行
sbt ensimeConfig
產生.ensime
文件
- 再執行 compile 進行編譯
8 為什么使用Emacs來開發?
Emacs被稱作是一個操作系統,它可以跨平台,跨語言,只要掌握一個編輯器,就可以覆蓋所有的語言了。有這樣的優勢,實在想不到什么理由不用它來作為開發工具。作為一個編輯器,它擅長的是編輯。對於需要大量解析的工作,它不是不擅長,其實也很擅長,比如CEDET,只是太慢了,對於大型項目,速度始終是個硬傷。
這樣,就需要和其他的工具來進行配合使用。配合使用,就會涉及到交流和溝通的協議。一般的程序,直接把參數,或者字符串傳遞過去,得到返回的字符串就可以了。這是以字符串為傳遞介質。
對於,有些比較復雜的功能,單純的傳遞字符串已經不能滿足需求了。這樣就會有更加復雜的數據結構,來進行傳遞工作。這個數據結構,雙方要能理解,就必須有一個規定,這就是協議。
9 Emacs中的幾款主要Java解釋器或者后端
9.1 jdee(old)
9.2 eclim(eclipse as server)
9.3 meghanada(推薦)
我之前本來試用一下meghanada,結果發現windows下使用不了,就作罷了,轉而使用ensime,但是ensime對scala支持很好,對java很多地方支持得並不好。於是,又硬着頭皮來看meghanada的源代碼,因為既然是java寫的,怎么可能只能在linux運行呢。java本來就是write once, run everywhere的。看完源代碼之后,發現確實是因為文件路徑,linux使用的是"/",而windows是用的"\"導致的,於是提交了代碼,現在linux、Mac和windows下都是可以正常運行的。
9.4 ensime
9.4.1 Introduce
https://coderwall.com/p/avlrna/emacs-ensime-for-your-scala-coding
http://blog.ssanj.net/posts/2011-04-06-ensime-with-emacs.html
構建工具和ensime配置工具,這里要分開來講。一般構建工具和ensime配置插件是使用一套的。但有時,gradle的ensime配置插件過時了,sbt的ensime插件是由官方更新的,所以,總是和ensime配套升級的。所以,用sbt的插件進行配置總是可行的。但是,sbt是一個新的構建系統,所以,在基礎的構建,如對springboot的支持中有時是不穩定的,這時使用Gradle或者Maven會更穩定。
結論:當sbt可以滿足構建需求時,使用sbt是最方便的,既可以配置ensime,又可以構建。當sbt構建出問題時(極少數情況下),這時可以使用Gradle或者Maven來進行構建。
ensime的配置:
9.4.2 sbt(推薦)
http://ensime.org/build_tools/sbt/
- install
~/.sbt/0.13/plugins/plugins.sbt
addSbtPlugin("org.ensime" % "sbt-ensime" % "1.12.14")
sbt ensimeConfig
9.4.3 Maven(配合使用)
http://ensime.org/build_tools/maven/
- install
~/.m2/settings.xml
:
<build> <pluginGroups> <pluginGroup>org.ensime.maven.plugins</pluginGroup> </pluginGroups> </build>
國內加速使用阿里雲鏡像,在<build>節點下添加,這樣速度就會快很多倍了:
<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors>
- use
mvn ensime:generate
9.4.4 Gradle(配合使用)
http://ensime.org/build_tools/gradle/
- install
~/.gradle/init.gradle
apply plugin: AddEnsimePlugin class AddEnsimePlugin implements Plugin<Gradle> { def supportedPlugins = [ 'org.gradle.api.plugins.JavaPlugin', 'org.gradle.api.plugins.ScalaPlugin', 'jp.leafytree.gradle.AndroidScalaPlugin' ] void apply(Gradle gradle) { def added = false gradle.allprojects { project -> project.with { if (parent == null) { buildscript { repositories { mavenLocal() mavenCentral() jcenter() } //if using snapshot, change rootProject.ensime.serverVersion to a snapshot //update this property to the lated ensime-gradle version dependencies { classpath 'net.coacoas.gradle:ensime-gradle:0.3.0-SNAPSHOT' } } } plugins.whenPluginAdded { plugin -> if (!added && supportedPlugins.contains(plugin.class.name)) { rootProject.apply plugin: 'org.ensime.gradle' //update the server version to the latest supported by the ensime-gradle plugin rootProject.ensime.serverVersion = "2.0.0-SNAPSHOT" added = true } } } } } }
- use
gradle ensime
10 Ensime 中常見的操作命令
10.1 sbt ensimeConfig
生成.ensime配置文件
10.2 sbt run
運行整個項目
10.3 sbt core/it:testOnly *JavaCompilerSpec – -z addListener
運行正則表達式匹配的測試用例。