5、Maven使用入门

1、  编写POM

Maven项目的核心是pom.xml。POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等等。现在先为Hello World项目编写一个最简单的pom.xml。

首先创建一个名为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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook</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元素,虽然这些属性不是必需的,但是使用这些属性能够让第三方工具(如IDE中的XML编辑器)帮助我们快速地编辑POM。

根元素下的第一个子元素modelVersion指定了当前POM模型的版本,对于 Maven2及Maven3来说,它只能是4.0.0.

这段代码中最重要的是包含groupId、artifactId和version的三行。这三个元素定义了这个项目基本的座标,在Maven的世界,任何的Jar、pom或者war都是以基于这些基本的座标进行区分的。

groupId定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联。一般为域名倒过来写

artifactId定义了当前Maven项目在项目中唯一的ID,我们为这个Hello World项目定义artifactId为hello-world

version指定了Hello World项目当前的版本。

name元素声明了一个对于用户更为友好的项目名称,虽然这不是必须的,但是还是推荐为每个POM声明name,以方便信息交流。

没有任何实际的Java代码,我们就能够定义一个Maven项目的POM,这体现了Maven的一大优点,它能让项目对象模型最大程序地与实际代码相独立,我们可以称之为解耦,或者正交性。这在很大程度上避免了Java代码和POM代码的相互影响。比如当项目需要升级版本时,只需要修改POM,而不需要更改Java代码;而在POM稳定之后,日常的Java代码开发工作基本不涉及POM的修改。

2、  编写主代码

项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(如jar),而测试代码只在运行测试时用到,不会被打包。默认情况下,Maven假设项目主代码位于src/main/java目录,我们遵循Maven的约定,创建该目录,然后在该目录下创建文件com/juvenxu/mvnbook/helloworld/HelloWorld.java


package com.juvenxu.mvnbook.helloworld;


public class HelloWorld {
public String sayHello(){
return "Hello Maven";
}
public static void main(String[] args) {
System.out.println(new HelloWorld().sayHello());
}


}

对于Java代码有两点需要注意。首先,在绝大多数情况下,应该把项目主代码放到src/main/java目录下(遵循Maven的约定),而无须额外的配置,Maven会自动搜寻该目录找到项目主代码。其实,该java类的包名是com.juvenxu.mvnbook.helloworld,这与之前在POM中定义的groupId和artifactId相吻合。一般来说,项目中Java类的包都应该基于项目的groupId和artifactId,这样更加清晰,更加符合逻辑,也方便搜索构件或者Java类。

代码编写完毕后,使用Maven进行编译,在项目根目录下运行命令mvn clean compile,会得到如下输出:



clean 告诉Maven清理输出目录target/,compile告诉Maven编译项目主代码,从输出中看到Maven首次执行了clean任务,删除target/目录。默认情况下,Maven构建的所有输出都在target/目录中;接着执行resources任务(不定义项目资源,暂且略过);最后执行compile任务,将项目主代码编译至target/classes目录

clean,resources,compile对应了maven的一些插件及插件目标,后面会详细介绍。

接下来编写一些单元测试代码并让Maven执行自动化测试。

3、  编写测试代码

为了使项目结构保持清晰,主代码与测试代码应该分别位于独立的目录中。对应地,Maven项目默认的测试代码目录是src/test/java。因此,在编写测试用例前,应当先创建该目录。

JUnit是事实上的单元测试标准。要使用Junit,首先需要为HelloWorld项目添加一个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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.juvenxu.mvnbook</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.7</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

代码中添加了dependencies元素,该元素下可以包含多个dependency元素以声明项目的依赖。有了这段声明,maven就能自动下载junit-4.7.jar。会自动到Maven的中央仓库下载,后面章节会介绍中央仓库相关

上述代码中scope元素指定为test,表示该依赖只对测试有效。换句话说,测试代码中的import JUnit代码是没有问题的,但是如果在主代码中用import JUnit代码就会造成编译错误。如果不声明范围,那么默认值就为compile,表示该依赖对主代码和测试代码都有效。



在src/test/java下创建测试代码

package com.juvenxu.mvnbook.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 clean test



测试通过


4、  打包和运行

将项目进行编译、测试之后,下一个重要步骤就是打包(package)。Hello World的POM中没有指定打包类型,使用默认打包类型jar。简单地执行命令mvn clean package 进行打包



Maven在打包前执行编译、测试等操作。打包操作会在target/下生成一个文件:hello-world-1.0-SNAPSHOT.jar

至此,我们得到了项目的输出,如果有需要的话,就可以复制整个jar文件到其它项目的classpath中从而使用Hello World类。但是,如何才能让其它的Maven项目直接引用这个jar呢?还需要一个安装的步骤,执行mvn clean install

目的是将jar安装到本地仓库中,此时其它maven项目才能使用它。

我们已经体验了maven最主要的命令:mvn clean compile,mvn clean test,mvn clean package,mvn clean install。执行test之前是会先执行compile的,执行package前是会先执行test的,而类似地,install前会执行package。

到目前为止,还没有运行Hello World项目,不要忘了HelloWorld类可是有一个main方法的。默认打包的jar是不能够直接运行的,因为带有main方法的类信息不会添加到manifest中(打开jar文件中的META-INF/MANIFEST.MF文件,将无法看到Main-Class一行)。为了生成可执行的jar文件,需要借助maven-shade-plugins,配置插件如下:

            <plugins>

                     <plugin>

                               <groupId>org.apache.maven.plugins</groupId>

                               <artifactId>maven-shade-plugin</artifactId>

                               <version>1.2.1</version>

                               <executions>

                                        <execution>

                                                 <phase>package</phase>

                                                 <goals>

                                                           <goal>shade</goal>

                                                 </goals>

                                                 <configuration>

                                                           <transformers>

                                                                    <transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

                                                                             <mainClass>com.juvenxu.mvnbook.helloworld.HelloWorld</mainClass>

                                                                    </transformer>

                                                           </transformers>

                                                 </configuration>

                                        </execution>

                               </executions>

                     </plugin>

            </plugins>

   </build>

plugin元素在POM中的相对位置应该在<project><build><plugins>下面。现在执行mvn clean package,等构建完成之后打开target/目录,可以看到hello-world-1.0-SNAPSHOT.jar和original-hello-world-1.0-SNAPSHOT.jar,前者是带有Main-Class信息的可运行的jar,后者是原始的jar,打开hello-world-1.0-SNAPSHOT.jar的META-INF/MANIFEST.MF可以看到它包含这样一行信息:

Main-Class: com.juvenxu.mvnbook.helloworld.HelloWorld

现在在项目要目录执行该jar文件


控制台输出的内容正是我们期望的。

5、  使用Archetype生成项目骨架

Hello World项目中有一些Maven的约定:在项目的根目录中放置pom.xml。在src/main/java目录中放置项目的主代码,在src/test/java中放置项目的测试代码。我们称这些基本的目录结构和pom.xml文件内容为项目的骨架。maven命令可以自动生成骨架。

还是以Hello World为例,我们使用maven archetype来创建该项目的骨架,离开当前的Maven项目目录。

运行命令:mvn archetype:generate

我们实际上是在运行插件maven-archetype-plugin,注意冒号的分隔,其格式为:groupId:artifactId:version:goal,org.apache.maven.plugins是maven官方插件的groupId,maven-archetype-plugin是Archetype插件的artifactId,generate是要使用的插件的目标。

紧接着会看到一段长长的输出,有很多可用的Archetype供选择。每一个Archetype前面都会对应一个编号,同时命令行会提示一个默认的编号,其对应的Archetype为maven-archetype-quickstart,直接回车以选择该Archetype,紧接着maven会提示输入要创建项目的groupId、artifactId、version以及包名package。如下输入并确认:



Archetype插件将根据我们提供的信息创建项目骨架。在当前目录下,Archetype插件会创建一个名为hello-world(我们定义的artifactId)的子目录,从中可以看到项目的基本结构:基本的pom.xml已经被创建,里面包含了必要的信息以及一个junit依赖;主代码目录src/main/java已经被创建,在该目录下还有一个java类com.juvenxu.mvnbook.App,注意这里使用到了刚才定义的包名,而这个类也仅仅只有一个简单的输出Hello World!的main方法;测试代码目录src/test/java也被创建好了,并且包含了一个测试用例。

这里仅仅是看到了一个最简单的Archetype,如果有很多项目拥有类似的自定义项目结构以及配置文件,则完全可以一劳永逸地开发自己的Archetype,然后在这些项目

中使用自定义的Archetype来快速生成项目骨架。

6、  m2eclipse简单使用

A、 导入Maven项目

File->Import(弹出对话框),在对话框中输入maven进行过滤,按图选择

单击Next按钮选择对应的项目,导入即可


B、 创建Maven项目。

选择菜单File->New->Other,在弹出的对话框中选择Maven下的Maven Project,然后单击Next按钮,在弹出的New Maven Project对话框中使用默认的选项(不要选择Create a simple project选项,那样我们就能使用MavenArchetype),单击Next按钮,此时m2eclipse会提示我们选择一个Archetype。这里选择maven-archetype-quickstart,再点击Next按钮。输入相关的信息,如下图


注意:为了不和前面已导入的Hello World项目产生冲突和混淆,这里使用不同的artifactId和package。单击Finish按钮,Maven项目就创建完成了。

C、 运行mvn命令

在Maven项目或pom.xml上右击,再在弹出的快捷菜单中选择Run as,就能看见常见的Maven命令。这里有一个常见的问题,默认选项中没有我们想要执行的Maven命令怎么办?比如,默认带有mvn test,但是我人想执行mvn clean test,很简单,选择Maven build以自定义Maven运行命令,在弹出对话框的Goals一项中输入我们想要执行的命令,如clean test,设置一下Name,单击Run即可。并且下一次我们选择maven build或者使用对应的快捷键时,上次的配置就会在历史记录中找到。下图就是mvn自定义命令界面





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章