上周给公司的同事做了一下Maven的培训,周末重新整理一下发布到网上。以前使用Ant构建项目,如果使用Ant构建项目时会有一个比较严重的问题,基于分模块的时候对于依赖的管理不太好操作,Maven就是为了解决Ant不太好解决的哪些问题的一种新的项目管理工具,目前Maven是Apache的一个顶级项目(http://maven.apache.org/)。从官方下载的Maven二进制包只有4.7M左右,其实通过官网下载到的只是Maven的一个架构。
Maven的安装非常简单,将Maven的二进制包解压到指定的目录下。那么需要将Maven的bin目录配置到操作系统环境变量中的path中,新建环境变量M2_HOME配置为Maven的根目录。
如果在命令行下输入“mvn -version”命令后能够显示maven的版本信息,说明整个maven的安装已经成功。
如果使用Maven构建项目,需要项目目录下创建一个pom.xml文件,在Ant中配置文件是build.xml,在Maven中配置文件是pom.xml。目前凡是从网上下载的第三方工具包中都是使用Maven进行管理的,我们可以从已建项目中将pom.xml文件拷贝过来作为参考。
所有的Maven都需要配置四个最基本的元素:
<?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.jianshi.demo</groupId> <artifactId>demo-core</artifactId> <version>SNAPSHOT-0.0.1</version> </project>
下面演示一个使用Maven搭建的一个小例子,如果要使用maven构建一个项目那么就需要按照maven的约定去创建对应的目录结构:
package com.jianshi.demo.dataobject; public class Hello{ public String sayHello(String name){ return "hello:" + name; } }
这个简单的小例子中的pom.xml文件内容可以直接参考上面pom.xml中的内容,如果需要使用maven对项目进行编译那么就需要在项目中pom.xml文件所在的路径下执行命令“mvn compile”。
D:\Demo\maven\01>mvn compile [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building uimc-core SNAPSHOT-0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ demo-core --- [debug] execute contextualize [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\Demo\maven\01\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ demo-core --- [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent! [INFO] Compiling 1 source file to D:\Demo\maven\01\target\classes [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.285s [INFO] Finished at: Sun Aug 26 15:44:44 CST 2012 [INFO] Final Memory: 6M/83M [INFO] ------------------------------------------------------------------------ D:\Demo\maven\01>
Maven只有4M,我们所需要的jar包都是作为插件存储在中心仓库中,在执行maven命令的时候需要什么插件,他会直接从网上下载。当每次maven命令执行后从中央仓库下载的插件都会存储在本地的仓库中。通常是在当前登录用户(操作系统)的工作目录下面有一个“.m2”的目录。我们将本地仓库放在C盘明显是不明智的选择(通常C盘作为系统盘),那么通常的方式是将Maven的仓库放在另外一个空闲盘的某个文件夹中。通常maven的配置都会在setting.xml文件中,在maven的安装目录下也有setting.xml文件,安装目录下面setting.xml文件是对所有的项目都起作用的,如果需要为自己机器的maven设置本地仓库的信息就需要将这个setting.xml文件拷贝到本地的仓库目录下面。
<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 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>D:\maven\repository</localRepository> ......
通过本地仓库的配置后,就可以做到如果在本地仓库中存在插件就从本地仓库中获取,如果没有再从中央仓库中下载。(maven安装文件中也需要作此配置)通过刚才执行的“mvn compile”命令发现在pom.xml的目录中出现了target目录,里面存储着编译后的文件。如果需要对文件进行测试,那么就需要在src目录下面创建test目录。同样也需要在test目录下面创建测试类。
package com.jianshi.demo.dataobject; import org.junit.*; import static junit.framework.Assert.*; public class TestHello{ @Test public void testHello(){ Hello h = new Hello(); assertEquals("hello:zhangsan",h.sayHello("zhangsan")); } }
上面的代码中需要引用Junit组件来完成测试,此时需要在pom.xml文件中加入Junit的依赖关系。dependencies表示所有依赖的配置的最高级标签,dependency表示每一个依赖的配置标签。
<?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.jianshi.demo</groupId> <artifactId>demo-core</artifactId> <version>SNAPSHOT-0.0.1</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> </dependencies> </project>
上面的配置就说明这个项目中存在一个依赖,即依赖Junit包,并且说明依赖于Junit的4.10这个版本,以及说明引入的这个包依赖仅作用于测试域。下面执行“mvn test”命令进行测试代码的编译以及测试代码的运行。
D:\Demo\maven\01>mvn test [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building uimc-core SNAPSHOT-0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ demo-core --- [debug] execute contextualize [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\Demo\maven\01\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ demo-core --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ demo-core --- [debug] execute contextualize [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\Demo\maven\01\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ demo-core --- [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent! [INFO] Compiling 1 source file to D:\Demo\maven\01\target\test-classes [INFO] [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ demo-core --- [INFO] Surefire report directory: D:\Demo\maven\01\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.jianshi.demo.dataobject.TestHello Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.088 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.399s [INFO] Finished at: Sun Aug 26 16:04:08 CST 2012 [INFO] Final Memory: 8M/108M [INFO] ------------------------------------------------------------------------ D:\Demo\maven\01>
工程的target目录下发现多出了一些测试报告的类。测试报告还可以生成更丰富的,那么后续测试部分进行介绍。下面执行“mvn clean”命令,可以清空刚才编译或执行的结果数据,即删除target目录。
D:\Demo\maven\01>mvn clean [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building demo-core SNAPSHOT-0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ demo-core --- [INFO] Deleting D:\Demo\maven\01\target [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.758s [INFO] Finished at: Sun Aug 26 16:06:42 CST 2012 [INFO] Final Memory: 2M/82M [INFO] ------------------------------------------------------------------------ D:\Demo\maven\01>
如果执行“mvn clean package”命令,可以先执行删除上次的编译结果,在执行本次的编译及打包。
D:\Demo\maven\01>mvn clean package [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building demo-core SNAPSHOT-0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ demo-core --- [INFO] Deleting D:\Demo\maven\01\target [INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ demo-core --- [debug] execute contextualize [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\Demo\maven\01\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ demo-core --- [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent! [INFO] Compiling 1 source file to D:\Demo\maven\01\target\classes [INFO] [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ demo-core --- [debug] execute contextualize [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\Demo\maven\01\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ demo-core --- [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent! [INFO] Compiling 1 source file to D:\Demo\maven\01\target\test-classes [INFO] [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ demo-core --- [INFO] Surefire report directory: D:\Demo\maven\01\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.jianshi.demo.dataobject.TestHello Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.101 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ demo-core --- [INFO] Building jar: D:\Demo\maven\01\target\demo-core-SNAPSHOT-0.0.1.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6.454s [INFO] Finished at: Sun Aug 26 16:11:08 CST 2012 [INFO] Final Memory: 11M/106M [INFO] ------------------------------------------------------------------------ D:\Demo\maven\01>
执行Maven命令“mvn clean package”后会在target目录之后创建对应的jar包,即:D:\Demo\maven\01 \target\demo-core-SNAPSHOT- 0.0 . 1 .jar
可以通过执行maven命令“mvn clean install”会完成上面的操作之后同时还会将其发布到本地仓库。
通常在一个项目开发过程中都是需要分模块进行建设的,在maven中不同的模块是物理分离的,上面创建的是demo项目的一个核心模块,那么下面再去创建一个manager模块,manager模块需要引用core的内容。此时在manager这个项目中并没有将core中的类引入到ClassPath中,那么就需要在项目manager的pom.xml中增加配置。因为上面的命令执行过“mvn clean install”命令,此时就会将编译后的文件上传到本地库中。
package com.jianshi.demo.manager; import com.jianshi.demo.dataobject.*; public class DemoManager{ public static void main(String [] args){ Hello h = new Hello(); System.out.println(h.sayHello("zhangsan")); } }
<?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.jianshi.demo</groupId> <artifactId>demo-manager</artifactId> <version>SNAPSHOT-0.0.1</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> <dependency> <groupId>com.jianshi.demo</groupId> <artifactId>demo-core</artifactId> <version>SNAPSHOT-0.0.1</version> <scope>compile</scope> </dependency> </dependencies> </project>
此时执行“mvn clean package”命令,此时编译打包成功,manager这个项目是依赖于第一个项目的。这个我们发现maven可以有效的在不同的模块之前有效的管理我们的项目。
D:\Demo\maven\02>mvn clean package [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building demo-manager SNAPSHOT-0.0.1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ demo-manager --- [INFO] Deleting D:\Demo\maven\02\target [INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ demo-manager --- [debug] execute contextualize [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\Demo\maven\02\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ demo-manager --- [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent! [INFO] Compiling 1 source file to D:\Demo\maven\02\target\classes [INFO] [INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @ demo-manager --- [debug] execute contextualize [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent! [INFO] skip non existing resourceDirectory D:\Demo\maven\02\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ demo-manager --- [INFO] No sources to compile [INFO] [INFO] --- maven-surefire-plugin:2.10:test (default-test) @ demo-manager --- [INFO] No tests to run. [INFO] Surefire report directory: D:\Demo\maven\02\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Results : Tests run: 0, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ demo-manager --- [INFO] Building jar: D:\Demo\maven\02\target\demo-manager-SNAPSHOT-0.0.1.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.549s [INFO] Finished at: Sun Aug 26 16:31:08 CST 2012 [INFO] Final Memory: 8M/106M [INFO] ------------------------------------------------------------------------ D:\Demo\maven\02>
通过上面的小例子对maven有了初步的了解,下面进行总结:
“mvn clean”表示运行清理操作(默认会将target文件夹中的数据清理)
“mvn clean compile”表示先运行清理之后在进行编译,将编译后的代码放到target文件夹中
“mvn clean test”运行清理和测试
“mvn clean package”运行清理和打包
“mvn clean install”运行清理和安装,将打包好的jar安装到本地仓库,以便于其他项目的调用
“mvn clean depoly”运行情况和发布(发布到私服上)
如果向上面一样老是手工的创建项目非常麻烦,可以使用“mvn archetype:generate”命令进行操作来完成项目基本骨架的构建。
mvn package -Dmaven.test.skip=true 打包但不测试
上面介绍的都是手工操作,在项目中通常可以使用工具进行管理,例如eclipse的m2eclipse插件。