maven 的依赖范围

  1. compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译、测试、运行三种classpath都有效。典型的例子是spring-core,在编译、测试和运行的时候都需要使用该依赖。
  2. test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效,比如 JUnit。
  3. provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试class-path有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入一遍。
  4. runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行class-path有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动。
  5. system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。
  6. import

    约定优于配置

    Maven 提倡 “约定优于配置”(Convention Over Configuration),源码目录为 src/main/java,编译输出目录为 target/classes/,打包方式为 jar,包输出目录为 target/ 。

超级 pom

对于 maven3,超级 pom 在 $MAVEN_HOME/lib/maven-modal-builder-x.x.x.jar 中的 org/apache/maven/modal/pom-4.0.0.xml 路径下。

  1. <!-- START SNIPPET: superpom -->
  2. <project>
  3. <modelVersion>4.0.0</modelVersion>
  4. <!-- 关于仓库的定义 -->
  5. <repositories>
  6. <repository>
  7. <id>central</id>
  8. <name>Central Repository</name>
  9. <url>https://repo.maven.apache.org/maven2</url>
  10. <layout>default</layout>
  11. <snapshots>
  12. <enabled>false</enabled>
  13. </snapshots>
  14. </repository>
  15. </repositories>
  16. <!-- 插件仓库的定义 -->
  17. <pluginRepositories>
  18. <pluginRepository>
  19. <id>central</id>
  20. <name>Central Repository</name>
  21. <url>https://repo.maven.apache.org/maven2</url>
  22. <layout>default</layout>
  23. <snapshots>
  24. <enabled>false</enabled>
  25. </snapshots>
  26. <releases>
  27. <updatePolicy>never</updatePolicy>
  28. </releases>
  29. </pluginRepository>
  30. </pluginRepositories>
  31. <!-- 项目结构的定义 -->
  32. <build>
  33. <directory>${project.basedir}/target</directory>
  34. <outputDirectory>${project.build.directory}/classes</outputDirectory>
  35. <finalName>${project.artifactId}-${project.version}</finalName>
  36. <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
  37. <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
  38. <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
  39. <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
  40. <resources>
  41. <resource>
  42. <directory>${project.basedir}/src/main/resources</directory>
  43. </resource>
  44. </resources>
  45. <testResources>
  46. <testResource>
  47. <directory>${project.basedir}/src/test/resources</directory>
  48. </testResource>
  49. </testResources>
  50. <!-- 定义插件的版本 -->
  51. <pluginManagement>
  52. <!-- NOTE: These plugins will be removed from future versions of the super POM -->
  53. <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
  54. <plugins>
  55. <plugin>
  56. <artifactId>maven-antrun-plugin</artifactId>
  57. <version>1.3</version>
  58. </plugin>
  59. <plugin>
  60. <artifactId>maven-assembly-plugin</artifactId>
  61. <version>2.2-beta-5</version>
  62. </plugin>
  63. <plugin>
  64. <artifactId>maven-dependency-plugin</artifactId>
  65. <version>2.8</version>
  66. </plugin>
  67. <plugin>
  68. <artifactId>maven-release-plugin</artifactId>
  69. <version>2.5.3</version>
  70. </plugin>
  71. </plugins>
  72. </pluginManagement>
  73. </build>
  74. <reporting>
  75. <outputDirectory>${project.build.directory}/site</outputDirectory>
  76. </reporting>
  77. <profiles>
  78. <!-- NOTE: The release profile will be removed from future versions of the super POM -->
  79. <profile>
  80. <id>release-profile</id>
  81. <activation>
  82. <property>
  83. <name>performRelease</name>
  84. <value>true</value>
  85. </property>
  86. </activation>
  87. <build>
  88. <plugins>
  89. <plugin>
  90. <inherited>true</inherited>
  91. <artifactId>maven-source-plugin</artifactId>
  92. <executions>
  93. <execution>
  94. <id>attach-sources</id>
  95. <goals>
  96. <goal>jar-no-fork</goal>
  97. </goals>
  98. </execution>
  99. </executions>
  100. </plugin>
  101. <plugin>
  102. <!--inherited标识该插件配置可以被子 POM 继承-->
  103. <inherited>true</inherited>
  104. <artifactId>maven-javadoc-plugin</artifactId>
  105. <executions>
  106. <execution>
  107. <id>attach-javadocs</id>
  108. <goals>
  109. <goal>jar</goal>
  110. </goals>
  111. </execution>
  112. </executions>
  113. </plugin>
  114. <plugin>
  115. <inherited>true</inherited>
  116. <artifactId>maven-deploy-plugin</artifactId>
  117. <configuration>
  118. <updateReleaseInfo>true</updateReleaseInfo>
  119. </configuration>
  120. </plugin>
  121. </plugins>
  122. </build>
  123. </profile>
  124. </profiles>
  125. </project>
  126. <!-- END SNIPPET: superpom -->

在 performRelease 为 true 的情况下,会激活 release-profile,会打包源码和 javadoc,比如:
mvn clean install -DperformRelease=true

maven 有一个 Effective POM 的概念,它表示一个合并整个继承结构所有信息的 POM。假设项目 A 继承自项目 B,B又隐式继承自超级 POM,那么 A 的 Effective POM 就包含了所有 A、B 以及超级 POM 的配置。
mvn help:effective-pom

仓库搜索服务

Nexus 是当前最流行的开源 Maven 仓库管理软件,https://repository.sonatype.org
https://mvnrepository.com

maven 目录

conf:该目录包含了一个非常重要的文件settings.xml。直接修改该文件,就能在机器上全局地定制Maven的行为。一般情况下,我们更偏向于复制该文件至~/.m2/目录下(~表示用户目录),然后修改该文件,在用户范围定制Maven的行为。

推荐使用用户范围的settings.xml,主要是为了避免无意识地影响到系统中的其他用户。
除了影响范围这一因素,配置用户范围settings.xml文件还便于Maven升级。直接修改conf目录下的settings.xml会导致Maven升级不便,每次升级到新版本的Maven,都需要复制settings.xml文件。如果使用~/.m2目录下的settings.xml,就不会影响到Maven安装文件,升级时就不需要触动settings.xml文件。

maven-archetype-plugin 生成项目的骨架

mvn clean install 使用 install 插件将文件复制到本地仓库中。

maven 配置

  1. <!-- localRepository
  2. | The path to the local repository maven will use to store artifacts.
  3. |
  4. | Default: ${user.home}/.m2/repository
  5. -->
  6. <localRepository>/path/to/local/repo</localRepository>
  7. <!--配置访问远程仓库的用户名和密码-->
  8. <servers>
  9. <server>
  10. <id>deploymentRepo</id>
  11. <username>repouser</username>
  12. <password>repopwd</password>
  13. </server>
  14. </servers>
  15. <!-- 配置仓库镜像,所有访问中央仓库的,都访问到该地址 -->
  16. <!-- mirrorOf 还可以配置 * ,表示该配置是所有 maven 仓库的镜像 -->
  17. <mirrors>
  18. <mirror>
  19. <id>nexus-aliyun</id>
  20. <mirrorOf>central</mirrorOf>
  21. <name>Nexus aliyun</name>
  22. <url>https://maven.aliyun.com/repository/public</url>
  23. </mirror>
  24. </mirrors>
  25. <profiles>
  26. <profile>
  27. <id>aliyun-profile</id>
  28. <repositories>
  29. <repository>
  30. <id>aliyunrepo</id>
  31. <url>https://maven.aliyun.com/repository/public</url>
  32. </repository>
  33. </repositories>
  34. </profile>
  35. </profiles>
  36. <activeProfiles>
  37. <!-- <activeProfile>pic</activeProfile> -->
  38. <activeProfile>aliyun-profile</activeProfile>
  39. </activeProfiles>

repositories 仓库地址也可以配置在项目的 pom 中,但是 server 的用户名和密码需要配置在 settings.xml 中。

  1. <project>
  2. <repositories>
  3. <repository>
  4. <id>...</id>
  5. <url>...</url>
  6. </repository>
  7. </repositories>
  8. </project

部署至远程仓库,仓库的用户名和密码配置在 settings.xml 中,mvn clean deploy 命令部署:

  1. <project>
  2. <distributionManagement>
  3. <repository>
  4. <id>project-release</id>
  5. <name>project release repository</name>
  6. <url>....</url>
  7. </repository>
  8. <snapshotRepository>
  9. <id>snapshot-release</id>
  10. <name>project snapshot release</name>
  11. <url>....</url>
  12. </snapshotRepository>
  13. </distributionManagement>
  14. </project

快照版本发布后,maven 会在快照版本后面加上时间戳。其他依赖该快照版本构建的时候,就会拉取最新的快照依赖。但如果依赖的是稳定版本,如果本地有的话,就不会重新拉取。

插件

插件仓库

Maven 超级 POM 中插件仓库的配置:

  1. <!-- 插件仓库的定义 -->
  2. <pluginRepositories>
  3. <pluginRepository>
  4. <id>central</id>
  5. <name>Central Repository</name>
  6. <url>https://repo.maven.apache.org/maven2</url>
  7. <layout>default</layout>
  8. <snapshots>
  9. <enabled>false</enabled>
  10. </snapshots>
  11. <releases>
  12. <updatePolicy>never</updatePolicy>
  13. </releases>
  14. </pluginRepository>
  15. </pluginRepositories>

插件默认的 groupId 是 org.apache.maven.pulgins
在用户没有提供插件版本的情况下,maven 会自动解析插件版本。
可以在 settings.xml 中配置自己的插件仓库元数据:

  1. <settings>
  2. <pluginGruops>
  3. <pluginGroup>com.your.plugins</pluginGroup>
  4. </pluginGroups>
  5. </settings>

查看插件的使用

  1. # 也可以不加 -Ddetail,就只返回概要信息
  2. $ mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin:3.2.1 -Ddetail
  3. $ mvn help:describe -Dplugin=org.springframework.boot:spring-boot-maven-plugin -Ddetail
  4. # 直接只看具体的目标
  5. $ mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin -Dgoal=compile
  6. # 可以使用插件目标前缀替换坐标(Goal prefix)
  7. $ mvn help:describe -Dplugin=compiler -Dgoal=compile
  8. #Call mvn surefire:help -Ddetail=true -Dgoal=<goal-name> to display parameter details.

image.png
help:describe 的完整格式是 mvn org.apache.maven.plugins:maven-help-plugin:2.1:describe -Dplugin=compiler

help 是 maven-help-plugin 的目标前缀,dependency 是 maven-dependency-plugin 的前缀,使用它们就可以找到对应的 artifactId。
然后再根据默认的 groupId 和 version 就可以获取到对应的插件。

mvn help:system该命令会打印出所有的Java系统属性和环境变量,这些信息对我们日常的编程工作很有帮助。

生命周期

Maven 的生命周期都是由插件来完成。
Maven 有三套相互独立的生命周期,分别是 clean、default、site
image.png
image.png

Maven 的生命周期和插件相互绑定。
clean 生命周期阶段与插件目标的绑定关系:

生命周期阶段 插件目标
pre-clean maven-clean-plugin:clean
clean
post-clean

default 生命周期还有很多其他阶段,默认它们没有绑定任何插件,因此也没有任何实际行为。
冒号前面是插件前缀,冒号后面是该插件的目标。
default 生命周期的内置插件绑定关系及具体任务(打包类型:jar):

生命周期阶段 插件目标 执行任务
process-resources maven-resources-plugin:resources 复制主资源文件至主输出目录
compile maven-compile-plugin:compile 编译主代码至输出目录
process-test-resources maven-resources-plugin:testResources 复制测试资源文件至测试输出目录
test-compile maven-compile-plugin:testCompile 编译测试代码至测试输出目录
test maven-surefire-plugin:test 执行测试用例
package maven-jar-plugin:jar 创建项目 jar 包
install maven-install-plugin:install 将项目输出构件安装到本地仓库
deploy maven-deploy-plugin:deploy 将项目输出构件部署到远程仓库

自定义绑定生命周期

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-maven-plugin</artifactId>
  6. </plugin>
  7. <plugin>
  8. <!--如果是 maven 的官方插件,groupId 可以省略 -->
  9. <groupId>org.apache.maven.plugins</groupId>
  10. <artifactId>maven-source-plugin</artifactId>
  11. <version>3.2.1</version>
  12. <executions>
  13. <execution>
  14. <id>attach-sources</id>
  15. <!-- 可以省略 phase,因为插件的每个目标都是默认绑定的生命周期 -->
  16. <phase>verify</phase>
  17. <goals>
  18. <goal>jar-no-fork</goal>
  19. </goals>
  20. </execution>
  21. </executions>
  22. </plugin>
  23. </plugins>
  24. </build>

很多插件目标的参数都支持从命令行配置,用户可以在 maven 命令中使用 -D 参数,来配置插件目标的参数。
比如 maven-surefire-plugin 提供了一个 maven.test.skip 参数,当为 true 的时候,可以跳过执行测试:
image.png
mvn install -Dmaven.test.skip=true 或者 mvn install -DskipTests
在 POM 中对插件进行全局配置,这样所有基于该插件的任务,都会使用这些配置。

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-compiler-plugin</artifactId>
  4. <version>3.10.0</version>
  5. <configuration>
  6. <source>1.8</source>
  7. <target>1.8</target>
  8. </configuration>
  9. </plugin>

还可以为某个插件任务配置特定的参数。
image.png
image.png

模块聚合及继承

聚合

为了方便快速构建项目。

  1. <modelVersion>4.0.0</modelVersion>
  2. <groupId>com.xiaocan</groupId>
  3. <artifactId>account-aggregator</artifactId>
  4. <!-- 注意聚合多个模块的pom配置 -->
  5. <packaging>pom</packaging>
  6. <version>1.0-SNAPSHOT</version>
  7. <modules>
  8. <module>account-email</module>
  9. <module>account-persist</module>
  10. <module>account-parent</module>
  11. </modules>

继承

为了消除重复的配置。

  1. <modelVersion>4.0.0</modelVersion>
  2. <groupId>com.xiaocan</groupId>
  3. <artifactId>account-parent</artifactId>
  4. <packaging>pom</packaging>
  5. <version>1.0-SNAPSHOT</version>
  6. <properties>
  7. <java.version>1.8</java.version>
  8. <spring.version>5.3</spring.version>
  9. </properties>
  10. <!--在 dependencyManagement 元素下的依赖生命不会引入实际的依赖-->
  11. <dependencyManagement>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework</groupId>
  15. <artifactId>spring-core</artifactId>
  16. <version>${spring.version}</version>
  17. </dependency>
  18. <dependency>
  19. <groupId></groupId>
  20. <artifactId></artifactId>
  21. </dependency>
  22. </dependencies>
  23. </dependencyManagement>
  24. <!-- 使用 pluginManagement 插件管理 -->
  25. <build>
  26. <pluginManagement>
  27. <plugins>
  28. <plugin>
  29. <groupId>org.apache.maven.plugins</groupId>
  30. <artifactId>maven-source-plugin</artifactId>
  31. <version>3.2.1</version>
  32. <executions>
  33. <execution>
  34. <id>attach-sources</id>
  35. <phase>verify</phase>
  36. <goals>
  37. <goal>jar-no-fork</goal>
  38. </goals>
  39. </execution>
  40. </executions>
  41. </plugin>
  42. </plugins>
  43. </pluginManagement>
  44. </build>

其他模块继承它:

  1. <parent>
  2. <groupId>com.xiaocan</groupId>
  3. <artifactId>account-parent</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. <!-- 如果 account-parent 位于它的上一层目录,可以省略 -->
  6. <relativePath>../account-parent/pom.xml</relativePath>
  7. </parent>
  8. <!--groupId 和 version 继承自父模块-->
  9. <artifactId>account-email</artifactId>
  10. <name>Account Email</name>
  11. <dependencies>
  12. <dependency>
  13. <groupId>org.springframework</groupId>
  14. <artifactId>spring-core</artifactId>
  15. <!-- 不用声明版本号,继承自父模块-->
  16. </dependency>
  17. </dependencies>
  18. <!-- 子模块配置 plugin -->
  19. <plugins>
  20. <plugin>
  21. <groupId>org.apache.maven.plugins</groupId>
  22. <artifactId>maven-source-plugin</artifactId>
  23. </plugin>
  24. </plugins>

import 的依赖范围,在 dependencyManagement 元素下才有效果,使用该范围的的依赖通常指向一个 POM,作用是将目标 POM 的 dependencyManagement 配置导入到当前 POM 的 dependencyManagement 元素中。

  1. <dependencyManagement>
  2. <dependencies>
  3. <dependency>
  4. <groupId>com.xiaocan</groupId>
  5. <artifactId>account-parent</artifactId>
  6. <version>1.0-SNAPSHOT</version>
  7. <type>pom</type>
  8. <scope>import</scope>
  9. </dependency>
  10. </dependencies>
  11. </dependencyManagement>

聚合和继承目的不同,但是可以组合起来使用,即在一个 pom 中既声明 module,也使用 dependencyManagement 管理依赖。

构建指定模块

正常情况下,模块的构建顺序是:
account aggregator
account parent
account email
account persist

-am,—also-mark 同时构建所列模块的依赖模块
-amd,-also-mak-dependents 同时构建依赖于所列模块的模块
-pl,—projects 构建指定的模块,模块间用逗号分隔
-rf,—resume-from 从指定的模块恢复反应堆

  1. $ mvn clean install -pl account-email,account-persist
  2. account email
  3. account persist
  4. $ mvn clean install -pl account-email -am
  5. account parent
  6. account email
  7. $ mvn clean install -pl account-parent -amd
  8. account parent
  9. account email
  10. account persist
  11. $ mvn clean install -rf account-email
  12. account email
  13. account persist
  14. $ mvn clean install -pl account-parent -amd -rf account-email
  15. account email
  16. account persist

maven-surefire-plugin

测试范围

surefire 的 test 目标会自动执行测试源码路径(src/test/java)下所有符合一组命令模式的测试类:

  • */Test.java ,任何子目录下所有命名以 Test 开头的 java 类。
  • */Test.java,任何子目录下所有命名以 Test 以为的 java 类。
  • */TestCase.java
    1. <plugin>
    2. <groupId>org.apache.maven.plugins</groupId>
    3. <artifactId>maven-surefire-plugin</artifactId>
    4. <version>3.0.0-M7</version>
    5. <configuration>
    6. <includes>
    7. <include>**/*Tests.java</include>
    8. </includes>
    9. <excludes>
    10. <exclude>**/TempDaoTest.java</exclude>
    11. </excludes>
    12. </configuration>
    13. </plugin>

    跳过测试

    mvn package -DskipTests
    或使用 xml 配置
    1. <plugin>
    2. <groupId>org.apache.maven.plugins</groupId>
    3. <artifactId>maven-surefire-plugin</artifactId>
    4. <version>3.0.0-M7</version>
    5. <configuration>
    6. <skipTests>true</skipTests>
    7. </configuration>
    8. </plugin>

同时跳过测试编译和测试运行:mvn package -Dmaven.test.skip=true (maven-compiler-plugin 的 testCompile 和 maven-surefire-plugin 的 test 都提供了参数 skip 来跳过,这个参数就是 maven.test.skip)
使用 xml 配置:

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-surefire-plugin</artifactId>
  4. <version>3.0.0-M7</version>
  5. <configuration>
  6. <skip>true</skip>
  7. </configuration>
  8. </plugin>
  9. <plugin>
  10. <groupId>org.apache.maven.plugins</groupId>
  11. <artifactId>maven-compiler-plugin</artifactId>
  12. <version>3.10.1</version>
  13. <configuration>
  14. <skip>true</skip>
  15. </configuration>
  16. </plugin>

指定要运行的测试用例:
mvn test -Dtest=RandomGeneratorTest
mvn test -Dtest=Random*Test
mvn test -Dtest=RandomGeneratorTest,AccountCaptchaServiceTest

测试报告

maven-surefire-plugin 会在项目的 target/surefire-reports 目录下生成两种格式的报告:

  • 简单文本格式;
  • 与 JUnit 兼容的 xml 格式

使用 cobertura-maven-plugin 插件获取测试覆盖率
mvn cobertura:cobertura
在 target/site/cobertura/ 下的 index.html 文件就是测试覆盖率报告。

重用测试代码

默认的打包没有测试代码。可以通过 maven-jar-plugin 配置将测试类打包:

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-jar-plugin</artifactId>
  4. <version>3.2.2</version>
  5. <executions>
  6. <execution>
  7. <goals>
  8. <goal>test-jar</goal>
  9. </goals>
  10. </execution>
  11. </executions>
  12. </plugin>

maven-jar-plugin 有两个目标,分别是 jar 和 test-jar,前者通过 Maven 的内置绑定在 default 生命周期的 package 阶段运行,对项目主代码进行打包,后者没有内置绑定,需要显式声明该目标来打包测试代码。
其他项目依赖该测试代码:

  1. <dependency>
  2. <groupId>***</groupId>
  3. <artifactId>account-captcha</artifactId>
  4. <version>1.1.17</version>
  5. <type>test-jar</type>
  6. <scope>test</scope>
  7. </dependency>

使用 maven 构建 web 应用

一个典型的 war 文件目录结构:
META-INF 包含了一些打包元数据信息。
image.png

除了 src/main/java 和 src/test/java 目录结构外,web 项目还有一个 web 资源目录,默认位置在 src/main/webapp 目录下。
image.png

finalName 配置,用来标识项目生成主构件的名称。超级 pom 中的默认配置是:
<finalName>${project.artifactId}-${project.version}</finalName>
为了方便 war 的访问,可以指定一个简单的名称:
<finalName>account</finalName>
maven-war-plugin 打包 war 包。

生成项目站点

maven-site-plugin
mvn site 就能直接生成一个最简单的站点。
(现在已经过时了吧, 没这样用了。)
里面包含了丰富的项目信息,是由 maven-project-info-plugin 插件生成的,该插件的配置内置在 maven-site-plugin 中。生成的信息报告有:
image.png

自动版本发布

使用 maven-release-plugin 插件
image.png
项目发布的时候,默认会生成 -source.jar 和 -javadoc.jar ,也就是超级 pom 中的 performRelease 被激活。
(书中以 svn 为例介绍自动化版本发布,使用 git 的话,自己搜索如何配置。)

maven 的属性使用

6类 maven 属性

image.png
image.png
image.png

使用 pom 属性配置依赖:
表示依赖的 groupId 和 verison 与当前模块一致。

  1. <dependency>
  2. <groupId>${project.groupId}</groupId>
  3. <artifactId>account-email</artifactId>
  4. <version>${project.version}</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>${project.groupId}</groupId>
  8. <artifactId>account-persist</artifactId>
  9. <version>${project.version}</version>
  10. </dependency>

使用 maven 属性配置插件:

  1. <plugin>
  2. <groupId>org.apache.maven.plugins</groupId>
  3. <artifactId>maven-surefire-plugin</artifactId>
  4. <version>3.0.0-M7</version>
  5. <configuration>
  6. <reportsDirectory>
  7. ${project.build.directory}/test-reports
  8. </reportsDirectory>
  9. </configuration>
  10. </plugin>

profile 使用

profile 配置:

  1. <profiles>
  2. <profile>
  3. <id>dev</id>
  4. <properties>
  5. <db.driver>com.mysql.jdbc.Driver</db.driver>
  6. <db.url>jdbc:mysql://localhost:3306/dev</db.url>
  7. <db.username>dev</db.username>
  8. <db.password>dev-pwd</db.password>
  9. </properties>
  10. </profile>
  11. </profiles>

那在配置文件中该怎么使用这些配置呢?

  1. database.jdbc.driverClass=${db.driver}
  2. database.jdbc.connectionURL=${db.url}
  3. database.jdbc.usernmae=${db.username}
  4. database.jdbc.pasword=${db.password}

使用 maven-resources-plugin ,通过下面的配置就能够解析资源文件中的 Maven 属性,即开启资源过滤:

<build>    
  <resources>
    <resource>
      <directory>${project.basedir}/src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
  <testResources>
    <testResource>
      <directory>${project.basedir}/src/test/resources</directory>
      <filtering>true</filtering>
    </testResource>
  </testResources>
</build>

在命令行中使用 -P 指定激活的 profile:
mvn clean install -Pdev

如果希望某个 profile 默认一直处于激活状态,就可以配置 settings.xml 中的 activeProfiles 元素。

<activeProfiles>
  <!-- <activeProfile>pic</activeProfile> -->
  <activeProfile>aliyun-profile</activeProfile>
</activeProfiles>

系统属性激活:

<profile>
  <id>env-dev</id>

  <!--存在target-env属性,并且为dev时,该profile被激活-->
  <activation>
    <property>
      <name>target-env</name>
      <value>dev</value>
    </property>
  </activation>

  <properties>
    <tomcatPath>/path/to/tomcat/instance</tomcatPath>
  </properties>
</profile>

还可以从命令行设置 target-env 的值:mvn clean install -Dtarget-env=prod

根据操作系统环境来激活 profile:
family 包括 Windwos、UNIX 和 Mac 等,其他几项可以通过查看环境中的系统属性 os.name、os.arch、os.version 获得。

<activation>
  <os>
    <name>windows7</name>
    <family>Windows</family>
    <version></version>
    <arch>x86</arch>
  </os>
</activation>

根据文件是否存在激活:

<activation>
  <file>
    <exists>xxx</exists>
    <missing>yyy</missing>
  </file>
</activation>

默认激活:
如果 pom 中有任何一个 profile 通过以上其他方式被激活了,所有的默认激活配置都会失效。

<activation>
  <activeByDefault>true</activeByDefault>
</activation>

怎么知道哪些 profile 被激活了呢?
mvn help:active-profiles
列出当前所有的 profile:mvn help:all-profiles

在 profile 中激活集成测试:
TestNG 中可以将测试分组成单元测试和集成测试:
@Test(groups={"unit"}
@Test(groups={"integration"}
可以配置不同的 profile 来激活:

<project>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M7</version>
        <configuration>
          <groups>unit</groups>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <profiles>
    <profile>
      <id>full</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M7</version>
            <configuration>
              <groups>unit,integration</groups>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>

这样,正常情况下只跑单元测试,只有激活了 full 才会跑集成测试。
在持续集成服务器上,可以配置两个触发器。其中一个,当有代码提交时,只跑单元测试。另外一个,每天凌晨定时跑集成测试。

maven 插件

maven-javadoc-plugin

生成项目的 Javadoc

maven-checkstyle-plugin

设置项目的编码规范

maven-pmd-plugin

Java源代码分析工具,能够寻找代码中的问题,包括潜在的 bug、无用代码、可优化代码、重复代码以及过于复杂的表达式等。

maven-changelog-plugin

基于版本控制系统就最近的变更记录生成三份变更报告:

  • change log,基于提交的变更报告
  • developer activity,基于作者的变更报告
  • file activity,基于文件的变更报告

需要配置 scm。

<reporting>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-changelog-plugin</artifactId>
      <version>2.3</version>
      <configuration>
        <type>range</type>
        <range>60</range>
      </configuration>
    </plugin>
  </plugins>
</reporting>

编写 maven 插件

mvn archetype:generate
然后选择:maven-archetype-plugin

Archetype 使用

maven-archetype-plugin
mvn archetype:help -Ddetail=true
使用交互方式生成:mvn archetype:generate
使用命令行生成:

$ mvn archetype:generate -B \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-quickstart \
    -DarchetypeVersion=1.1 \
    -DgroupId=foo \
    -DartifactId=bar \
    -Dversion=1.0-SNAPSHOT \
    -Dpackage=foobar

常用 Archetype:
maven-archetype-quickstart,默认
maven-archetype-webapp
image.png

创建自己的 Archetype

Archetype Catalog

当用户不指定 Archetype 坐标的方式使用 maven-archetype-plugin 的时候,会得到一个 Archetype 列表供选择,这个列表的信息来源于一个名为 archetype-catalog.xml 的文件。
该文件的来源有:

  • internal,maven-archetype-plugin 内置的 archetype catalog
  • local,指向用户本地,位置为 ~/.m2/archetype-catalog.xml
  • remote,指向 maven 中央仓库的 archetype catalog
  • file://…,用户可以指定本机任何位置的 archetype-catalog.xml 文件
  • http://…

mvn archetype:generate -DarchetypeCatalog=file:///tmp/archetype-catlog.xml

生成本地仓库的 archetype catalog
mvn archetype:crawl可以用它来便利本地 maven 仓库的内容并自动生成 archetype-catalog.xml 文件。
mvn archetype:crawl -Drepository=D:/java/repository -Dcatalog=C:/archetype-catalog.xml