分类:maven| 发布时间:2018-04-19 23:58:00
Maven 是一个跨平台的项目管理工具。主要服务于基于 Java 平台的项目构建、依赖管理和项目信息管理。
在 Ubuntu 平台下安装 maven 相当简单,键入以下命令即可:
% sudo apt-get install maven
下面的内容假设你已经安装好 Maven 并且配置好 Java 了。
就像 Make 的 Makefile、Ant 的 build.xml 一样,Maven 项目的核心是 pom.xml。POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建、声明项目依赖,等等。现在先为 hello World 项目编写一个最简单的的 pom.xml。
<?xml version="1.0" encoding="UTF-8"?>
<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</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Hello World Project</name>
</project>
代码的第一行是 XML 头,指定了该 xml 文档的版本和编码方式。紧接着是 project 元素,project 是所有 pom.xml 的根元素,它还声明了一些 POM 相关的命名空间以及 xsd 元素。 modelVersion 指定了当前 POM 模型的版本,对于 Maven 3 来说它只能是 4.0.0。 这段代码最重要的是包含 groupI、artifactId 和 version 的三行。这三个元素定义了一个项目的基本坐标,在 Maven 的世界,任何的 jar、pom 或者 war 都是基于这些基本的坐标进行区分的。 groupId 定义了项目属于那个组,这个组往往和项目所在的组织或公司存在关联。 artifactId 定义了当前 Maven 项目在组中唯一的 ID。 version 指定项目当前版本。 SNAPSHOT 表示该项目还在开发中,是不稳定的版本。
主代码和测试代码不同,项目的主代码会被打包进最终的构件中(如 jar),而测试代码只在运行测试时用到,不会被打包。 默认情况下,Maven 假设项目主代码位于 src/main/java 目录,我们遵循 Maven 的约定,创建该目录,然后在该目录下创建文件 com/mycompany/helloworld/HelloWorld.java,内容如下:
package com.mycompany.helloworld;
public class HelloWorld
{
public String sayHello()
{
return "Hello Maven";
}
public static void main(String[] args)
{
System.out.print(new HelloWorld().sayHello());
}
}
代码编写完毕后,使用 Maven 进行编译,在项目根目录下运行命令 mvn compile 得到如下输出:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Hello World Project 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.3:resources (default-resources) @ hello-world2 ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/ubuntu/src/hello/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.0.2:compile (default-compile) @ hello-world2 ---
[INFO] Nothing to compile - all classes are up to date
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.367s
[INFO] Finished at: Thu Apr 19 20:54:28 CST 2018
[INFO] Final Memory: 13M/481M
[INFO] ------------------------------------------------------------------------
项目的住代码会被编译进 target/classes 目录下。
在 Java 世界中,JUnit 是事实上的单元测试标准。要使用 JUnit,首先需要为项目添加一个 JUnit 依赖,修改项目的 POM。
<?xml version="1.0" encoding="UTF-8"?>
<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</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Maven Hello World Project</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
上面的 scop 限定了该依赖只对测试代码有效。 Maven 项目默认测试代码在 src/test/java。创建该目录,并将如下测试代码放进这个目录:
package com.mycompany.helloworld;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class HelloWorldTest
{
@Test
public void testSayHello()
{
HelloWorld helloWorld = new HelloWorld();
String result = helloWorld.sayHello();
assertEquals("Hello Maven", result);
}
}
使用 mvn test 命令编译并运行测试代码,很不幸,报错了:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Hello World Project 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.3:resources (default-resources) @ hello-world ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/ubuntu/src/hello/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.0.2:compile (default-compile) @ hello-world ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.3:testResources (default-testResources) @ hello-world ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/ubuntu/src/hello/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.0.2:testCompile (default-testCompile) @ hello-world ---
[INFO] Compiling 1 source file to /home/ubuntu/src/hello/target/test-classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.591s
[INFO] Finished at: Thu Apr 19 21:25:18 CST 2018
[INFO] Final Memory: 14M/481M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.0.2:testCompile (default-testCompile) on project hello-world: Compilation failure: Compilation failure:
[ERROR] /home/ubuntu/src/hello/src/test/java/HelloWorldTest.java:[3,7] 错误: -source 1.3 中不支持静态导入声明
[ERROR]
[ERROR] (请使用 -source 5 或更高版本以启用静态导入声明)
[ERROR] /home/ubuntu/src/hello/src/test/java/HelloWorldTest.java:[8,2] 错误: -source 1.3 中不支持注释
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
由于历史原因 Maven 的核心插件之一 compiler 插件默认只支持编译 Java 1.3,因此需要配置该插件使其支持我们当前版本的 Java。
修改 pom.xml,添加如下配置:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
...
再次执行 mvn test,可以正常执行并通过测试了。
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.mycompany.helloworld.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.049 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.144s
[INFO] Finished at: Thu Apr 19 21:30:26 CST 2018
[INFO] Final Memory: 16M/354M
[INFO] ------------------------------------------------------------------------
可以通过 mvn package 将项目打成一个 jar 包:
...
[INFO]
[INFO] --- maven-jar-plugin:2.2:jar (default-jar) @ hello-world ---
[INFO] Building jar: /home/ubuntu/src/hello/target/hello-world-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.338s
[INFO] Finished at: Thu Apr 19 21:39:38 CST 2018
[INFO] Final Memory: 16M/469M
[INFO] ------------------------------------------------------------------------
默认情况下打包生成的 jar 文件是不能够直接运行的,因为带有 main 方法的类信息不会添加到 manifest 中。 为了生成可执行的 jar 文件,需要借助 maven-shade-plugin,在 pom.xml 中添加如下配置:
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.mycompany.helloworld.HelloWorld</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
...
使用 mvn package 重新打包,可以看到 target 生成了两个 jar 包,其中一个是 original-xxx.jar 这个是不带有 MainClass 的 jar,而另一个则是包含 MainClass 的 jar。 现在我们可以通过:
java -jar target/hello-world-1.0-SNAPSHOT.jar
直接执行这个 jar 文件。
每次开始一个项目的时候都要手动编写 pom.xml 以及生成 src/main/java src/test/java 目录显然是很麻烦的事。 为此 Maven 提供了 Archetype 用于帮助我们快速地生成项目的骨架。 使用以下命令,然后根据向导填入相关信息即可:
% mvn archetype:generate