maven in eclipse practices
TRANSCRIPT
2
Eclipse Community Survey 2011
3 http://www.eclipse.org/org/press-release/20110610_survey.php Question 21
Re sp o nse
Pe rce nt
Re sp o nse
Co unt
48.2% 3013.0% 193.5% 224.6% 29
32.2% 2010.8% 5
16.0% 10030.8% 1920.8% 5
16.0% 10011.1% 6911.5% 722.2% 148.7% 54
624
0sk ip p e d q ue stio n
PDE Build
Custom/in-house
None - I don't use a build and release management
Don't know
Other (specify)
a nswe re d q ue stio n
CruiseControl
Hudson/Jenkins
IBM Build Forge
Make
Maven
Microsoft Team Foundation Server (TFS)
Wha t b uild a nd re le a se ma na g e me nt p ro d ucts d o yo u typ ica lly use ? (Se le ct
a ll tha t a p p ly .)
Answe r Op tio ns
Ant
Atlassian Bamboo
Buckminster
Sonatype Software Development Infrastructure Survey
4 http://go.sonatype.com/content/winter2011surveyresults?elq=cc593c0874f44285ba5f61fc9513b5b3
5
http://www.eclipse.org/downloads/compare.php
Java EE w/ Maven: http://www.sonatype.com/people/category/m2eclipse/
BUILD.
6
其實就只有兩件事…
• 編譯 (*.java → *.class)
–把 Java 原始碼編譯成可以被 JVM 載入執行的 Byte Code。
–使用 javac 指令。
• 打包 (*.class → jar/war/ear/rar…)
–產生 Deliverable 或是 Deployable 的檔案。
–使用 jar 指令。
7
透過 IDE 建置、打包
• 簡單到不行
• 可惜同步大家的 IDE 設定難如登天
• 較難自動化執行
8
Apache Ant
• 什麼設定都可以自己來 “Ant is extremely flexible and does not impose coding
conventions or directory layouts to the Java projects which
adopt it as a build tool.”
• 可惜 Build File 幾乎是唯寫的
9
https://bitbucket.org/satyagraha.1956/ant_vis/wiki/Home
http://ant.apache.org/
Top 15 Ant Best Practices
1. Adopt Consistent Style Conventions 2. Put build.xml in the Project Root Directory 3. Prefer a Single Buildfile 4. Provide Good Help 5. Provide a Clean Target 6. Manage Dependencies Using Ant 7. Define and Reuse Paths 8. Define Proper Target Dependencies …
10 http://onjava.com/pub/a/onjava/2003/12/17/ant_bestpractices.Html
以簡御繁,綱舉目張
Convention over Configuration
11
Maven 哲學
• Maven 試著要…
–將專案的 Build 結構套上 Pattern。
–提供清晰明確的方式使用 Best Practice。
–讓大家更容易理解專案,進而提升生產力。
• Convention over Configuration
12
除了 Build 之外…
• Maven 野心不小,還包括…
–文件
–報告
–相依性管理
–版本管理
–發行
–散佈
13
Maven 程式結構
• Maven 主程式
–只包含最基本的設定及程式執行框架。
–大部分的功能都是透過外掛程式來達成。
• 外掛程式
–也是 Maven 的 Artifact。
–提供 Goal 供執行,例如 compiler:compile。
– Goal 是由 Mojo 進行實作。
14
Maven 設定
• 設定內容
–專案間一體適用的資訊。
–不適合公開的資訊。
• 設定檔路徑
–全域設定
• $M2_HOME/conf/settings.xml
–使用者設定
• ${user.home}/.m2/settings.xml
15 http://maven.apache.org/settings.html
POM (Project Object Model)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cht.demo</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
16
Effective POM (1/2)
17
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cht.demo</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Maven Repository Switchboard</name>
<url>http://repo1.maven.org/maven2</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Maven Plugin Repository</name>
<url>http://repo1.maven.org/maven2</url>
</pluginRepository>
</pluginRepositories>
<build>
<sourceDirectory>D:\workspace\demo\src\main\java</sourceDirectory>
<scriptSourceDirectory>D:\workspace\demo\src\main\scripts</scriptSourceDirectory>
<testSourceDirectory>D:\workspace\demo\src\test\java</testSourceDirectory>
<outputDirectory>D:\workspace\demo\target\classes</outputDirectory>
<testOutputDirectory>D:\workspace\demo\target\test-classes</testOutputDirectory>
<resources>
<resource>
<directory>D:\workspace\demo\src\main\resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>D:\workspace\demo\src\test\resources</directory>
</testResource>
</testResources>
<directory>D:\workspace\demo\target</directory>
<finalName>simple-project-1.0-SNAPSHOT</finalName>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
...
...
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>default-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
...
Effective POM (2/2)
18
...
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>default-resources</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
<execution>
<id>default-testResources</id>
<phase>process-test-resources</phase>
<goals>
<goal>testResources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-install</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
...
...
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>2.0.1</version>
<executions>
<execution>
<id>default-site</id>
<phase>site</phase>
<goals>
<goal>site</goal>
</goals>
<configuration>
<outputDirectory>D:\workspace\demo\target\site</outputDirectory>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
<execution>
<id>default-deploy</id>
<phase>site-deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<outputDirectory>D:\workspace\demo\target\site</outputDirectory>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</execution>
</executions>
<configuration>
<outputDirectory>D:\workspace\demo\target\site</outputDirectory>
<reportPlugins>
<reportPlugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</reportPlugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<outputDirectory>D:\workspace\demo\target\site</outputDirectory>
</reporting>
</project>
POM 繼承
• Maven 內部定義了 Super POM
–所有的 POM 都自動繼承 Super POM
• 可以指定 parent 繼承其他 POM 設定
19
<project xmlns=http://maven.apache.org/POM/4.0.0
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.cht.demo</groupId>
<artifactId>demo-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>demo</artifactId>
</project>
Maven Build Lifecycle
• 多個階段 (Phase) 組成生命週期 (Lifecycle)
20
階段 說明
validate 檢查專案資訊是否正確。
compile 編譯原始碼。 (單元測試程式碼是在另一個階段: test-compile 裡做的)
test 使用合適的單元測試框架測試編譯後的原始碼。
package 依照指定的格式 (預設是 jar, 也可以指定 war, ear 等) 打包編譯出的檔案,不包含單元測試程式碼。
integration-test 將打包檔部署到整合測試環境進行測試。
verify 驗證測試及分析結果是否符合品質要求
install 安裝到本機檔案庫,供其他專案使用。
deploy 複製檔案到遠端檔案庫,供其他使用者與其他專案使用。
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
Maven Dependency 機制
• Transitive Dependency
21
Maven Dependency Scope
• 相依的函式庫 Scope 千萬不要搞錯
22
Scope 類型 說明
compile 預設值,整個專案的生命週期都會將這個函式庫加入到 classpath 中,包含測試與打包 (輸出成 WAR 或 EAR)。
provided 代表 JRE 或是 Container 等執行環境將提供這個函式庫。 例如開發 Web 專案的時候就應該將 Servlet API 設成 provided,因為 Web Server 提供了這個函式庫。
runtime 執行或測試時需要使用,但是編譯時用不到的函式庫。
test 只有編譯及執行測試程式時才用得到的函式庫,例如 JUint。 (m2eclipse 在執行 src/main/java 下的程式時會自動將這一類的函式庫排除)
system 跟 provided 差不多,不過必需要手動指定函式庫的路徑,所以別的環境可能無法正常編譯,應該盡可能使用 Repository 上的函式庫。
http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
Maven Dependency 管理
• 版本衝突
– Maven 使用 “nearest definition” 進行版本解析。
• 善用 <exclusions> 排除不必要的函式庫。
–例如將 commons-logging 排除,以 jcl-over-slf4j 代替。
• 必要時指定 <optional>
–不要強迫使用者加入所有你使用到的函式庫。
23
Maven Remote Repository
• 存放函式庫的大倉庫
– Artifact 們都依 G, A, V 參數分門別類放好。
–分成 RELEASE 跟 SNAPSHOT 兩類。
– Maven 預設使用 Maven Central Repository
• http://repo1.maven.org/maven2/
• Sonatype Nexus
–目前最熱門的 Maven Repository Manager 軟體。
24 http://maven.apache.org/guides/introduction/introduction-to-repositories.html
Maven Local Repository
• Artifact 的本地端快取
–避免做什麼事情都要透過網路連線。
– install 的目的地。
• 預設路徑
– ${user.home}/.m2/repository
–或在 settings.xml 裡透過 <localRepository> 設定路徑。
25 http://maven.apache.org/guides/introduction/introduction-to-repositories.html
百無一用是書生
Go Fighting!
26 http://zh.wikipedia.org/wiki/File:Normandy7.jpg
Eclipse Maven 整合
• m2e
– http://eclipse.org/m2e/
• 安裝 m2e
– Update Site • http://download.eclipse.org/technology/m2e/milestones/1.0
• 安裝 m2eclipse-wtp
– Update Site • https://repository.sonatype.org/content/sites/forge-sites/m2eclipse-wtp/0.13.0/S/
27
設定下載 Source 及 Javadoc
28
設定 Repository 索引
29
先處戰地而待敵者佚
Keep Things DRY
30
DRY
• Don't Repeat Yourself (DRY)
–嘴巴毒一點的人說: Duplication is Evil (DIE)
• 大師說:
“Every piece of knowledge must have a single,
unambiguous, authoritative representation within a
system.”
31
XML Schema 編譯成 JAXB 2 物件
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.7.4</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<schemaIncludes>
<include>META-INF/resources/sys-domain.xsd</include>
</schemaIncludes>
<generatePackage>com.sys.domain</generatePackage>
<args>
<arg>-no-header</arg>
</args>
</configuration>
</execution>
</executions>
</plugin>
32
JAX-WS 介面產生 WSDL
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>1.12</version>
<executions>
<execution>
<goals>
<goal>wsgen</goal>
</goals>
<configuration>
<sei>com.cht.sys.DemoWebService</sei>
<!-- 實際在 Server 裡運作時並不需要 WSDL -->
<genWsdl>true</genWsdl>
</configuration>
</execution>
</executions>
</plugin>
33
編譯 JasperReports 報表檔 (1/2)
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jasperreports-maven-plugin</artifactId>
<version>1.0-beta-2</version>
<executions>
<execution>
<goals>
<goal>compile-reports</goal>
</goals>
<configuration>
<compiler>
net.sf.jasperreports.compilers.JRGroovyCompiler
</compiler>
<!-- 統一放到將來 jar 的 META-INF\jasperreports 目錄下 -->
<outputDirectory>
${project.build.outputDirectory}\META-INF\jasperreports
</outputDirectory>
</configration>
</execution>
</executions>
...
34
編譯 JasperReports 報表檔 (2/2)
...
<dependencies>
<dependency>
<!-- 宣告 JasperReports 函式庫,才能載到正確版本的 XML 驗證資料 -->
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<!-- 我們 Report 裡 Expression 的語法預設都是使用 Groovy -->
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<!-- 如果不加這個 Depdendency,這個古董外掛程式就會跑不起來 -->
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
</dependencies>
</plugin>
35
WET
• We Edit Terribly, Tumultuously, Tempestuously, Tenaciously, Too much, Timidly, Tortuously, Terrifiedly...
• We Enjoy Typing!
• We also Enjoy Troubleshooting!
36 http://c2.com/cgi/wiki?DontRepeatYourself
工欲善其事,必先利其器
Handy Eclipse Tips & Plugins
37
“Navigator” View
• 很懷念檔案總管?
38
Eclipse Runner 外掛程式
• 你一天按幾次 “Run As…” ?
39
• 官方網站: http://code.google.com/p/eclipserunnerplugin/
• Update Site : http://eclipserunnerplugin.googlecode.com/svn/trunk/EclipseRunnerSite/
EasyShell 外掛程式
• 你一天開幾次檔案總管找專案裡的檔案?
40
• 官方網站: http://pluginbox.sourceforge.net/plugins.html
• Update Site : http://pluginbox.sourceforge.net/
學海無涯苦作舟
41
相關電子書
• Maven By Example – http://www.sonatype.com/index.php/Support/Books/Maven-By-
Example
• Maven: The Complete Reference – http://www.sonatype.com/index.php/Support/Books/Maven-The-
Complete-Reference
• Developing with Eclipse & Maven – http://www.sonatype.com/index.php/Support/Books/Developing-
with-Eclipse-Maven
42
Maven 也不是萬能的
• Maven 的限制
– http://community.jboss.org/wiki/MavenProblems
• 為什麼 Hibernate 使用 Gradle 建置
– http://community.jboss.org/wiki/GradleWhy
43
44