原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79551210

这里给大家详细说一下Maven的运行机制,让大家不仅知其然,更知其所以然。

1、插件保存在哪里?

与我们所依赖的构件一样,插件也是基于坐标保存在我们的Maven仓库当中的。在用到插件的时候会先从本地仓库查找插件,如果本地仓库没有则从远程仓库查找插件并下载到本地仓库。

与普通的依赖构件不同的是,Maven会区别对待普通依赖的远程仓库与插件的远程仓库。前面提到的配置远程仓库只会对普通的依赖有效果。当Maven需要的插件在本地仓库不存在时是不会去我们以前配置的远程仓库查找插件的,而是需要有专门的插件远程仓库,我们来看看怎么配置插件远程仓库,在pom.xml加入如下内容:

<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<name>nexus</name>
<url>http://192.168.0.70:8081/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>

大家可以发现,除了pluginRepositoriespluginRepository与以前配置远程仓库不同以外,其他的都是一样的,所代表的含义也是一样的。Maven的父POM中也是有内置一个插件仓库的,我现在用的电脑安装的是Maven 3.0.4版本,我们可以找到这个文件:${M2_HOME}/lib/maven-model-builder-3.0.4.jar,打开该文件,能找到超级父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven项目都继承该配置。

我们来看看默认的远程插件仓库配置的是啥:

<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>

默认插件仓库的地址就是中央仓库咯,它关闭了对snapshots的支持,防止引入snapshots版本的插件而导致不稳定的构件。一般来说,中央仓库所包含的插件完全能够满足我们的需要,只有在少数情况下才要配置,比如项目的插件无法在中央仓库找到,或者自己编写了插件才会配置自己的远程插件仓库。

2、插件命令运行解析

我们来看这样一个命令:

mvn compiler:compiler

这个命令会调用maven-compiler-plugin插件并执行compiler目标,大家有木有觉得很神奇?我们在pom.xml中配置插件往往是这样:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source> <!-- 源代码使用的开发版本 -->
<target>1.7</target> <!-- 需要生成的目标class文件的编译版本 -->
</configuration>
</plugin>

maven-compiler-plugin插件默认执行的目标为compiler,那么命令的完整写法应该是:mvn org.apache.maven.plugins:maven-compiler-plugin:3.1:compiler才对啊,为什么mvn compiler:compiler也能完美的执行?

我们来看看Maven到底干了些神马来做到如此牛逼的功能:

① 插件默认groupId

Maven默认以org.apache.maven.plugins作为groupId,到这里我们的命令应该是长这样的:

mvn org.apache.maven.plugins:compiler:compiler

我们也可以配置自己默认的groupId,在Maven的settings.xml中添加如下内容,前面提过最好将settings.xml放在用户目录的.m2下:

<pluginGroups>
<!-- pluginGroup
| Specifies a further group identifier to use for plugin lookup.
<pluginGroup>com.your.plugins</pluginGroup>
-->
<pluginGroup>com.your.plugins</pluginGroup>
</pluginGroups>

不过说实在的,没必要动他就别去动他了,我们用Maven只是解决一些刚需的问题,没必要的设置就尽量不去动他,别把Maven搞得太复杂,虽然Maven的却有点小复杂,跟大家扯这些只是希望大家能够对maven理解的更深入那么一点点,并不是建议大家一定要去使用某些东西,大家在平时的开发中要谨记这一点。

② 我们来看看Maven插件远程仓库的元数据org/apache/maven/plugins/maven-metadata.xml,Maven默认的远程仓库是http://repo.maven.apache.org/maven2/,所有插件元数据路径则是:http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml,我们找到compiler插件的元数据,如图:

这里会根据prefix指定的前缀找到对应的artifactId,到这里我们的命令应该长成了这样:

mvn org.apache.maven.plugins:maven-compiler-plugin:compiler

③ 我们再根据groupIdartifactId找到maven-compiler-plugin插件单个的元数据,路径为http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml,如图:

maven将所有的远程插件仓库及本地仓库元数据归并后,就能找到release的版本(maven3后为了保证项目构建的稳定性默认使用release版本),到这里命令就被扩展成为这样:

mvn org.apache.maven.plugins:maven-compiler-plugin:3.6.0:compiler

如果执行的是mvn compiler:compiler命令,由于maven-compiler-plugin的最新版本已经到了3.6.0,则默认会使用此版本。最后的compiler则是插件要执行的目标咯,看到这里大家应该明白mvn compiler:compiler命令为什么能够得到完美的运行了吧。

3、Maven超级POM

最后给大家把超级父POM贴出来,再次强调,如果我们没有在自己的pom.xml中配置相应的内容,则默认会使用超级父POM配置的内容。我现在用的电脑安装的是Maven 3.5.2版本,我们可以找到这个文件:${M2_HOME}/lib/maven-model-builder-3.5.2.jar,打开该文件,能找到超级父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven项目都继承该配置。

<?xml version="1.0" encoding="UTF-8"?>

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
--> <!-- START SNIPPET: superpom -->
<project>
<modelVersion>4.0.0</modelVersion> <repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories> <pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories> <build>
<directory>${project.basedir}/target</directory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
<pluginManagement>
<!-- NOTE: These plugins will be removed from future versions of the super POM -->
<!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.3.2</version>
</plugin>
</plugins>
</pluginManagement>
</build> <reporting>
<outputDirectory>${project.build.directory}/site</outputDirectory>
</reporting> <profiles>
<!-- NOTE: The release profile will be removed from future versions of the super POM -->
<profile>
<id>release-profile</id> <activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation> <build>
<plugins>
<plugin>
<inherited>true</inherited>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles> </project>
<!-- END SNIPPET: superpom -->

很多插件是超级父POM当中并没有配置的,如果用户使用某个插件时没有设定版本,那么则会根据我上述所说的规则去仓库中查找可用的版本,然后做出选择。在Maven2中,插件的版本会被解析至latest。也就是说,当用户使用某个非核心插件且没有声明版本的时候,Maven会将版本解析为所有可用仓库中的最新版本,latest表示的就是最新版本,而这个版本很有可能是快照版本。

当插件为快照版本时,就会出现潜在的问题。昨天还好好的,可能今天就出错了,其原因是这个快照版本发生了变化导致的。为了防止这类问题,Maven3调整了解析机制,当插件没有声明版本的时候,不再解析至latest,而是使用release。这样就避免了由于快照频繁更新而导致的不稳定问题。但是这样就好了吗?不写版本号其实是不推荐的做法,例如,我使用的插件发布了一个新版本,而这个release版本与之前的版本的行为发生了变化,这种变化依然可能导致我们项目的瘫痪。所以使用插件的时候,应该一直显式的设定版本,这也解释了Maven为什么要在超级父POM中为核心插件设定版本咯。

结束语:当你感到悲哀痛苦时,最好是去学些什么东西,学习会使你从悲哀痛苦中走出来,学习会使你永远立于不败之地。说实在的,不要太在意眼前所发生的一切,更重要的是培养自己的个人能力,如今待在公司亦或者跳槽,决定你能不能继续走下去的一定是你的个人能力,作为年轻人,在公司更看重的不应该是薪水的高低,而是公司能给你带来多大的成长环境。找个好的公司其实不比找个合适的女朋友简单,作为年轻人我们一定要不断的提升个人能力,就跟找女朋友似的,往往就是你越有本事就越能够不将就,你个人能力越强则越有选择公司的资本。

Maven 教程(13)— Maven插件解析运行机制的更多相关文章

  1. (十三)Maven插件解析运行机制

    这里给大家详细说一下Maven的运行机制,让大家不仅知其然,更知其所以然. 1.插件保存在哪里? 与我们所依赖的构件一样,插件也是基于坐标保存在我们的Maven仓库当中的.在用到插件的时候会先从本地仓 ...

  2. Maven教程:tutorialspoint-maven

    来自turorialspoint的Maven教程(英文),官网:http://www.tutorialspoint.com/maven/index.htm 这个教程在国内已经被翻译成中文,官网:htt ...

  3. 13 Maven 编写插件

    Maven 编写插件 Maven 的任何行为都是由插件完成的,包括项目的清理.绵编译.测试以及打包等操作都有其对应的 Maven 插件.每个插件拥有一个或者多个目标,用户可以直接从命令行运行这些插件目 ...

  4. 第二节:Maven的运行机制

    Maven 的运行机制分为两个分别是生命周期和插件 首先我们来说说Maven的生命周期 1.1:生命周期是个个阶段组成的 1.2:Maven的生命周期是相互独立的,他们之间没有交集 1.3:阶段是有顺 ...

  5. maven(三):maven项目结构及其运行机制

    在上一篇中讲了如何创建maven项目,现在回到那个项目 项目结构 src/main/java:java代码目录 src/main/resources:资源目录,比如spring.xml文件,prope ...

  6. Maven配置tomcat和jetty插件来运行项目

    针对eclipse中的Run on Server有些情况下并不是那么好操作,比如配置maven下的springmvc插件,如果使用此方法运行会很容易出现组件缺少导致错误出现一大堆的问题. 那么针对这种 ...

  7. Maven 依赖调解源码解析(二):如何调试 Maven 源码和插件源码

    本文是系列文章<Maven 源码解析:依赖调解是如何实现的?>第二篇,主要介绍如何调试 Maven 源码和插件源码.系列文章总目录参见:https://www.cnblogs.com/xi ...

  8. Maven教程(转载)

    转载自:http://www.yiibai.com/maven/ Apache Maven是一个软件项目管理和综合工具.基于项目对象模型(POM)的概念,Maven可以从一个中心资料片管理项目构建,报 ...

  9. Maven实战——常用Maven插件介绍

    maven nexus 库已上传了第三方jar,但就是用mvn compile下不到本地 回答于 2013-06-04 14:40 你是通过何种方式上传到nexus的? 有给pom文件吗? 如果是单纯 ...

随机推荐

  1. 数据库xp_cmdshell使用

    首先也开启组件. sp_configure reconfigure go sp_configure reconfigure go 删除本地文件,注意是删除数据库所在的服务器的本地文件. exec ma ...

  2. python 排序 归并排序

    算法思想 迭代法: 归并算法一共有两种思想,笼统的说,这两种思想的区别就在于一种不分割未排序的序列(直接将序列看为n个个数为1的子序列),这种称为---迭代法 直接从队头开始,两两合并为一个个数为2的 ...

  3. 【python+selenium学习】常见错误: 'gbk' codec can't decode byte 0xb0 in position 30

    最近编写的自动化脚本,数据部分使用到了从配置文件中取,即自定义config.ini,但是在读取配置文件的时候却报错了'gbk' codec can't decode byte 0xb0 in posi ...

  4. MySQL难点语法——子查询

    本篇主要通过练习来讲解子查询的知识,进入正题之前,先熟悉数据表,表格的数据可以先不用管,主要是熟悉表格的字段名 这里子查询分为三个部分: 1.where条件子查询 这个子查询和普通的查询没什么区别,主 ...

  5. EntityFramework 基类重写

    /* * ------------------------------------------------------------------------------ * * 创 建 者:F_Gang ...

  6. Java 之 枚举(Enum)

    一.枚举 1.概述 枚举:JDK1.5引入的,类似于穷举,一一罗列出来 Java 枚举:把某个类型的对象,全部列出来 2.应用 什么情况下会用到枚举类型? 当某个类型的对象是固定的,有限的几个,那么就 ...

  7. JVM常见面试题及答案

    11.JVM内存分哪几个区,每个区的作用是什么? java虚拟机主要分为以下一个区: 方法区:1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区 ...

  8. Linux shell变量详解

    Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个 ...

  9. ant笔记

    目录 ant远程部署 ant的使用,命令! 参考文献: ant+maven一键打包springboot上传服务器发布 判断linux文件.文件夹是否存在 shell中脚本参数传递的两种方式 shell ...

  10. 《linux就该这么学》课堂笔记15 vsftpd文件传输、Samba/NFS文件共享

    1.为了能够在如此复杂多样的设备之间(Windows.Linux.UNIX.Mac等不同的操作系统)解决问题解决文件传输问题,文件传输协议(FTP)应运而生. FTP服务器是按照FTP协议在互联网上提 ...