Maven使用手册

什么是Maven

Maven首先是一种最佳实践的模式,通过提供一些标准来提高效率。Maven本质是项目管理的工具,它能提供:

  • Builds 构建管理
  • Reporting 报告管理
  • Denpendencies 依赖管理
  • SCMs 软件配置管理
  • Releases 发版管理
  • Distribution 分发管理

如何创建Maven工程

创建Maven工程会使用到原型(Archetype)机制,原型机制可以快速创建模板化的工程。
以下命令使用Maven自带的原型创建工程:

mvn -B archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4

执行结束后会创建工程目录my-app,目录中还包含pom.xml文件:

<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.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
 
  <name>my-app</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>
 
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
 
  <build>
    <pluginManagement>
       ... lots of helpful plugins
    </pluginManagement>
  </build>
</project>

pom.xml 是项目对象模型(POM Project Object Model),其包含了项目的所有信息:

  • project:pom.xml的最外层元素
  • modelVersion: pom使用的对象模型的版本
  • groupId:创建项目的组织机构,通常会是组织机构的域名,例如org.apache.maven.plugins
  • artifactid: 项目生成的成果物的名称,通常会是jar文件,通常生成文件的命名规则为-. ,例如myapp-1.0.jar
  • version: 项目生成的成果物的版本
  • name: Maven项目的展示名称,这个名称通常是显示在文档中的
  • url: 项目的网站地址
  • properties: 定义可以在POM中任意位置使用的变量
  • dependencies: 项目依赖
  • build: 定义项目目录结构和管理插件

上面创建的项目会有以下目录结构:

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

可以看到,根据原型创建的项目包含pom.xml,应用源代码目录,测试源代码目录,这也是Maven工程的标准布局,如果是手工创建工程,也要依据此机构进行创建,这是Maven的约定。

编译应用源代码

进入到包含pom.xml的目录,执行以下命令:

mvn compile

会得到以下输出:

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to <dir>/my-app/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.899 s
[INFO] Finished at: 2020-07-12T11:31:54+01:00
[INFO] ---------------------------------------------------------------------

第一次执行这个命令,Maven需要下载所有的插件以及项目中的依赖。
编译后的文件存储于${basedir}/target/classes,这是Maven的另一个标准约定

如何编译测试源代码和运行单元测试

编译单元测试用例源代码并执行

mvn test

命令之后输出如下:

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to <dir>/my-app/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in com.mycompany.app.AppTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.881 s
[INFO] Finished at: 2020-07-12T12:00:33+01:00
[INFO] ---------------------------------------------------------------------

在输出内容中可以看到:

  • Maven下载了更多的依赖,这些是执行测试所需要的的依赖和插件
  • 在编译执行测试之前,Maven会先编译主代码

如果只是想编译测试源代码而不执行,可以用以下命令:

mvn test-compile

如何创建JAR并安装到本地资源库

创建JAR执行以下命令:

mvn package

生成的JAR文件在目录${basedir}/target

如果想将刚刚生成的JAR安装进行本地资源库(默认路径${user.home}/.m2/repository),执行以下命令:

mvn install

输出信息为:

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
...
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app ---
...
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in com.mycompany.app.AppTest
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] 
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ my-app ---
[INFO] Building jar: <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ my-app ---
[INFO] Installing <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar to <local-repository>/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.jar
[INFO] Installing <dir>/my-app/pom.xml to <local-repository>/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.678 s
[INFO] Finished at: 2020-07-12T12:04:45+01:00
[INFO] ------------------------------------------------------------------------

注意执行测试的surefire插件是依照命名约定来定位测试文件的,默认的规则为:

  • **/*Test.java
  • */Test.java
  • **/*TestCase.java

默认排除的文件命名:

  • **/Abstract*Test.java
  • **/Abstract*TestCase.java

目前已经介绍了Maven工程的典型流程,包括创建、编译、测试、打包、安装,这些步骤也是大部分Maven项目主要使用的,这些所有步骤都由POM来驱动,如果使用Ant来实现这些功能,则脚本文件将会复杂很多。

Maven有很多有用的开箱即用的插件,这里我们列举一个插件,它也是Maven的优点之一:创建工程描述文档站点:

mvn site

还有大量的独立目标,例如:

mvn clean

该命令会清空target目录,通常在构建工程之前执行,这样能保证工程文件都是最新的。

什么是快照版本

在pom.xml的版本标签中包含-SNAPSHOT,就是快照版本

<project xmlns="http://maven.apache.org/POM/4.0.0"
  ...
  <groupId>...</groupId>
  <artifactId>my-app</artifactId>
  ...
  <version>1.0-SNAPSHOT</version>
  <name>Maven Quick Start Archetype</name>
  ...

快照版本是指开发分支上的最新代码,不保证代码是稳定的,只要发布版本才会保证是不变且稳定的。
换言之,快照版本就是在发布版本之前的开发版本。
在版本释放的过程中,版本号会去掉-SNAPSHOT后缀,x.y-SNAPSHOT 变为 x.y,版本释放也会使快照版本号增加为x.(y+1)-SNAPSHOT,如1.0-SNAPSHOT 释放为 1.0,最新的开发版本为1.1-SNAPSHOT

如何使用插件

如果要自定义Maven工程的构建时,就需要使用插件或者配置插件
例如,我们要设置Java编译器为JDK5,以下是POM的例子:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.3</version>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>

在Maven中插件就像一个依赖,从某些方面看插件就是依赖,插件会自动下载并运行,用户也可以指定插件的版本,默认的版本采用最新
configuration 元素会将配置的要素传递给compiler 插件的所有目标,在上面的例子中,compiler 插件已经作为构建流程的一部分,这个配置仅仅是改变了一些信息。也可以为流程增加新的目标。

如何为JAR添加资源

添加资源不需要更改POM,Maven是依赖标准目录布局,也就是说将资源文件按照约定放置在指定目录中,Maven就会将资源打包进JAR中
以下的目录机构中展示了资源文件的位置 ${basedir}/src/main/resources ,放置在其中的任何目录或者文件都会被打包进JAR

my-app
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- app
    |   |               `-- App.java
    |   `-- resources
    |       `-- META-INF
    |           `-- application.properties
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

在上面的例子中工程中有一个目录META-INF,其中包含application.properties,如果将这个工程的打包JAR文件解压,你会看到以下文件结构:

|-- META-INF
|   |-- MANIFEST.MF
|   |-- application.properties
|   `-- maven
|       `-- com.mycompany.app
|           `-- my-app
|               |-- pom.properties
|               `-- pom.xml
`-- com
    `-- mycompany
        `-- app
            `-- App.class

${basedir}/src/main/resources 目录中的内容会在JAR的根目录下,application.properties 文件在 META-INF目录中,也可以看到还有其他的文件META-INF/MANIFEST.MF、pom.xml、pom.properties,这些是Maven生成JAR文件的标准描述文件,你也可以自定义manifest信息。pom.xml和pom.properties也被打包进JAR文件了,这样你可以在有需求的场景去使用,一个最简单的场景就是查看JAR文件的版本,pom.properties如下:

#Generated by Maven
#Tue Oct 04 15:43:21 GMT-05:00 2005
version=1.0-SNAPSHOT
groupId=com.mycompany.app
artifactId=my-app

测试资源的约定路径为${basedir}/src/test/resources

my-app
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- app
    |   |               `-- App.java
    |   `-- resources
    |       `-- META-INF
    |           |-- application.properties
    `-- test
        |-- java
        |   `-- com
        |       `-- mycompany
        |           `-- app
        |               `-- AppTest.java
        `-- resources
            `-- test.properties

在测试用例中,你可以用以下代码获取资源:

// Retrieve resource
InputStream is = getClass().getResourceAsStream( "/test.properties" );
 
// Do something with the resource

如何过滤资源文件

有时资源文件中会包含一些只在构建期间使用的信息,为了实现这个需求,Maven中支持在资源文件变量引用的语法${},这个属性可以定义在pom.xml,setting.xml,扩展的属性文件以及环境变量
Maven过滤资源,只需要将在pom.xml中filtering 属性值设置为true

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
 
  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
</project>

上面build中的resources属性默认是可以缺省的,因为Maven已经定了目录等默认值,如果指定filtering为true,则需要显示的指定

在引用pom.xml中定义的变量时,可以直接使用xml便签名引用标签内的值,pom的跟别名为project,所以 p r o j e c t . n a m e 为 工 程 名 , {project.name}为工程名, project.name{project.version}为工程版本, p r o j e c t . b u i l d . f i n a l N a m e 为 打 包 文 件 名 , 等 等 。 注 意 p o m 中 的 元 素 都 由 默 认 值 , 所 以 可 以 不 必 显 示 的 定 义 。 同 样 的 , 用 户 s e t t i n g . x m l 可 以 通 过 s e t t i n g s . 的 方 式 引 用 , 例 如 {project.build.finalName}为打包文件名,等等。注意pom中的元素都由默认值,所以可以不必显示的定义。同样的,用户setting.xml可以通过settings.的方式引用,例如 project.build.finalNamepomsetting.xmlsettings.{settings.localRepository}为本地资源库的路径
我们src/main/resources目录下的application.properties增加以下内容:

application.name=${project.name}
application.version=${project.version}

执行以下命令(该命令为Maven复制和过滤资源文件的过程)

mvn process-resources

target/classes目录下的application.properties会被过滤为以下:

application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT

如何使用外部依赖

pom.xml中dependencies 元素列举了工程所需的所有依赖

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

对于任何一个外部依赖,都需要定义至少4项信息:groupId,artifactId,version,scope,groupId,artifactId,version是依赖的工程属性,scope指定了当前工程如何使用这个依赖,它的值可以是compile, test, and runtime
有了这些信息,工程就能引用依赖,那么这些依赖是从哪里来的?
Maven首先会检索本地资源库,默认路径是${user.home}/.m2/repository,在之前的章节里我们使用mvn install在本地资源库安装了my-app-1.0-SNAPSHOT.jar, 那么其他工程就可以引用了

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-other-app</artifactId>
  ...
  <dependencies>
    ...
    <dependency>
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-app</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

那么在其他地方构建的依赖怎么引用?他们如何下载到我本地资源库?如果引用的依赖本地资源库不存在,Maven会从远程资源库下载至本地资源库,你会发现在首次使用maven构建工程时会下载很多东西,下载的东西通常是构建工程使用的插件,默认的远程资源库为https://repo.maven.apache.org/maven2/.,你也可以设置自定义的远程仓库。

例如我们想添加记录日志的依赖,在Maven中央仓库中的目录为 /maven2/log4j/log4j,目录中有文件maven-metadata.xml,其内容为:

<metadata>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.1.3</version>
  <versioning>
    <versions>
      <version>1.1.3</version>
      <version>1.2.4</version>
      <version>1.2.5</version>
      <version>1.2.6</version>
      <version>1.2.7</version>
      <version>1.2.8</version>
      <version>1.2.11</version>
      <version>1.2.9</version>
      <version>1.2.12</version>
    </versions>
  </versioning>
</metadata>

通过这个文件我们可以看到groupId 是log4j,artifactId是log4j,我们看到有很多版本可以选择,我们使用最新版本1.2.12。此外,我们可以看到每个版本的log4j都由一个单独的目录,目录内部包含jar文件以及pom.xml以及另外的 maven-metadata.xml,其中的md5文件包含了这些文件的hash码,你可以用来认证这个库或者识别出正在使用的版本。

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

敲入命令mvn compile,可以看到maven开始下载log4j

如何发布自己的jar到远程仓库

想要发布jar到外部的资源库,需要在pom.xml中配置资源库的url以及在settings.xml.配置资源库的身份认证信息

下面的例子中使用了 scp 和 username/password 身份认证:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>Maven Quick Start Archetype</name>
  <url>http://maven.apache.org</url>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.codehaus.plexus</groupId>
      <artifactId>plexus-utils</artifactId>
      <version>1.0.4</version>
    </dependency>
  </dependencies>
 
  <build>
    <filters>
      <filter>src/main/filters/filters.properties</filter>
    </filters>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
  </build>
  <!--
   |
   |
   |
   -->
  <distributionManagement>
    <repository>
      <id>mycompany-repository</id>
      <name>MyCompany Repository</name>
      <url>scp://repository.mycompany.com/repository/maven2</url>
    </repository>
  </distributionManagement>
</project>

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
  ...
  <servers>
    <server>
      <id>mycompany-repository</id>
      <username>jvanzyl</username>
      <!-- Default value is ~/.ssh/id_dsa -->
      <privateKey>/path/to/identity</privateKey> (default is ~/.ssh/id_dsa)
      <passphrase>my_key_passphrase</passphrase>
    </server>
  </servers>
  ...
</settings>

如何创建其他类型的工程

使用以下命令创建一个新的工程

mvn archetype:generate \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-webapp \
    -DgroupId=com.mycompany.app \
    -DartifactId=my-webapp

生成的pom.xml如下:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-webapp</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
 
  <build>
    <finalName>my-webapp</finalName>
  </build>
</project>

标签定义为生成war,使用以下名称构建工程,会构建出arget/my-webapp.war

mvn package

如何同时构建多个工程

Maven可以处理多模块,首先根据之前构建的两个工程的父目录中创建pom.xml,目录结构如下:

+- pom.xml
+- my-app
| +- pom.xml
| +- src
|   +- main
|     +- java
+- my-webapp
| +- pom.xml
| +- src
|   +- main
|     +- webapp

pom.xml的内容为:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
 
  <modules>
    <module>my-app</module>
    <module>my-webapp</module>
  </modules>
</project>

在my-webapp/pom.xml中添加对my-app JAR的依赖

...
  <dependencies>
    <dependency>
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    ...
  </dependencies>

在子模块的pom.xml中分别添加一下元素

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  ...

在最顶层的目录运行:

mvn verify

在my-webapp/target/my-webapp.war中生成了war文件,并且包含了JAR

$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/
 222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
 215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
 123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties
  52 Fri Jun 24 10:59:56 EST 2005 index.jsp
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值