本文将详述 maven 在软件项目中的使用。首先讲述 maven 的基本工作原理及环境的搭建。然后讲述开发及配置管理人员如何使用 maven,最后将介绍 maven 与 eclipse 集成使用。
class="first">maven 是人为制订的一套开发规范,该规范定义了开发一个 java 项目时的各个细节。maven 通过 pom.xml 这一配置文件来描述一个项目。以下将介绍 pom.xml 文件及 maven 的主要概念。
POM (Project Object Model) 是对一个项目定义的模型。通过该配置文件可以完整地定义一个项目所涉及的如:项目放在哪里,项目依赖哪些东西,项目的作者是谁,项目如何构建等信息。maven 将通过该文件定义的信息对项目进行构建。
以下是 POM 文件的概要(详细内容参考:http://maven.apache.org/pom.html):
<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>...</groupId> <!-- 项目所在组、机构 --> <artifactId>...</artifactId> <!-- 项目产品名称 --> <version>...</version> <!-- 项目产品版本 --> <packaging>...</packaging> <!-- 项目包类型 --> <dependencies>...</dependencies> <!-- 项目依赖包 --> <parent>...</parent> <!-- 项目所继承的父项目 --> <dependencyManagement>...</dependencyManagement> <!-- 继承父系的依赖 --> <modules>...</modules> <!-- 所包含的子模块 --> <properties>...</properties> <!-- 定义变量 --> <!-- 项目构建设置 --> <build>...</build> <!-- 项目报告生成设置 --> <reporting>...</reporting> <!-- 项目更多设置 --> <name>...</name> <!-- 项目名称 --> <description>...</description> <!-- 项目描述 --> <url>...</url> <!-- 项目网站 --> <inceptionYear>...</inceptionYear> <!-- 项目起始年份 --> <licenses>...</licenses> <!-- 项目许可 --> <organization>...</organization> <!-- 项目组织 --> <developers>...</developers> <!-- 项目开发人员 --> <contributors>...</contributors> <!-- 项目贡献者 --> <!-- 环境设置 --> <issueManagement>...</issueManagement> <!-- 问题管理 --> <ciManagement>...</ciManagement> <mailingLists>...</mailingLists> <scm>...</scm> <!-- 代码管理 --> <prerequisites>...</prerequisites> <repositories>...</repositories> <!-- 指定依赖包所在的仓库 --> <pluginRepositories>...</pluginRepositories> <!-- 指定插件所在的仓库 --> <distributionManagement>...</distributionManagement> <!-- 指定发布位置 --> <profiles>...</profiles> <!-- 针对不同的环境使用不同的配置,如开发与生产环境的数据库是不同的 --> </project>
从概要可以看到 maven 可以做代码管理,代码测试报告,项目网站,项目依赖关系等管理。
sample | pom.xml 项目定义文件 \---src 项目源文件 +---main 项目主文件 \---test 项目测试文件
一个 maven 项目的目录结构如上所示,maven 通过项目定义文件(pom.xml)来对项目的源文件进行操作。源文件包含两部分,一部分是最终能够提供功能的主要文件(main),另一部分是用于测试主要功能的辅助文件(test)。
maven 程序的整个操作就是根据项目定义文件中的定义对源文件进行操作。maven 在 components.xml 文件中定义了一个项目的三种生命周期。每种生命周期有不同的阶段((详细参考 http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference))。
maven 的每个生命周期定义了不同的阶段,每个阶段都可以设置该阶段所使用的插件及插件中的任务。以下通过 maven 命令来举例说明:
# 将项目设置到默认生命周期的 deploy 阶段 # 这将使源码已经被编译、测试、安装及发布 mvn deploy # 直接通过 maven 运行 clean 插件的 clean 任务 mvn clean:clean # 先将项目设置到清理生命周期(clean) # 然后将项目设置到默认生命周期的编译阶段(compile) # 最后运行 jetty 插件的 run 任务 mvn clean compile jetty:run
通过下面的配置(取自 components.xml )可以了解到一个生命周期是如何定义的,并且生命周期的每个阶段会执行哪些 plugin 的任务。
<component> <role>org.apache.maven.lifecycle.Lifecycle</role> <implementation>org.apache.maven.lifecycle.Lifecycle</implementation> <role-hint>site</role-hint> <configuration> <id>site</id> <phases><!-- site 生命周期包括哪些阶段 --> <phase>pre-site</phase> <phase>site</phase> <phase>post-site</phase> <phase>site-deploy</phase> </phases> <default-phases> <site><!-- site 阶段使用 site-plugin 的 site 任务 --> org.apache.maven.plugins:maven-site-plugin:2.0.1:site </site> <site-deploy> org.apache.maven.plugins:maven-site-plugin:2.0.1:deploy </site-deploy> </default-phases> </configuration> </component>
maven 会将所有的公共 jar 包放置于公共的中心仓库(Center Repository)中。为了提高速度,各个网站会复制一份中心仓库的内容并且与中心仓库保持同步。这些复制的仓库称为镜像(Mirror)。在本地的电脑上,会有一个本地仓库,maven 根据项目的依赖关系从中心仓库或者镜像中下载所需要的 jar 包到本地仓库中,供不同的项目使用。
新建一个测试目录,在命令行中进入该目录,运行:
mvn archetype:generate
此时,会看到 maven 下载了很多东西到机器上来,最终会显示一个列表,并提示输入
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 163:
这是要用户选择创建什么类型的项目,maven 会根据选择将项目的基本框架搭建好。由于是为了测试 maven 这里可以直接选择默认的项目(直接按回车),接下来会提示输入
Choose version: 1: 1.0-alpha-1 2: 1.0-alpha-2 3: 1.0-alpha-3 4: 1.0-alpha-4 5: 1.0 6: 1.1 Choose a number: 6:
这是让用户选择版本,同样选择默认的版本(回车),接下来提示
Define value for property 'groupId': :
这是让用户输入所在的组织,可以输入如 com.mycompany 或者 org.mygroup 等,这里输入本站的网址:
Define value for property 'groupId': : com.lsi2
之后提示输入产出物的名称,后面类似:
Define value for property 'artifactId': : sample Define value for property 'version': 1.0-SNAPSHOT: : Define value for property 'package': : : com.lsi2.sample Confirm properties configuration: groupId: com.lsi2 artifactId: sample version: 1.0-SNAPSHOT package: com.lsi2.ssa Y: : y
以上步取可以通过一条命令搞定:
mvn archetype:generate -DgroupId=com.lsi2.sample -DartifactId=sample -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
这样项目就创建完成,可以运行以下命令来测试项目
cd sample mvn test
看到以下内容,说明 maven 安装成功
------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.lsi2.sample.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.044 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 8.778s [INFO] Finished at: Sat Dec 31 01:59:43 CST 2011 [INFO] Final Memory: 8M/20M [INFO] ------------------------------------------------------------------------
maven 配置包括以下三个层面:
对于单个项目的配置前文已有介绍(pom.xml)。现介绍 settings.xml((详细内容可以参考 http://maven.apache.org/settings.html))。
<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/> <!-- 指定本地仓库位置 --> <interactiveMode/> <!-- 指定 maven 的运行模式是否为交互模式 --> <usePluginRegistry/> <!-- 目前少用,指定插件配置文件 --> <offline/> <!-- 指定是否为离线模式,在不需要网络交互的时候使用 --> <pluginGroups/> <!-- 指定插件所在的路径,maven 将通过该路径查找插件 --> <servers/> <!-- 指定服务器的用户名、密码等,用于上传,下载文件等 --> <mirrors/> <!-- 指定 maven 主仓库的镜像 --> <proxies/> <!-- 网络代理配置,用于有代理的网络 --> <profiles/> <!-- pom.xml 中的 profile 能够用于公共配置的部分 --> <activeProfiles/> </settings>
默认情况下,maven 通过客户端机器直接与中心仓库进行网络通信,会存在以下两个主要的问题:
为此,可以通过搭建一个代理服务器来解决以上问题。搭建代理服务器后的网络结构为:
搭建代理服务器之后,可以将开发成品(jar包)容上传到代理服务器上,并使用代理服务器来管理所有的团队共用 jar 包。
目前有两种流行的代理服务器:http://www.jfrog.com/products.php|artifactory 和 http://nexus.sonatype.org/|nexus。以下介绍 nexus 的安装配置。
安装完成之后,可以访问以下网址:
http://localhost:8081/nexus/
初始的用户名及密码:
admin/admin123 用于管理系统 deployment/deployment123 用于发布jar包
settings.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"> ... <servers> <server> <!-- 设置发布 jar 包时的用户名及密码 --> <id>deploymentRepo</id> <username>deployment</username> <password>deployment123</password> </server> </servers> ... <mirrors> <mirror> <!-- 设置 maven 的远程仓库为 nexus --> <id>nexus</id> <mirrorOf>*</mirrorOf> <name>Local Repository</name> <url>http://192.168.1.60:8081/nexus/content/groups/public</url> </mirror> </mirrors> ... <profiles> ... <profile> <!-- 设置 nexus 的路径等 --> <id>nexus</id> <repositories> <repository> <id>central</id> <name>local private nexus</name> <url>http://localhost:8081/nexus/content/groups/public</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>true</enabled></snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>central</id> <name>local private nexus</name> <url>http://localhost:8081/nexus/content/groups/public</url> <releases><enabled>true</enabled></releases> <snapshots><enabled>true</enabled></snapshots> </pluginRepository> </pluginRepositories> </profile> ... </profiles> ... <activeProfiles> <!-- 激活 nexus --> <activeProfile>nexus</activeProfile> </activeProfiles> ... </settings>
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/maven-v4_0_0.xsd"> ... <distributionManagement> <!-- 设置发布 jar 包时所用到的 server 及路径 --> <repository> <id>deploymentRepo</id> <!-- 与 settings.xml 中的 server id 对应 --> <name>Uploadable Nexus Repo</name> <url>http://192.168.1.60:8081/nexus/content/repositories/snapshots/</url> </repository> </distributionManagement> ... </project>
以上介绍完 maven 的基本原理及相关配置,接下来举例说明 maven 的使用。
在 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/maven-v4_0_0.xsd"> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.5</source> <target>1.5</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> ... </project>
运行
mvn eclipse:eclipse
如果需要在 eclipse 中能够查看到依赖包的源码,可以配置 eclipse 插件如下:
<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"> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-eclipse-plugin</artifactId> <version>2.8</version> <configuration> <downloadSources>true</downloadSources> <downloadJavadocs>true</downloadJavadocs> </configuration> </plugin> </plugins> </build> ... </project>
jetty 可以进行热部署,在开发时可以不用频繁启动服务,从而提高开发效率。使用 jetty 的配置如下:
<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"> ... <build> <plugins> <plugin> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.10</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <stopKey>foo</stopKey> <stopPort>9999</stopPort> <webDefaultXml>src/test/resources/webdefault.xml</webDefaultXml> </configuration> <executions> <execution> <id>start-jetty</id> <phase>pre-integration-test</phase> <goals> <goal>run</goal> </goals> <configuration> <scanIntervalSeconds>0</scanIntervalSeconds> <daemon>true</daemon> </configuration> </execution> <execution> <id>stop-jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> </plugins> </build> ... </project>
同时,还需要修改 jetty 的配置文件 webdefault.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" metadata-complete="true" version="2.5"> ... <servlet> <servlet-name>default</servlet-name> <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class> ... <init-param> <param-name>useFileMappedBuffer</param-name> <param-value>false</param-value> <!-- 不缓存文件,文件修改之后马上使用新文件 --> </init-param> ... </servlet> ... </web-app>
该文件可以从 jetty 插件中找到,修改后可以放置于以下目录中,在测试时使用。
src/test/resources
运行下列命令,可以清除所有已经编译的产出。
mvn clean:clean