Fork me on GitHub

《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>
View Code

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> 
View Code

此外,修改资源文件如下:

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>
View Code

至此,运行 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>  
View Code

这个 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>  
View Code

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>  
View Code

在一个特殊的环境下,配置默认自动激活的 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

 

posted on 2022-12-01 18:42  loopever  阅读(45)  评论(0编辑  收藏  举报