《maven实战》学习--部分摘自许晓斌博客
部分摘自许晓斌博客:https://juvenshun.iteye.com/blog/206815
1.简介:Maven不仅仅是一个工具,它更是一种先进的理念,其一是"约定优于配置(Convention Over Configuration)",只要你遵循Maven的约定,你可以节省很多时间和学习成本,这一理念也能在 Ruby On Rails 和 JPA 中看到。其二是持续集成,Maven的生命周期几乎对应着持续集成的生命周期,编译,单元测试,打包,集成测试,发布,审计,这一框架Maven已经帮你定义好了,你只要稍作修改便能符合你的要求。
maven可以消除构建中的重复工作。maven是声明式(不同于ant的命令式),可以屏蔽实现的细节,便于理解。
5.坐标和依赖:group id/artifact id/version
依赖范围:用于控制加载的classpath。compile(默认的,对所有classpath生效) ,test(仅对测试classpath生效) ,provided(编译和测试有效,但是运行无效,例如servlet-api,运行时由容器提供), runtime(对测试和运行有效,但是编译无效,典型的是JDBC驱动的实现) ,system(生效范围同provided,但是必须通过systemPath元素显式指定路径,不通过maven仓库解析,适用于不入maven库的场景)
7.生命周期和插件:生命周期(lifecycle),包括clean/default/site,生命周期是抽象的,具体工作由插件(plugin)实现。每个生命周期包括一些阶段(phase),clean(clean) ,default(validate, compile, test, package, install, deploy等),site(site)。每个生命周期是独立的,生命周期内部的阶段是有前后依赖关系的。
执行命令: mvn clean install 实际执行了clean生命周期的clean阶段,和default生命周期的从validate到install阶段。mvn命令本质是激活生命周期的阶段,然后执行阶段对应绑定的插件目标。
插件目标(plugin goal):每个插件可能有多个功能,所以可以通过 插件名称:插件目标 的方式引用,例如 mvn dependency:analyze 和 mvn dependency:tree, mvn dependency:list
插件绑定:maven已经默认为很多阶段绑定了插件目标,例如: clean===maven-clean-plugin:clean, compile===maven-compile-plugin:compile , package===maven-jar-plugin:jar, 也有一些其他阶段没有绑定任何插件目标,故没有任何行为,例如default生命周期的validate阶段,在maven的输出中会指出实际调用的插件和插件目标。可以自定义绑定关系,在POM文件的build元素下声明插件的使用,例如,我们需要在构建jar包的时同时构建一个名为-source.jar的源代码包
1 <build> 2 <plugins> 3 <plugin> 4 <groupId>org.apache.maven.plugins</groupId> 5 <artifactId>maven-source-plugin</artifactId> 6 <version>2.1.1</version> 7 <executions> 8 <execution> 9 <id>attach-source</id> 10 <phase>initialize</phase> 11 <goals> 12 <goal>jar-no-fork</goal> 13 </goals> 14 </execution> 15 </executions> 16 </plugin> 17 </plugins> 18 </build>
7.5 配置插件 使用mvn命令时加上-D参数,设置java系统属性,maven会读取属性并实现配置,例如: mvn clean package -Dmaven.test.skip=true, 另一种方式:mvn clean package -DskipTests
7.7 从命令行调用插件 有些任务不适合绑定到生命周期的阶段上,例如maven-help-plugin:descibe 我们并不需要在构建项目时描述插件信息,而是需要从命令行调用。为此maven引入了插件前缀概念,例如maven-help-plugin的前缀是help,我们可以直接使用 mvn help:describe 调用,例如 :mvn help:describe -Dplugin=org.apache.maven.plugins:maven-help-plugin
8 聚合与继承
---------------------------------------------------------------------------------------------------------------------------------------------------
使用Profile和Resources Filter隔离测试环境:https://juvenshun.iteye.com/blog/206825
问题:项目中有很多单元测试,连的数据库参数写在了src/test/resources 下的配置文件中,项目部分成员在美国,连接中国的数据库非常慢,导致单元测试失败。
解决:通过Profile,我们可以通过Maven传入一些个性化变量,先让我们把Profile定义好,这里我选择在%M2_HOME%/conf 下的settings.xml 里定义全局的Profile,因为数据库链接是很多模块的测试都会用到的,定义如下:
1 <profiles> 2 3 <profile> 4 5 <id>myProfile</id> 6 7 <properties> 8 9 <mysql.url>jdbc:mysql://localhost:3306</mysql.url> 10 11 <mysql.username>test</mysql.username> 12 13 <mysql.password>test</mysql.password> 14 15 <mysql.dbname>test</mysql.dbname> 16 17 </properties> 18 19 </profile> 20 21 </profiles> 22 23 <activeProfiles> 24 25 <activeProfile>myProfile</activeProfile> 26 27 </activeProfiles>
此外,修改资源文件如下:
1 <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> 2 3 <property name="hibernate.connection.url" value="jdbc:mysql://${mysql.url}/${mysql.dbname}"/> 4 5 <property name="hibernate.connection.username" value="${mysql.username}"/> 6 7 <property name="hibernate.connection.password" value="${mysql.password}"/>
至此,我们已经把环境相关的变量隔离开了,每个用户都有自己的settings.xml 文件,所以每个人都能配置自己的settings.xml 来使用他想要使用的数据库。针对我们上面的场景,美国的团队只要在本地配置一个数据库,他们也就可以运行测试了,皆大欢喜!
最后,不要忘了配置 Maven Resources 插件让它开启 filtering 功能:
1 <resource> 2 <directory>src/test/resources</directory> 3 <filtering>true</filtering> 4 </resource>
至此,运行 mvn install ,Maven 会让 Resources 插件首先根据 setttings.xml 文件中的值填充测试资源文件中的变量,然后再运行测试。这种解决方案不仅仅适用于数据库,任何外部环境配置都可以使用该方案,如对消息服务器的依赖。尽情享受Maven给你带来的便利吧!
---------------------------------------------------------------------------------------------------------------------------------------------------
激活Maven profile的几种方式:https://juvenshun.iteye.com/blog/208714 ???
首先简单介绍下 Maven 的 profile 是什么。对于人来说,profile 是指人的肖像,轮廓,比如论坛里每个人注册了帐号后,可以设置自己的 profile,放上照片,介绍等等。对于 Maven 来说又是怎样呢?整个项目定义好了项目对象模型(POM),就像论坛为每个人提供了默认的行为功能,如果我想改变我机器上的 POM 呢?这时就可以使用 profile。下面举个例子:
1 <profiles> 2 <profile> 3 <id>jdk16</id> 4 <activation> 5 <jdk>1.6</jdk> 6 </activation> 7 <modules> 8 <module>simple-script</module> 9 </modules> 10 </profile> 11 </profiles>
这个 profile 的意思是,当机器上的 JDK 为1.6的时候,构建 simple-script 这个子模块,如果是1.5或者1.4,那就不构建,这个 profile 是由环境自动激活的。
我们需要在合适的地方使用合适的 profile ,并且在合适的时候用合适的方式将其激活,你不能在构建服务器上激活非公共的 profile,你也不能要求开发人员写很复杂的命令来使用常规的 profile。因此这里介绍一下几种 profile 的激活方式。
1. 根据环境自动激活。
如前一个例子,使用JDK版本,除此之外,我们还可以根据操作系统参数和 Maven 属性等来自动激活 profile,如:
1 <profile> 2 <id>dev</id> 3 <activation> 4 <activeByDefault>false</activeByDefault> 5 <jdk>1.5</jdk> 6 <os> 7 <name>Windows XP</name> 8 <family>Windows</family> 9 <arch>x86</arch> 10 <version>5.1.2600</version> 11 </os> 12 <property> 13 <name>mavenVersion</name> 14 <value>2.0.5</value> 15 </property> 16 <file> 17 <exists>file2.properties</exists> 18 <missing>file1.properties</missing> 19 </file> 20 </activation> 21 ... 22 </profile>
2. 通过命令行参数激活。
这是最直接和最简单的方式,比如你定义了一个名为 myProfile 的 profile,你只需要在命令行输入 mvn clean install -Pmyprofile 就能将其激活。
3. 配置默认自动激活。
方法很简单,在配置 profile 的时候加上一条属性就可以了,如:
1 <profile> 2 <id>dev</id> 3 <activation> 4 <activeByDefault>true</activeByDefault> 5 </activation> 6 ... 7 </profile>
在一个特殊的环境下,配置默认自动激活的 profile 覆盖默认的 POM 配置,非常简单有效。
4. 配置 settings.xml 文件 profile 激活。
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven生命周期详解:https://juvenshun.iteye.com/blog/213959 ???
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven仓库管理器的重要性:https://juvenshun.iteye.com/blog/230713
今天在maven主题的irc中得知,又一个中国的ip被中央Maven仓库 封了。原因我猜到了大半,但还是忍不住问一下,回答是:他们消耗了很大的中央仓库带宽,会使之变慢。因此这些人不是良好的Maven公民。我猜测是某个公司吧,很多人用Maven构建项目,但是自己没有建立一个仓库管理服务器,有太多的重复下载,直接导致占用了很大的带宽。
仓库管理器有两个服务目的:首先它的角色是一个高度可配置的介于你的组织与公开Maven仓库之间的代理,其次它为你的组织提供了一个可部署你组织内部生成的构件的地方。
我略微解释下,首先它是代理,因此这个公司需要维护一个Maven仓库管理器,它代理所有内部Maven的构件请求,并在服务器上维护一份缓存,该公司为所有的构件只向公共仓库请求一次,内部请求完全通过LAN搞定,开发者看到进度条刷刷的闪,心情会比较好。此外,所有开发者只需要配置一个指向这个代理的仓库。公共服务器的配置,在仓库管理器维护,这也大大减少的时间。
Maven仓库管理器的第二个功能是,为组织提供一个部署构件的公共地址,以便共享。一个项目可能分割成5个模块,模块之间相互有依赖,有了仓库管理器,模块A的SNAPSHOT版本可以随时发布到内部仓库上,模块B就能很方便的得到最新的模块A构件。此外,release版本的构件也能很方便的发布,供QA测试等等。
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven中的插件和生命周期:https://juvenshun.iteye.com/blog/232916 ???
Maven的核心是它的生命周期,生命周期什么都不做,因此Maven的安装文件很小。所有的事情都交给了插件来完成。比如说,Maven的default生命周期中定义了一个compile阶段,这个定义本身什么都不会做,真正编译代码的是Compiler插件,它的groupId是org.apache.maven.plugins,artifactId是maven-compiler-plugin。
---------------------------------------------------------------------------------------------------------------------------------------------------
解决Maven中OutOfMemory错误:https://juvenshun.iteye.com/blog/240257
当Maven项目很大,或者你运行诸如 mvn site 这样的命令的时候,maven运行需要很大的内存,在默认配置下,就可能遇到java的堆溢出。解决的方法是调整java的堆大小的值。
Windows环境中:设置环境变量,MAVEN_OPTS= -Xms128m -Xmx512m
Linux环境中:设置环境变量解决该问题,如,编辑文件 /etc/profile 如下:
MAVEN_OPTS=-Xmx512m
export JAVA_HOME MAVEN_HOME MAVEN_OPTS JAVA_BIN PATH CLASSPATH
使用Hudson:
用 Hudson + Maven做持续集成,并不幸也遇到了类似的错误,那么上述两种方式都将不再起作用了,因为Hudson使用自己的maven-agent来启动Maven,不会去调用Maven的脚本,自然相应的配置也就无效了。
好在Hudson也给为我们提供了配置点,在Hudson的项目配置页面中,有一块Build区域,这里我们已经设置了Root Pom和Goals。注意该区域的右下角有一个"Advanced..."按钮,点击会看到MAVEN_OPTS输入框,这里输入"-Xmx512m"就OK了。
m2eclipse中:
类似以上的方法都会失效,所幸m2eclipse提供了配置点。步骤如下:
项目上右击 -> Run As -> Run Configurations -> Maven Build 上右击 -> New
这时会看到一个maven运行配置对话框,这里面其它的配置我不多解释了,为了解决内存溢出的问题,我们可以选择第二个TAB: JRE,然后在VM arguments中输入配置如:-Xms128m -Xmx512m。
---------------------------------------------------------------------------------------------------------------------------------------------------
现实中的Maven项目:https://juvenshun.iteye.com/blog/242651 ???
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven疑难排解:https://juvenshun.iteye.com/blog/261888
如何诊断在Maven构建过程中碰到的问题?可以看一下这些手段:
2. 有时候遇到奇怪问题的时候,清理一下你的本地仓库。检查一下snapshots的更新策略。
3. 使用:
mvn help:effective-pom 查看有效POM
mvn help:effective-settings 查看有效settings
mvn help:active-profiles 查看激活的profile
这些命令会检查所有的的pom文件,settings文件,profile文件,帮助你查看其中的差异和影响。可能有些人在~/.m2/settings.xml 或者M2_HOME/conf/settings.xml做了自定义。
4. 你是否正使用公共仓库?时候有两台机器访问不同的仓库?如果你没有使用Nexus,我建议你下载并运行使用它 ,它能让你更好的了解配置仓库,并且是一个很好的发布构件的地方。
5. 使用-X参数查看Maven详细运行情况,如 mvn clean install -X ,让Maven打开debug日志。
6,将完整的异常信息,pom.xml, settings.xml 发到我们的讨论组:http://groups.google.com/group/maven-zh ,这里总有热心的人帮助你。
---------------------------------------------------------------------------------------------------------------------------------------------------
使用仓库管理器——Sonatype Nexus的九大理由: https://juvenshun.iteye.com/blog/285059 ???
简单,好处多多
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven最佳实践:遵循约定:https://juvenshun.iteye.com/blog/293975
Maven是服务于项目生命周期的(有些人说它是build工具,但build只是生命周期的一部分),它试图抽象整个项目生命周期,实际上它也做到了。几乎所有的项目都离不开Mave所定义的生命周期阶段(clean compile test package site...)。不止如此,基于这些阶段,Maven通过插件提供了绝大部分的默认实现,它们不用做任何配置(或者仅需要很少的配置),就能帮你完成你的工作。
使用基于Ant的build.xml文件,复杂,且难以在不同项目间移植。
现在看看使用Maven我们需要什么配置,就一个pom.xml文件:
<project> <modelVersion>4.0.0</modelVersion> <groupId>org.sonatype.mavenbook</groupId> <artifactId>my-project</artifactId> <version>1.0</version> </project>
不用惊讶,Maven不会变魔术,它能做到这么简单,是有条件的,条件就是你要遵守Maven约定。pom.xml所在的目录应为项目的根目录,假设该目录为${proj-dir},那么Maven有以下假设:
- ${proj-dir}/src/main/java —— 存放项目的.java文件。
- ${proj-dir}/src/main/resources —— 存放项目资源文件,如spring, hibernate配置文件。
- ${proj-dir}/src/test/jave —— 存放所有测试.java文件,如JUnit测试类。
- ${proj-dir}/src/test/resources —— 测试资源文件。
- ${proj-dir}/target —— 项目输出位置。
运行一条mvn clean package命令,Maven会帮你清除target目录,重新建一个空的,编译src/main/java类至target/classes,复制src/main/resources的文件至target/classes,编译src/test/java至target/test-classes,复制src/test/resources的文件至target/test-classes;然后运行所有测试;测试通过后,使用jar命令打包,存储于target目录。Maven做的事情一点也不少,只是都对用户隐蔽起来了,它只要求你遵循它的约定。
这么做有什么好处呢?第一,显而易见,配置大量减少了,随着项目变得越复杂,这种优势就越明显。第二,我这里要强调的是,对于软件工程来说,所有使用Maven的项目,对外都暴露统一的命令集。如mvn clean install。只要项目被正确配置好了,任何一个新人,输入一行Maven命令,就能将项目构建起来了,这大大减少了交流学习的时间。、
其实基本上所有的约定,或者说默认配置,都可以在Maven的超级POM(super pom)中找到。由于所有的POM都继承了这个超级POM(类似于java中所有类都继承于Object),因此它的默认配置就被继承了。以Maven 3.6.0为例,你可以在%m2_home%/lib/下看到一个名为XXX.jar的文件,打开这个文件,可以找到org/apache/maven/project/pom-4.0.0.xml这个文件,这就是超级POM。
Maven提供了一套科学的默认配置,它要求你遵循这些配置约定,然后它就会帮你处理日常的事务compile, test, package等等。使用Maven的时候,你应该尽可能遵循它的配置约定,一方面可以简化配置,另一方面可建立起一种标准,减少交流学习成本。一旦你习惯了这种约定,你得到的回报是巨大的。反之,恣意的做自定义,想要Maven像Ant一样听你的话,那么你会讨厌Maven,Maven也会讨厌你。
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven最佳实践:划分模块:https://juvenshun.iteye.com/blog/305865
所有用Maven管理的真实的项目都应该是分模块的,每个模块都对应着一个pom.xml。它们之间通过继承和聚合(也称作多模块,multi-module)相互关联。那么,为什么要这么做呢?我们明明在开发一个项目,划分模块后,导入Eclipse变成了N个项目,这会带来复杂度,给开发带来不便。
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven持续集成最佳实践:https://juvenshun.iteye.com/blog/319267
---------------------------------------------------------------------------------------------------------------------------------------------------
m2e:为Eclipse引入Maven(上):https://juvenshun.iteye.com/blog/322875
---------------------------------------------------------------------------------------------------------------------------------------------------
m2e:为Eclipse引入Maven(下):https://juvenshun.iteye.com/blog/322946
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven最佳实践:管理依赖:https://juvenshun.iteye.com/blog/337405
---------------------------------------------------------------------------------------------------------------------------------------------------
Nexus入门指南(图文): https://juvenshun.iteye.com/blog/349534
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven最佳实践:Maven仓库:https://juvenshun.iteye.com/blog/359256
---------------------------------------------------------------------------------------------------------------------------------------------------
Maven最佳实践:版本管理:https://juvenshun.iteye.com/blog/376422
---------------------------------------------------------------------------------------------------------------------------------------------------
按需构建多模块,玩转Maven反应堆:https://juvenshun.iteye.com/blog/565240