问题导读:
1.如何使用Maven2创建工程?
2.如何使用Maven2编译、打包项目?
3.groupId, artifactId, version的作用是什么?
4.如何设置工程依赖jar包?
5.maven2资源库的作用是什么?
相关资料推荐:源码编译maven系列视频教程汇总
目录
1. 环境配置
1.1. 配置Maven2
1.2. 配置Eclipse环境变量MIA_LIB
1.3. 安装Maven2 的eclipse plugin
2. Maven2使用说明
2.1. 简单例子
2.2. groupId, artifactId, version的作用
2.3. Maven2的plugin, goal和phase的说明
2.3.1. plugin和goal
2.3.2. phase
2.3.3. plugin goal与phase的区别
2.3.4. 命令行一次执行多个 goal或phase
2.4. 几个常用的phase: clean, compile, package, install
2.5. 工程依赖jar包的设置
2.5.1. 设置说明
2.5.2. 关于maven2资源库
2.6. 手动安装jar包到本地资源库
2.7. 使用maven编译项目代码注意事项
3. 构建项目规范说明
3.1. 项目目录结构
3.2. 设置groupId, artifactId规范
3.3. 在Eclipse要引用的jar包设置规范
3.4. MIA_LIB维护更新规范
1. 环境配置
1.1. 配置Maven2
1) 将maven2从\\192.168.22.51\Group\MIA\开发环境\tool\apache-maven-2.2.1复制到本地,如复制到D:\work\apache-maven-2.2.1
2) 配置Path环境变量,指向bin目录,如图:
3)把svn上的maven2资源库http://192.168.22.53/svn/mobile_mia/mlib/ check out下来,如check out 到D:\work\mlib
4)修改Maven2安装目录下的配置文件conf\settings.xml,把<localRepository>的值设置成第3步中从SVN上 check out下来的maven资源库路径,如:
<localRepository>D:/work/mlib</localRepository>
关于settings.xml结构详细说明,请参考:http://maven.apache.org/settings.html
1.2. 配置Eclipse环境变量MIA_LIB
配置Eclipse环境变量MIA_LIB指向maven2的<localRepository>,配置方法如下:
打开菜单Window -> Preferences,然后选择如图:
1.3. 安装Maven2 的eclipse plugin
通过Eclipse update 功能安装,安装地址是:http://m2eclipse.sonatype.org/update/
2.Maven2使用说明
2.1. 简单例子
1)新建工程,目录结构如下图:
更多目录结构的作用详细说明请参考:http://maven.apache.org/guides/i ... rectory-layout.html
2) 设置pom.xml,maven2 编译配置文件。
在每个使用maven2编译的项目必须有pom.xml
pom.xml文件详细结构说明请参考:http://maven.apache.org/pom.html 。
此例简单的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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
复制代码
3) 运行mvn命令
在命令行进入工程目录
运行compile命令编译class
复制代码
运行结果在工程目录下生成target目录,如图:
注:maven2默认所有运行编译等临时文件和生成的结果都在target目录下。
运行package命令打包成jar, war等,打成什么包取决于pom.xml中<packaging>jar</packaging>的配置,它的值有jar, war, ear, pom等几种,如设成jar, 运行mvn package就将classes打成jar包。设成war,就打包成war包,但必须是一个web工程,如在此例中必须有my-app/src/main/webapp/WEB-INF/web.xml存在,否则会运行失败。
复制代码
运行结果:
注:更多关于简单例子和使用请看:http://maven.apache.org/guides/getting-started/index.html
2.2. groupId, artifactId, version的作用
Maven2中groupId, artifactId, version是各种依赖jar包、plugin等调用、引用的基础标识结构。如dependency引用、plugin引用,还有将项目打包发布到Maven2 Repository上都需要是利用该结构的。
groupdId类似于java package的概念,artifactId相当于是java类名。 当工程被安装到Maven2 Repository上时,被安装打包后的文件路径将是groupId/artifactId/version/artifactId-version.jar
如pom.xml是:
<project>
........
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>my-app</name>
........
</project>
如本地的Maven2 Repository是在D:\work\mlib,项目被打包发布到D:\work\mlib下的com\mycompany\app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.jar。
注:这里生成的目录为什么是com\mycompany\app,而不是com.mycompany.app?因为如果groupId是以点号隔开的,Maven2会把点号分隔生成目录,所以这里就把com.mycompany.app分隔生成com\mycompany\app了。
如果把:<groupId>com.mycompany.app</groupId>
改成:<groupId>com-mycompany-app</groupId>
结果在Maven2 Repository发布的包的路径是:com-mycompany-app\my-app\1.0-SNAPSHOT\my-app-1.0-SNAPSHOT.jar
2.3. Maven2的plugin, goal和phase的说明
Maven2的中的plugin, goal作用相当于ant中的task, phase相当于ant中的target depends, ant通过depends的关联,实现运行一系列task,Maven2中用phase来实现这种功能,并且它的功能更强,更简单易用。
2.3.1.plugin和goal
Maven2中所有的build的实现都是通过plugin形式,每个plugin下有多个goal,具体的build动作是通过goal来完成的。执行plugin主要有两种方式。
一、在命令行输入
mvn plugin:goal 或者mvn pluginGroupId:pluginArtifactId:pluginVersion:goal
如:
复制代码
作用等于:
mvn org.apache.maven.plugins:maven-compiler-plugin:2.0.2:compile
复制代码
二、在pom.xml中配置plugin,配置如下:
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
复制代码
注:Maven2内置了很多plugin,关于它们的作用和使用方法,具体请查看:http://maven.apache.org/plugins/index.html
关于自定义plugin的开发请参考:http://maven.apache.org/plugin-developers/index.html
2.3.2.phase
Maven2 的phase是指一个build的生命周期,每个phase绑定一个或多个plugin goal(compile绑定的默认plugin goal是compile:compile),执行每一个phase时,会依次执行完这个phase之前的所有phase后再执行当前phase。
phase的执行方法,如:
复制代码
注:这里的 compile是phase,中间有冒号隔开的是goal,否则是执行一个phase。如:mvn compile:compile是执行一个goal。
下表是Mave2的默认phase:
1
validate the project is correct and all necessary information is available
compile the source code of the project
test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
take the compiled code and package it in its distributable format, such as a JAR.
process and deploy the package if necessary into an environment where integration tests can be run
run any checks to verify the package is valid and meets quality criteria
install the package into the local repository, for use as a dependency in other projects locally
done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
如当执行第7个phase install时,会依次执行完前面的1到6个phase后再执行install。如运行:
mvn install
会先依次按顺序调用install前面的几个phase:validate, compile, test, package, integration-test,verify,最后再调用install。
如运行:
mvnpackage
会先依次调用validate,compile, test,最后调用package。
1.1.2. plugin goal与phase的区别
每个plugin goal可以被设置成在指定的phase中被调用,但是在命令行下直接调用goal时不能指定到某个phase中执行,如执行goal:
mvnjar:jar
结果只是单一的调用这个动作,不会执行一系列动作,如果class没有被编译出来,直接调用mvn jar:jar结果将是失败的,因为class不存在。
plugin goal可以通过在pom.xml中设置到指定phase中执行。
如下面的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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
......
<build>
<plugins>
......
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project> 复制代码
默认的plugin goal org.apache.maven.plugins:org.apache.maven.plugins:2.2:jar(简写jar:jar)运行在phasepackage上,也就是说只有当执行“mvn package”时这个plugin goal才会被调用。下面进行修改这个plugin goal的默认phase:
......
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
<executions>
<execution>
<phase>compile</phase> //将这个plugin指定到compile phase中执行
<goals>
<goal>jar</goal> //指定要执行的goal
<goal>...</goal>
</goals>
</execution>
</executions>
</plugin>
...... 复制代码
1.1.3. 命令行一次执行多个 goal或phase
在命令行中一条命令可以同时执行多个goal或phase,如:
mvn cleancompile
先调用clean phase清除旧的编译临时文件和目录,然后再调用compile编译源代码
goal 和phase可以组合调用,如:
mvn cleancompile jar:jar
先执行清除编译后,再调用plugingoal jar:jar对编译class打成jar包。
1.2. 几个常用的phase: clean, compile, package, install
1) clean
mvn clean
清除编译生成的目录文件,如:默认是清除target目录及下面的所有文件
2) compile
mvncompile
编译java源代码
3) package
mvnpackage
对工程进行编译后打包,如打成jar包或war包等
4) install
mvninstall
将工程编译打包,最后发布到localRepository上
1.3. 工程依赖jar包的设置
1.3.1. 设置说明
在ant中,工程依赖的jar包需要存放在本地,并且通过设置指定位置引用。Maven2中,jar包依赖库的引用变的很简单,只需要在pom.xml中配置好,jar包无需存放在本地,可以在网络的任何地方,maven2在运行编译时会根据pom.xml中的设置自行从网上指定的maven资源库中去下载。每一个依赖的包在pom.xml中设置<dependency>值,如:工程需要引用servlet-api 2.4, jsp-api 2.0, commons-beanutils 1.6, commons-codec 1.3等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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
...
</project> 复制代码
Maven2 首先根据groupId, artifactId, version发布包时生成的路径规则寻找,如找commons-codec包,将会拼成:commons-code/commons-codec/1.3/commons-codec-1.3.pom,然后从maven2资源库去下载这个pom就是maven的编译配置文件pom.xml,在发布的时候随着jar一起发布到资源库库的。如果找到这个pom文件,然后解析它,如果这个pom有相应的依赖库<dependency>,Maven2也会把它下载过来,并且这个是循环遍历的,如果依赖的库又有相应的依赖包,会依次下载过来。如果找不到这个pom文件,Maven2会去直接下载要引用的jar包commons-code/commons-codec/1.3/commons-codec-1.3.jar,如果还是找不到,将会编译失败。
注:<dependency>下的<scope>有几个值:
scope
this is the default scope, used if none is specified. Compile dependencies are available in all classpaths. Furthermore, those dependencies are propagated to dependent projects.
this is much like compile, but indicates you expect the JDK or a container to provide it at runtime. It is only available on the compilation and test classpath, and is not transitive.
this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.
this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
systemPath:
is used only if the the dependency scope is system. Otherwise, the build will fail if this element is set. The path must be absolute, so it is recommended to use a property to specify the machine-specific path (more on properties below), such as ${java.home}/lib. Since it is assumed that system scope dependencies are installed a priori, Maven will not check the repositories for the project, but instead checks to ensure that the file exists. If not, Maven will fail the build and suggest that you download and install it manually.
1.3.2. 关于maven2资源库
上面说的Maven2将所有jar包都是网上下载到本地资源库然后再引用进行编译,所以Maven2先会去检测该jar包在本地资源库localRepository中是否则已经有了,如果有了就直接调用,如果没有再从网上资源库中寻找下载。
<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.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
......
<pluginRepositories> //plugin的jar包下载资源库
<pluginRepository>
<id>Maven Snapshots</id>
<url>http://snapshots.maven.codehaus.org/maven2/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
<repositories> //自定义的jar包下载资源库
<repository>
<releases>
<enabled>false</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
<id>apacheSnapshots</id>
<name>Apache Snapshots</name>
<url>http://people.apache.org/repo/m2-snapshot-repository/</url>
<layout>default</layout>
</repository>
</repositories>
......
</project>
复制代码
1.4. 手动安装jar包到本地资源库
在2.5.1 设置说明中提到,如果一个jar包在所有提供的资源库中都找不到,就会编译失败。所以只能把这个jar包手动安装到本地资源库中。安装方法:
mvninstall:install-file -DgroupId=groupId -DartifactId=artifactId-Dversion=version -Dpackaging=jar -DgeneratePom=true -Dfile=/path/to/file
如ugc sti的nokia jar包naai-sdk.jar, 在任何资源库中都找不到它,所以只有手动将naai-sdk.jar安装到本地资源库上
mvninstall:install-file -DgroupId=com.nokia.ncim -DartifactId=naai-sdk -Dversion=1.0-Dpackaging=jar -DgeneratePom=true -Dfile=D:/ttt/sti/WebContent/WEB-INF/lib/naai-sdk.jar
groupId设成com.nokia.ncim
arartifactId设成naai-sdk
version设成1.0
然后就可以在pom.xml中引用了:
<dependency>
<groupId>com.nokia.ncim</groupId>
<artifactId>naai-sdk</artifactId>
<version>1.0</version>
</dependency>
1.5. 使用maven编译项目代码注意事项
在Maven中,对代码的要求比较严格,只要编译时出现警告提示,虽然在eclipse或在ant中能编译通过,
但是在Maven中无法编译通过
1. 方法返回泛型类型的需注意:
有如下代码:
public <T> T queryForObject(final String statementName,final Object parameterObject) throws DataAccessException {
return (T)getSqlMapClientTemplate().queryForObject(statementName, parameterObject);
}
如果该函数返回是java primitive基本类型的,返回的变量一定要要声明成它的Wrapper Class,如下:
Integer num=queryForObject(arg1, arg2)
如果以下面这种形式
int num= queryForObject(arg1, arg2)
在maven中将无法通过编译
2. 引入com.sum打头的包会编译失败,所以不要直接引用这种类
3. 构建项目规范说明
3.1. 项目目录结构
目录结构如图:
现有实际项目目录结构图参考:
目录作用说明:
src/main/java 存放所有java source code
src/main/resources 存放所有资源文件,如xml, properties等配置文件
src/main/webapp 存放web资源文件
src/test 存放所有测试相关的程序代码和资源文件,src/test下面的目录结构和作用与src/main下面的一样
pom.xml maven2 编译配置文件。在每个使用maven2编译的项目该文件必须有,pom.xml文件详细结构说明请参考:http://maven.apache.org/pom.html
assembly.xml maven2的 plugin assembly的配置文件,主要作用是配置相关文件如自定义配置xml, properties, lib等复制到指定的位置,关于plugin assembly的使用说明请参考:http://maven.apache.org/plugins/maven-assembly-plugin/index.html
关于assembly.xml配置文件结构说明请参考:http://maven.apache.org/plugins/ ... lugin/assembly.html
更多目录结构的作用详细说明请参考:http://maven.apache.org/guides/i ... rectory-layout.html
注:
1) 所有的需要被打到jar包的文件或class path里的资源配置文件除了java 文件以外的文件,必须放在src/main/resources或在pom.xml里指定resources的目录,否则将无法被打进jar包或放在class path里
2) 如果不按照maven2标准的目录结构,在pom.xml中将需要做配置指定相关的目录,如:
<build>
<directory>${project.basedir}/target</directory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<sourceDirectory>${project.basedir}/src</sourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
</build> 复制代码
3.2. 设置groupId, artifactId规范
规范示例:
<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>mia</groupId> //groupId统一为 mia
<artifactId>mia-nbi</artifactId> // artifactId前缀加上“mia-”
<packaging>jar</packaging>
<version>1.0.0</version>
<name>mia-nbi</name> // name值同artifactId
......
</project> 复制代码
3.3. 在Eclipse要引用的jar包设置规范
在Eclipse工程中所有要引用的lib jar包,必须从上面已建的环境变量MIA_LIB库中引用。引用方法如图:
3.4. MIA_LIB维护更新规范
环境变量MIA_LIB指向的是Maven2 local repository,也是就从svn check out下来的mlib,所以维护MIA_LIA就是维护maven2本地资源库。所以必须经常从svn更新这个库,或在本地有新增加jar包,一定要提交到svn上,通过svn来保证各开发人员之间,本地资源库的统一。
我们内部所有项目如commons, nbi等,如有更新修改,也需要发布更新安装到MIA_LIB,提交svn。与其他开发人员需要引用的这些库保持同步。