关于maven-基本

BitTigerio 2017-11-29

笔记

Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。

Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。

这两段来自百度的描述,其实说来还是很准确的!!

所以,总体来说,pom是整个maven的核心,或者说,是使用者,也就是我们的核心关注点!
***

缘由

可以说现在稍微大一点的公司,稍微有点追求的公司,都在使用这个了吧,当然我也是工作之后才知道的...

刚工作那会儿,只是先学会用它而已,具体是怎么个回事并不是很清楚,出现问题了,可能只知道查下冲突啊,clean一下再package一下啊,install从来不用,都是直接deploy的。究其本质,都是不懂maven所致。
***

中&左右

如上所述,maven是用来管理项目的,by描述语言,通过项目的依赖,构建来进行管理。引用下官网的描述:

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.

挑重点:基于POM,管理项目的build、报告和文档。

所以,学习maven,核心是了解pom文件,然后搞清楚是如何管理项目的。

关于pom文件,首先要明白,这是个xml文件:

可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。

也就是说,xml重点在于传递数据,而在于

它被设计用来传输和存储数据,其焦点是数据的内容。
超文本标记语言被设计用来显示数据,其焦点是数据的外观。

所以他传递的信息,在这里就是项目的依赖,或者说项目的结构。pom文件描述了整个项目的依赖结构。

下面是一个最简单的pom文件的代码

<?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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.andy.maven</groupId>
  <artifactId>maven-test-server</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <modules>
    <module>maven_test_biz</module>
    <module>untitled</module>
  </modules>

  <name>maven-test-server</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

具体每块是什么,如下图所示
关于maven-基本

所以,对于maven来说,一切都要从如何描述项目结构出发,分析pom中的每一个元素。

包,可以说是pom中最基本的元素了,不管是项目所依赖的各种包,还是包之间的关系,还是其他什么,都是以包为对象的。

包,其实是一个版本,也可以说是是一个项目,所以pom所描述的项目也都是一个包:

<groupId>com.andy.maven</groupId>
  <artifactId>maven-test-server</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>

这个东西,就是一个包的坐标!!不管包是在那个仓库,都是根据这个坐标去加载进来的。需要强调的是,这四个值都是必须的,只不过最后一个默认情况下是jar包。

  • 仓库

那么,有了包,包从哪里来咧?就是仓库。

对于maven本身来说,有一个中心仓库,讲道理所有的包都在上面的,但是这里有两个需要特别注意的地方:

  1. 一个团队中,只要有>=2个人需要访问中心仓库,就应该考虑者自建私库
  2. 配置镜像中心仓库;

第二个好理解,第一个的话,不要嫌麻烦,具体给出原因如下引用:

  1. 九个使用私库的原因

    (译自:Nine Reasons to Use a Repository Manager: Sonatype Nexus )

    目前有很多组织使用了一些工具依赖于Maven仓库,但他们并没有采用一个仓库管理器,对于这一点我十分惊讶。可能没人提出来这一点,没人站出来告诉别人使用一个仓库管理器能带来什么好处。我经常能从很多不使用Maven仓库管理器的组织那里听到这样的字眼:“我们不需要那么复杂……”,或者“中央仓库够了,我们不需要在本地建立这样一个仓库”

    不用说,关于什么“是”一个好的Maven仓库,还存在很多误解。首先,安装它一点都不复杂。你只需要花几分钟就能下载并安装好Nexus ,而且我们已经特意的使得这一过程变得容易,并且尽可能减少侵入性。第二,一个缓存远程仓库的仓库管理器并不会缓存所有的东西。一个好的仓库管理器只会按需的缓存内容。这里是为那些排斥仓库管理器的人提供的九条理由。

    九 - 加速构建

    当你在Maven中运行多模块项目构建的时候,你认为Maven是怎么知道它是否需要更新插件或者snapshot依赖的呢?它需要为所有需要检验的构件向服务器提出一个请求。即使没什么变化,如果你的项目依赖于一些SNAPSHO或者你没有指定插件版本,Maven就必须对远程仓库提交数十至数百的请求。所有这些通过公共Internet的请求加起来会浪费很多时间。我看到过一个复杂的构建,在安装了本地Nexus之后,节省了75%的时间。不要再浪费编码时间去无畏的等待Maven对远程仓库的请求了。

    八 - 节省你自己的带宽

    组织越大,节省带宽就越重要。如果你有数千开发者不停的浪费带宽在下载同样的文件,那么使用一个仓库管理器可以保存一个本地的缓存,从而节省大量的带宽。即使一些小型的组织,对于网络连接和IT运行的预算也有限,也必须处理很多开发人员浪费带宽不停重复下载同样文件的问题。

    七 - 节省中央Maven仓库的带宽

    这可以说是一种公德心,利己利人。运行一个中央Maven仓库不容易。基于全球软件构件的需要,服务数百万的请求,数T的数据,一点都不便宜。简单的事情如每个组织安装一个本地仓库管理器可以大量降低对中央仓库的带宽需求(至少一半)。如果你有大于两个开发者在使用Maven,那么请为了中央仓库义务的安装一个仓库管理器。

    六 - 可预见性和稳定性

    过去一些年,你多久会遇到一次由于断网引起的业务彻底中断?让每天的工作依赖于中央仓库意味着你正依赖于因特网连接(事实上中央仓库是24/7可用的)。虽然我们有信心保持中央仓库24/7运行,但你还是应该花一点时间建立你自己的仓库,以确保你的开发团队不会由于任意一方的网络中断而惊讶。如果你有本地的仓库管理器,如Nexus,你可以确保即使你失去了网络连接你还能工作。

    五 - 控制和审计

    当然,你已经转移到了Maven(或者Ivy,Ivy读取同样的仓库),而且你有一房间的开发人员,他们被授权添加或者删除依赖,以及试验新的框架。我们都清楚。开发人员可能都对试验新框架更感兴趣,而不是正常工作。但不幸的是,很多时间,一个架构师,或者一个架构小组需要建立组织使用的基线标准。Nexus提供这一层次的控制。

    如果你需要对那些组织中使用的构件进行更多的监管,看一下Nexus。没有仓库管理器,对于那些你开发团队会使用的依赖你只有很少的控制。

    四 - 能够部署第三方构件

    你希望能够基于开源数据库工作,如MySQL或者Postgres,但是你组织有不同的需求,和Oracle有一个长期的支持合同。因此,你有一系列JAR文件不能够从公共Maven仓库获得。你需要将这些构件部署到仓库中,然后配置Maven去读取该仓库。

    你不用为此手工编写一些POM,只要下载Nexus,然后花两三分钟时间使用这个免费,功能强大的工具来创建一个仓库,部署第三方构件。Nexus提供了直观的上传界面,你可以使用它上传任意JAR文件,然后在你项目依赖中引用它。

    三 - 可以建立本地内部仓库

    非常好,你正使用Maven,每个人都从头开始根据代码执行快速的构建。整个一年,这都工作得很好,但是当系统变得庞杂,程序员开始抱怨构建花了太多时间。你可以通过分割项目解决这个问题,然后使用Nexus作为一个内部仓库来存储内部的依赖。

    例如,有一个公司有30个开发者,被分成三个10人的小组,每个小组关注于系统的不同部分。如果不能够很方便的实现内部依赖共享,类似的小组就不得不创建一个基于文件系统的仓库,或者将系统整个的构建,那样依赖就能被安装到每个开发者的本地仓库。

    另一种选择是将项目分隔成不同的模块,每个模块都依赖于存储在Nexus仓库中的构件。这么做之后,小组之间可以通过基于Nexus交换已编译的snapshot和release构件来协作。换句话说,你不需要让没个开发者签出巨大的包含整个组织代码的多模块项目。组织中的每个小组可以发布snapshot构件至本地Nexus,从而每个小组可以维护一个只包含它负责代码的项目结构。

    在宏观层次,公共Maven仓库及建立项目定义的严格制度,可以充当开源世界中跨项目协作的基础。(这听起来是不是很重要,很“令人敬畏”?)

    二 - 可以建立公共仓库

    如果是一个开源项目,或者你将软件发布到公共环境,Nexus可以是一个你用来为外部用户提供构件服务的工具。这么想……上你发布项目的一个版本是什么时候?假设它没被发布到Maven仓库中,你很可能需要编写一些脚本来打包此次发布的内容,可能某些特定的人需要使用一个超级权限的密钥来为该发布签名。然后,你必须将其上传到一些web服务器上,然后确保相应的页面被更新,正确描述了此次发布。这里有很多不必要的复杂度。

    如果你正使用Nexus,它可以被配置成一个暴露在公共世界的宿主仓库,你就可以使用Maven的打包和装配能力,以及Maven仓库的结构,来使得一次发布变得非常的简单。而且,这不仅仅正对于JAR文件和Java web应用;Maven仓库可以存储任何种类的构件(事实上,我正考虑使用Maven仓库结构来发布用户文档和视频内容)。Nexus,及Maven仓库,总得来说为发布定义了大家都知道的结构。如果你正编写一些Java类库,将其发布到你自己的Nexus实例中,然后提供公共仓库服务,就可以让人们更容易的马上开始使用的的代码。

    一 - 这相当简单

    类似的事情我经常听到。有一个早晨的Scrum会议,或者项目状态的周会。一些低层的程序员怯懦的举起他的手说,“我们可以安装一个如Nexus的仓库软件么?我认为它能帮助我们显著的加速很多工作。”一直被时间的预算压着的开发经理,听到单词“安装”和“软件”,就马上否决了这件事情,理由是他们没有时间做这种基础工作,因为这不是“需求驱动”的。(我看到过这种事情发生。)

    这个经理不知道的是,在一个共享的机器上安装Nexus,然后配置随后的系统服务可能是需要花不到十分钟的时间。事实上,你可以在免费的Maven书上读到安装说明。安装Nexus十分的简单。我已经有了一些实践,但是我认为任何一个知道如何操作web浏览器的人都可以在几分钟内完成这项工作。

  2. 使用私库的教程

1、 为什么使用Nexus
如果没有私服,我们所需的所有构件都需要通过maven的中央仓库和第三方的Maven仓库下载到本地,而一个团队中的所有人都重复的从maven仓库下载构件无疑加大了仓库的负载和浪费了外网带宽,如果网速慢的话,还会影响项目的进程。很多情况下项目的开发都是在内网进行的,连接不到maven仓库怎么办呢?开发的公共构件怎么让其它项目使用?这个时候我们不得不为自己的团队搭建属于自己的maven私服,这样既节省了网络带宽也会加速项目搭建的进程,当然前提条件就是你的私服中拥有项目所需的所有构件。

2、Nexus下载
下载地址:http://www.sonatype.org/nexus/go

3、Nexus启动
我下载的是zip包,解压后进入\nexus-2.1.2-bundle\nexus-2.1.2\bin\jsw,根据操作系统类型选择文件夹,我选的是windows-x86-32文件夹,进入后可看到如下所示bat文件。

图(1)
双击console-nexus.bat运行。游览器中输入http://127.0.0.1:8081/nexus/,出现图(2)所示就代表nexus已经启动成功。

图(2)
8081为默认的端口号,要修改端口号可进入nexus-2.1.2-bundle\nexus-2.1.2\conf\打开nexus.properties文件,修改application-port属性值就可以了。
默认的用户名和密码:admin/admin123,登录后看到图(3)所示:

图(3)

4、Nexus仓库
nexus的仓库类型分为以下四种:
group: 仓库组
hosted:宿主
proxy:代理
virtual:虚拟
首次登陆nexus后可以看到以下一个仓库组和多个仓库。

图(4)
Public Repositories: 仓库组
3rd party: 无法从公共仓库获得的第三方发布版本的构件仓库
Apache Snapshots: 用了代理ApacheMaven仓库快照版本的构件仓库
Central: 用来代理maven中央仓库中发布版本构件的仓库
Central M1 shadow: 用于提供中央仓库中M1格式的发布版本的构件镜像仓库
Codehaus Snapshots: 用来代理CodehausMaven 仓库的快照版本构件的仓库
Releases: 用来部署管理内部的发布版本构件的宿主类型仓库
Snapshots:用来部署管理内部的快照版本构件的宿主类型仓库

5、配置nexus

5.1、开启远程索引

新搭建的neuxs环境只是一个空的仓库,需要手动和远程中心库进行同步,nexus默认是关闭远程索引下载,最重要的一件事情就是开启远程索引下载。登陆nexus系统,默认用户名密码为admin/admin123。
点击左边Administration菜单下面的Repositories,找到右边仓库列表中的三个仓库Apache Snapshots,Codehaus Snapshots和Maven Central,然后再没有仓库的configuration下把Download Remote Indexes修改为true。如下图

然后在Apache Snapshots,Codehaus Snapshots和Maven Central这三个仓库上分别右键,选择Repari Index,这样Nexus就会去下载远程的索引文件。

这样设置以后, Nexus会自动从远程中央仓库下载索引文件, 为了检验索引文件自动下载是否生效,可以却换到Browse Index

在左边菜单栏里面有个Artifact Search, 在输入框里面输入你想要搜索的构件名字,比如:maven, 那么查询结果如下:

5.2建立宿主仓库

新 建公司的内部仓库,步骤为Repositories –> Add –> Hosted Repository,在页面的下半部分输入框中填入Repository ID和Repository Name即可,比如分别填入
zfy 和 zfy repostiory,另外把Deployment Policy设置为Allow Redeploy,点击save就创建完成了。
这里我点击添加宿主类型的仓库,在仓库列表的下方会出现新增仓库的配置,如下所示:

图(6)
点击save按钮后就会在仓库列表中看到刚才新增的仓库。

5.3、创建Nexus仓库组
Nexus 中仓库组的概念是Maven没有的,在Maven看来,不管你是hosted也好,proxy也好,或者group也好,对我都是一样的,我只管根据 groupId,artifactId,version等信息向你要构件。为了方便Maven的配置,Nexus能够将多个仓库,hosted或者 proxy合并成一个group,这样,Maven只需要依赖于一个group,便能使用所有该group包含的仓库的内容。
neuxs- 1.9.2.3中默认自带了一个名为“Public Repositories”组,点击该组可以对他保护的仓库进行调整,把刚才建立的公司内部仓库zfy repostiory加入其中,这样就不需要再在maven中明确指定内部仓库 的地址了。同时创建一个Group ID为public-snapshots、Group Name为Public Snapshots Repositories的组,把Apache Snapshots、Codehaus Snapshots、Snapshots和zfy repostiory加入其中。

到这里neuxs的安装配置就完成了,下面介绍如何在maven中使用自己的私服。

5.4、创建Nexus代理仓库
点击菜单栏上的Add按钮后选择Proxy Repository,看到如下所示配置界面:

图(7)

以上本人分别创建 了  hosted和group ,没有创建proxy,经maven测试通过。

6、 settings.xml的配置
[html] view plaincopyprint?


[html] view plaincopyprint?

[html] view plaincopyprint?
7、 maven 项目 的pom.xml配置
[html] view plaincopyprint?

[html] view plaincopyprint?

8、<a class="uri">mvn:deploy命令上传包,会发现下载路径必不是中央库的路径,而是nexus里面的仓库组路径。这个说明配置环境成功</a>。


另外,关于仓库,还有两点需要说明下:

  1. 仓库的设定在pom文件中,以及,配置文件中;distributionManagement
  2. 插件也是有仓库的,设置同上;
  • 依赖关系

有了包,以及包的来源,如何组织这些包,maven使用了标签

当然,上述描述是最简单的一种情况,由俭入奢,我们谈到两种情况:

  1. profile

配置,使得maven可以使得同一个项目在不同环境中,可以动态配置参数、插件,依赖的包,以及依赖的包的属性值等等。

<profile>
            <id>dev</id>
            <properties>
                <maven.test.skip.exec>false</maven.test.skip.exec>
                <jsf.alias>_dev</jsf.alias>
                <iUserTagService.alias>tag-interface</iUserTagService.alias>
            </properties>
            <build>
                <resources>
                    <resource>
                        <directory>${profiles.dir}/dev</directory>
                    </resource>
                </resources>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-antrun-plugin</artifactId>
                        <version>1.7</version>
                        <executions>
                            <execution>
                                <id>prepare-node-npm</id>
                                <phase>validate</phase>
                                <goals>
                                    <goal>run</goal>
                                </goals>
                                <configuration>
                                    <target>
                                        <copy todir="${basedir}/target/app">
                                            <fileset dir="${basedir}/app">
                                                <exclude name="**/node_modules"/>
                                            </fileset>
                                            <fileset file="${basedir}/fis-conf.js">
                                            </fileset>
                                            <fileset file="${basedir}/package.json">
                                            </fileset>
                                        </copy>
                                        <unzip src="target/app/node_modules.zip" dest="target"/>
                                        <unzip src="target/app/node.zip" dest="target"/>
                                        <copy file="target/node_modules/fis3/bin/fis.js" tofile="target/fis3"/>
                                        <copy file="target/app/package.json" tofile="target/package.json"/>
                                        <copy file="target/app/fis-conf.js" tofile="target/fis-conf.js"/>
                                        <chmod dir="target/fis3" perm="ugo+x"/>
                                        <chmod dir="target/node/node" perm="ugo+x"/>
                                    </target>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>com.github.eirslett</groupId>
                        <artifactId>frontend-maven-plugin</artifactId>
                        <version>1.0</version>
                        <configuration>
                            <workingDirectory>target</workingDirectory>
                            <installDirectory>target</installDirectory>
                            <environmentVariables>
                                <APPDATA>${basedir}/target/APPDATA</APPDATA>
                            </environmentVariables>
                        </configuration>
                        <executions>
                            <execution>
                                <id>npm run build</id>
                                <goals>
                                    <goal>npm</goal>
                                </goals>
                                <configuration>

                                    <arguments>run dev-copy</arguments>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>

                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>2.2</version>
                        <configuration>
                            <webResources>
                                <resource>
                                    <directory>target/output/src/main/webapp/</directory>
                                </resource>
                                <resource>
                                    <directory>src/main/webapp/WEB-INF</directory>
                                    <targetPath>WEB-INF</targetPath>
                                </resource>
                            </webResources>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

另外,如此方便的功能,如果都是上述这样子的代码,一定不是程序员们所期待的,所以,ide中各种maven的插件就带来了方便的profile的管理,在此不再赘述。

  1. 项目关系

前面说过,项目本身就会是一个包,有时候/常常,会把多个项目共同开发,然后每个项目依赖的东西其实都差不多,于是诞生了模块的概念,对应就有了项目关系。

项目关系中最重要的就是多模块和继承了。

多模块好理解,继承其实和对象的继承是一样样的,只不过继承的是对包的依赖关系,其他类似,比如需要在总的pom文件中声明module,比如需要子模块表示自己的爸爸是哪个类似这样。

  1. 依赖冲突

由于依赖具有传递性,比如a依赖了b,b依赖了c,那么a就依赖了c,所以引用包的过程中,很容易出现预见不到的依赖冲突问题。

作为菜鸟程序员,一般而言,我都是打日志看下,然后把旧版本的直接exclusion掉,搞定之,百试不爽...

命令如下

mvn -Pdev clean package -Dmaven.test.skip=true dependency:tree -Dverbose > tree.log

mvn dependency:tree -Dverbose > tree.log
  • 生命周期

就不献丑了,直接引用一篇写的很详细明了的
博客

  • 常用命令

这里主要是在eclipse中使用maven,因此只使用到了一部分命令,整理下来方便以后查阅。

生成清除Eclipse项目结构:
mvn eclipse:eclipse
mvn eclipse:clean

清理(删除target目录下编译内容)
mvn clean

仅打包Web页面文件
mvn war:exploded

编译项目
mvn compile

打包发布
mvn package

打包时跳过测试
mvn package -Dmaven.test.skip=ture

还有很多命令目前还没有使用到,以后遇到再补充

本文地址:http://blog.csdn.net/kongxx/article/details/6993501

Maven用了很久了,命令一直记不住,其实想想就那个几个常用的,今天写下来,帮着记忆吧

创建一个简单的Java工程:mvn archetype:create -DgroupId=com.mycompany.example -DartifactId=Example
创 建一个java的web工程:mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.mycompany.app -DartifactId=my-webapp
打包:mvn package
编译:mvn compile
编译测试程序:mvn test-compile
清空:mvn clean
运行测试:mvn test
生成站点目录: mvn site
生成站点目录并发布:mvn site-deploy
安装当前工程的输出文件到本地仓库: mvn install
安 装指定文件到本地仓库:mvn install:install-file -DgroupId=

  1. 创建Maven的普通java项目:
    mvn archetype:create
    -DgroupId=packageName
    -DartifactId=projectName
  2. 创建Maven的Web项目:
    mvn archetype:create
    -DgroupId=packageName
    -DartifactId=webappName
    -DarchetypeArtifactId=maven-archetype-webapp
  3. 编译源代码: mvn compile
  4. 编译测试代码:mvn test-compile
  5. 运行测试:mvn test
  6. 产生site:mvn site
  7. 打包:mvn package
  8. 在本地Repository中安装jar:mvn install
  9. 清除产生的项目:mvn clean
  10. 生成eclipse项目:mvn eclipse:eclipse
  11. 生成idea项目:mvn idea:idea
  12. 组合使用goal命令,如只打包不测试:mvn -Dtest package
  13. 编译测试的内容:mvn test-compile
  14. 只打jar包: mvn
  15. 只测试而不编译,也不测试编译:mvn test -skipping compile -skipping test-compile
    ( -skipping 的灵活运用,当然也可以用于其他组合命令)
  16. 清除eclipse的一些系统设置:mvn eclipse:clean

懒懒懒,再加上本身不怎么使用命令,暂且记下吧。
***

上下

似乎从maven出发,上下游没什么东西,可能主要是应用场景还不够丰富吧,姑且等待有问题出现的时候及时总结吧
***

结束

maven可以说是很大程度的解放了程序员在项目构建方面的问题,但提供简便的背后一定是复杂逻辑处理的掩盖,由此,maven可以说是外表清纯,内心复杂。

对于我们而言,还是好用就行,保持对maven问题重视即可。

相关推荐

XingKai / 0评论 2014-10-09