maven in eclipse practices

44
Apache Maven Eclipse 整合開發實務研討 中華電信研究所 黃培棠 [email protected] 2011/07/01

Upload: pei-tang-huang

Post on 16-Apr-2017

11.026 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Maven in eclipse practices

Apache Maven 與 Eclipse 整合開發實務研討

中華電信研究所 黃培棠

[email protected]

2011/07/01

Page 2: Maven in eclipse practices

2

Page 3: Maven in eclipse practices

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

Page 4: Maven in eclipse practices

Sonatype Software Development Infrastructure Survey

4 http://go.sonatype.com/content/winter2011surveyresults?elq=cc593c0874f44285ba5f61fc9513b5b3

Page 5: Maven in eclipse practices

5

http://www.eclipse.org/downloads/compare.php

Java EE w/ Maven: http://www.sonatype.com/people/category/m2eclipse/

Page 6: Maven in eclipse practices

BUILD.

6

Page 7: Maven in eclipse practices

其實就只有兩件事…

• 編譯 (*.java → *.class)

–把 Java 原始碼編譯成可以被 JVM 載入執行的 Byte Code。

–使用 javac 指令。

• 打包 (*.class → jar/war/ear/rar…)

–產生 Deliverable 或是 Deployable 的檔案。

–使用 jar 指令。

7

Page 8: Maven in eclipse practices

透過 IDE 建置、打包

• 簡單到不行

• 可惜同步大家的 IDE 設定難如登天

• 較難自動化執行

8

Page 9: Maven in eclipse practices

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/

Page 10: Maven in eclipse practices

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

Page 11: Maven in eclipse practices

以簡御繁,綱舉目張

Convention over Configuration

11

Page 12: Maven in eclipse practices

Maven 哲學

• Maven 試著要…

–將專案的 Build 結構套上 Pattern。

–提供清晰明確的方式使用 Best Practice。

–讓大家更容易理解專案,進而提升生產力。

• Convention over Configuration

12

Page 13: Maven in eclipse practices

除了 Build 之外…

• Maven 野心不小,還包括…

–文件

–報告

–相依性管理

–版本管理

–發行

–散佈

13

Page 14: Maven in eclipse practices

Maven 程式結構

• Maven 主程式

–只包含最基本的設定及程式執行框架。

–大部分的功能都是透過外掛程式來達成。

• 外掛程式

–也是 Maven 的 Artifact。

–提供 Goal 供執行,例如 compiler:compile。

– Goal 是由 Mojo 進行實作。

14

Page 15: Maven in eclipse practices

Maven 設定

• 設定內容

–專案間一體適用的資訊。

–不適合公開的資訊。

• 設定檔路徑

–全域設定

• $M2_HOME/conf/settings.xml

–使用者設定

• ${user.home}/.m2/settings.xml

15 http://maven.apache.org/settings.html

Page 16: Maven in eclipse practices

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

Page 17: Maven in eclipse practices

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>

...

Page 18: Maven in eclipse practices

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>

Page 19: Maven in eclipse practices

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>

Page 20: Maven in eclipse practices

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

Page 21: Maven in eclipse practices

Maven Dependency 機制

• Transitive Dependency

21

Page 22: Maven in eclipse practices

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

Page 23: Maven in eclipse practices

Maven Dependency 管理

• 版本衝突

– Maven 使用 “nearest definition” 進行版本解析。

• 善用 <exclusions> 排除不必要的函式庫。

–例如將 commons-logging 排除,以 jcl-over-slf4j 代替。

• 必要時指定 <optional>

–不要強迫使用者加入所有你使用到的函式庫。

23

Page 24: Maven in eclipse practices

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

Page 25: Maven in eclipse practices

Maven Local Repository

• Artifact 的本地端快取

–避免做什麼事情都要透過網路連線。

– install 的目的地。

• 預設路徑

– ${user.home}/.m2/repository

–或在 settings.xml 裡透過 <localRepository> 設定路徑。

25 http://maven.apache.org/guides/introduction/introduction-to-repositories.html

Page 26: Maven in eclipse practices

百無一用是書生

Go Fighting!

26 http://zh.wikipedia.org/wiki/File:Normandy7.jpg

Page 28: Maven in eclipse practices

設定下載 Source 及 Javadoc

28

Page 29: Maven in eclipse practices

設定 Repository 索引

29

Page 30: Maven in eclipse practices

先處戰地而待敵者佚

Keep Things DRY

30

Page 31: Maven in eclipse practices

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

Page 32: Maven in eclipse practices

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

Page 33: Maven in eclipse practices

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

Page 34: Maven in eclipse practices

編譯 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

Page 35: Maven in eclipse practices

編譯 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

Page 36: Maven in eclipse practices

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

Page 37: Maven in eclipse practices

工欲善其事,必先利其器

Handy Eclipse Tips & Plugins

37

Page 38: Maven in eclipse practices

“Navigator” View

• 很懷念檔案總管?

38

Page 39: Maven in eclipse practices

Eclipse Runner 外掛程式

• 你一天按幾次 “Run As…” ?

39

• 官方網站: http://code.google.com/p/eclipserunnerplugin/

• Update Site : http://eclipserunnerplugin.googlecode.com/svn/trunk/EclipseRunnerSite/

Page 40: Maven in eclipse practices

EasyShell 外掛程式

• 你一天開幾次檔案總管找專案裡的檔案?

40

• 官方網站: http://pluginbox.sourceforge.net/plugins.html

• Update Site : http://pluginbox.sourceforge.net/

Page 41: Maven in eclipse practices

學海無涯苦作舟

41

Page 42: Maven in eclipse practices

相關電子書

• 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

Page 43: Maven in eclipse practices

Maven 也不是萬能的

• Maven 的限制

– http://community.jboss.org/wiki/MavenProblems

• 為什麼 Hibernate 使用 Gradle 建置

– http://community.jboss.org/wiki/GradleWhy

43

Page 44: Maven in eclipse practices

44