關於靈活的構建css
一個優秀的構建系統必須足夠靈活,它應該可以讓項目在不一樣的環境下都能成功地構建。java
例如,典型的項目都會有開發環境、測試環境和產品環境,這些環境的數據庫配置不盡相同,那麼項目構建的時候就須要可以識別所在的環境並使用正確的配置mysql
還有一種常見的狀況是,項目開發了大量的集成測試,這些測試運行起來很是耗時,不適合在每次構建項目的時候都運行,所以須要一種手段能讓咱們在特定的時候才激活這些集成測試,Maven爲了支持構建的靈活性,內置了三大特性,即屬性、Profile和資源過濾web
Maven屬性spring
使用Maven屬性歸類依賴sql
<properties>數據庫
<springframework.version>2.5.6</springframework.version>apache
</properties>app
<dependencies>webapp
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
...
</dependencies>
這多是最多見的使用Maven屬性的方式,經過<properties>元素用戶能夠自定義一個或多個Maven屬性,而後再POM的其餘地方使用${屬性名稱}的方式引用該屬性,這種作法的最大意義在於消除重複
Maven的6類屬性
1、內置屬性,主要有兩個經常使用內置屬性——${basedir} 表示項目根目錄,即包含pom.xml文件的目錄;${version} 表示項目版本
2、POM屬性,用戶可使用該類屬性引用POM文件中對應元素的值,例如:
${project.artifactId}就對應了<project> <artifactId>元素的值,經常使用的POM屬性包括:
n ${project.build.sourceDirectory}:項目的主源碼目錄,默認爲src/main/java/
n ${project.build.testSourceDirectory}:項目的測試源碼目錄,默認爲src/test/java/
n ${project.build.directory}:項目構建輸出目錄,默認爲target/
n ${project.outputDirectory}:項目主代碼編譯輸出目錄,默認爲target/classes/
n ${project.testOutputDirectory}:項目測試代碼編譯輸出目錄,默認爲target/testclasses/
n ${project.groupId}:項目的groupId
n ${project.artifactId}:項目的artifactId
n ${project.version}:項目的version,與${version}等價
n ${project.build.finalName}:項目打包輸出文件的名稱,默認爲${project.artifactId}-
${project.version}
這些屬性都對應了一個POM元素,它們中一些屬性的默認值都是在超級POM中定義的
3、自定義屬性,用戶能夠在POM的<properties>元素下自定義Maven屬性
<project>
...
<properties>
<my.prop>hello</my.prop>
</properties>
...
</project>
而後在POM中其餘地方使用${my.prop}的時候會被替換成hello
4、Settings屬性,與POM屬性同理,用戶使用以settings.開頭的屬性引用settings.xml文件中xml元素的值,如經常使用的${settings.localRepository}指向用戶本地倉庫的地址
5、Java系統屬性,全部Java系統屬性均可以使用Maven屬性引用,例如${user.home}指向了用戶目錄,用戶可使用mvn help:system查看全部的Java系統屬性
6、環境變量屬性,全部環境變量均可以使用以env.開頭的Maven屬性引用。例如${env.JAVA_HOME}指代了JAVA_HOME環境變量的值。用戶可使用mvn help:system查看全部的環境變量
使用POM屬性配置依賴
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>account-email</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>account-persist</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
使用Maven屬性配置插件
修改測試報告目錄
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<reportsDirectory>
${project.build.directory}/test-reports
</reportsDirectory>
</configuration>
</plugin>
構建環境的差別,考慮一下這種狀況
在不一樣的環境中,項目的源碼應該使用不一樣的方式進行構建,最多見的就是數據庫配置了
例如在開發的過程當中,有些項目會在src/main/resources/目錄下放置帶有以下內容的數據庫配置文件:
database.jdbc.driverClass=com.mysql.jdbc.Driver
database.jdbc.connectionURL=jdbc:mysql://localhost:3306/test
database.jdbc.username=dev
database.jdbc.password=dev-pwd
這本沒什麼問題,可當測試人員想要構建項目產品並進行測試的時候,他們每每須要使用不一樣的數據庫,這時的數據庫配置文件多是這樣的:
database.jdbc.driverClass=com.mysql.jdbc.Driver
database.jdbc.connectionURL=jdbc:mysql://10.1.0.56:3306/test
database.jdbc.username=test
database.jdbc.password=test-pwd
鏈接數據庫的URL、用戶名和密碼都發生了變化,相似地,當項目被髮布到產品環境的時候,所使用的數據庫配置又是另一套了。這個時候,比較原始的作法是,使用與開發環境同樣的構建,而後再測試或者發佈產品以前再手動更改這些配置。這是可行的,也是比較常見的,但確定不是最好的方法。本書已經不止一次強調,手動每每就意味着低效和錯誤,所以須要找到一種方法,使它可以自動對構建環境的差別
Maven的答案是針對不一樣的環境生成不一樣的構件。也就是說,在構建項目的過程當中,Maven就已經將這種差別處理好了
資源過濾
爲了應對環境的變化,首先須要使用Maven屬性將這些將會發生變化的部分提取出來。
將上面的配置,用Maven屬性取代
database.jdbc.driverClass=${db.driver}
database.jdbc.connectionURL=${db.url}
database.jdbc.username=${db.username}
database.jdbc.password=${db.password}
這裏定義了4個Maven屬性:db.driver、db.url、db.username和db.password
使用一個額外的profile包裹自定義Maven屬性
針對開發環境的數據庫配置
<profiles>
<profile>
<id>dev</id>
<properties>
<db.driver> com.mysql.jdbc.Driver </db.driver>
<db.url> jdbc:mysql://localhost:3306/test </db.url>
<db.username> dev </db.username>
<db.password> dev-pwd </db.password>
</properties>
</profile>
</profiles>
對上面這些配置進行解釋
Maven屬性定義與直接在POM的properties元素下定義沒什麼區別,只是使用了一個id爲dev的profile,其目的是將開發環境下的配置與其餘環境區分開
那麼,有了屬性定義,配置文件中也使用了這些屬性,一切OK了嗎?
仍是不行,Maven屬性默認只有在POM中才會被解析。也就是說,${db.username}放到POM中會變成test,可是若是放到src/main/resources目錄下的文件中,構建的時候它將仍然仍是${db.username},所以,須要讓Maven解析資源文件中的Maven屬性
資源文件的處理實際上是maven-resources-plugin作的事情,它默認的行爲只是將項目主資源文件複製到主代碼編譯輸出目錄中,將測試資源文件複製到測試代碼編譯輸出目錄中,不過只要經過一些簡單的POM配置,該插件就可以解析資源文件中的Maven屬性,即開啓資源過程
Maven默認的主資源目錄和測試資源目錄
默認狀況下是定義在超級POM中,要爲資源目錄開啓過濾,只要在此基礎上添加一行filtering配置便可
爲主資源目錄開啓過濾
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
爲測試資源目錄開啓過濾
<resources>
<resource>
<directory>${project.basedir}/src/test/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
配置多個資源目錄
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<resources>
<resource>
<directory>src/main/sql</directory>
<filtering>false</filtering>
</resource>
</resources>
其中src/main/resources開啓了過濾,而src/main/sql沒有啓用過濾
執行mvn clean install -Pdev命令
mvn的-P參數表示在命令行激活一個profile,這裏激活了id爲dev的profile。構建完成後,輸出目錄中的數據庫配置就是開發環境的配置了
爲了構建差別的jdbc配置,咱們作了哪些配置?
1、數據庫配置的變化部分提取成了Maven屬性
2、在POM的profile中定義了這些屬性的值
3、爲資源目錄開啓了屬性過濾
4、最後須要在命令行激活profile,Maven就可以在構建項目的時候使用profile中屬性值替換數據庫配置文件中的屬性引用
激活profile,Maven支持不少種激活Profile的方式
1、命令行激活
使用mvn命令行參數-P加上profile的id來激活profile,多個id之間以逗號分隔
使用命令激活dev-x和dev-y兩個profile
mvn clean install -Pdev-x,dev-y
2、settings文件顯式激活
若是用戶但願某個profile默認一直處於激活狀態,就能夠配置settings.xml文件的activeProfiles元素,表示其配置的profile對於全部項目都處於激活狀態
settings文件顯式激活profile
<settings>
...
<activeProfiles>
<activeProfile>dev-x</activeProfile>
</activeProfiles>
...
</settings>
3、系統屬性激活
配置當某系統屬性存在的時候,自動激活profile
當系統屬性test存在時,激活此profile
<profiles>
<profile>
<activation>
<property>
<name>test</name>
</propety>
</activation>
...
</profile>
</profiles>
當系統屬性test存在,且值等於x的時候激活profile
<profiles>
<profile>
<activation>
<property>
<name>test</name>
<value>x</value>
</propety>
</activation>
...
</profile>
</profiles>
上面的配置,不要忘了在命令行聲明系統屬性
mvn clean install -Dtest=x
所以,這其實也是一種從命令行激活profile的方法,並且多個profile徹底可使用同一個系統屬性來激活
4、操做系統環境激活
Profile還能夠自動根據操做系統環境激活,若是構建在不一樣的操做系統有差別,用戶徹底能夠將這些差別寫進profile,而後配置它們自動基於操做系統激活
基於操做系統環境激活profile
<profiles>
<profile>
<activation>
<os>
<name>Windows XP</name>
<family>Windows</family>
<arch>x86</arch>
<version>5.1.2600</version>
</os>
</activation>
...
</profile>
</profiles>
這裏family的值包括Windows、UNIX和Mac等,而其餘幾項name、arch、version,用戶能夠經過查看環境中的系統屬性os.name、os.arch、os.version得到
5、文件存在與否激活
Maven可以根據項目中某個文件存在與否來決定是否激活profile
基於文件存在與否激活profile
<profiles>
<profile>
<activation>
<file>
<missing>x.properties</missing>
<exists>y.properties</ exists >
</file>
</activation>
...
</profile>
</profiles>
6、默認激活
用戶能夠在定義profile的時候指定其默認激活
默認激活profile
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
...
</profile>
</profiles>
使用activeByDefault元素用戶能夠指定profile自動激活,不過須要注意的是,若是POM中有任何一個profile經過以上其餘任意一種方式被激活了,全部的默認激活配置都會失效
項目中有不少profile,用戶怎麼知道哪一個激活了?
maven-help-plugin提供一個目標幫助用戶瞭解當前激活的profile
mvn help:active-profiles
maven-help-plugin還有另一個目標用來列出當前全部的profile
mvn help:all-profiles
那麼,profile的種類有哪些?或者說在哪裏能夠配置profile?
1、pom.xml,很顯然,pom.xml中聲明的profile值對當前項目有效
2、用戶settings.xml:用戶目錄下.m2/settings.xml中的profile對本機上該用戶全部的Maven項目有效
3、全局settings.xml:Maven安裝目錄下conf/settings.xml中的profile對本機上全部的Maven項目有效
4、profiles.xml(Maven 2):還能夠在項目根目錄下使用一個額外的profiles.xml文件來聲明profile,不過該特性已經在Maven 3中被移除。建議用戶將這類profile移到settings.xml中
POM中的profile可以使用的元素
由於profile能夠伴隨pom.xml一塊兒存在,因此可使用不少POM元素
<project>
<repositories></repositories>
<pluginRepositories></pluginRepositories>
<distributationManagement></distributationManagement>
<dependencyManagement></dependencyManagement>
<modules></modules>
<properties></properties>
<reporting></reporting>
<build>
<plugins></plugins>
<defaultGoal></defaultGoal>
<resources></resources>
<testResources></testResources>
<finalName></finalName>
</build>
</project>
POM外部的profile可以使用的元素
因爲沒法保證外部的profile隨着特定的pom.xml一塊兒分發,因此外部的profile可以使用的元素不多
<project>
<repositories></respositories>
<pluginRepositories></pluginRepositories>
<properties></properties>
</project>
外部的profile僅僅能影響項目的倉庫和Maven屬性
Web資源過濾
在Web項目中,資源文件一樣位於src/main/resources目錄下,它們經處理後會位於WAR包的WEB-INF/classes目錄下,這也是Java代碼編譯打包後的目錄。也就是說,這類資源文件在打包事後位於應用程序的classpath中。
Web項目中海油另一類資源文件,默認它們的源碼位置src/main/webapp/目錄,經打包後位於WAR包的根目錄。
例如,一個Web項目的css源碼文件在src/main/webapp/css/目錄,項目打包後能夠在WAR包的css/目錄下找到對應的css文件。這一類資源文件稱做web資源文件,它們在打包事後不位於應用程序的classpath中
與通常的資源文件同樣,web資源文件默認不會被過濾。開啓通常資源文件的過濾也不會影響到web資源文件
不過有的時候,咱們可能但願在構建項目的時候,爲不一樣的客戶使用不同的資源文件(例如客戶的logo圖片不一樣,或者css主題不一樣)。這時能夠在web資源文件中使用Maven屬性,例如用 ${client.logo}表示客戶的logo圖片,用${client.theme}表示客戶的css主題。而後使用profile分別定義這些Maven屬性的值
針對不一樣客戶web資源的profile
<profiles>
<profile>
<id>client-a</id>
<properties>
<client.logo>a.jpg</client.logo>
<client.theme>red</client.theme>
</properties>
</profile>
<profile>
<id>client-b</id>
<properties>
<client.logo>b.jpg</client.logo>
<client.theme>blue</client.theme>
</properties>
</profile>
</profiles>
爲web資源目錄src/main/webapp/開啓過濾
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
<configuration>
<resource>
<filtering>true</filtering>
<directory>src/main/webapp</directory>
<includes>
<include>**/*.css</include>
<include>**/*.js</include>
</includes>
</resource>
</configuration>
</plugin>
對上述配置進行解釋
1、web資源目錄src/main/webapp(這也是默認的web資源目錄)
2、配置filtering開啓過濾,而且使用includes指定要過濾的文件,這裏是全部的css和js文件
3、激活某個profile進行構建,mvn clean install -Pclient-a,告訴web資源文件使用logo圖片a.jpg,使用css主題red
在profile中激活集成測試?
什麼是集成測試?
如何在Maven中使用TestNG?