Maven笔记

一、Maven基础

1.1 Maven功能

Maven能帮助我们干什么?它主要有两个功能:

  1. 依赖管理(jar包管理):在开发过程中需要大量jar包,我们只需要在Maven的主配置文件中添加相应jar包的标识,他就会自动下载相应jar包,不用我们自己去到处搜索jar包了
  2. 构建项目:我们可以通过Maven构建项目,它定义了一套生命周期,规范了构建流程,可以一键构建,提高了大型项目的开发效率
Maven构建流程

1.2 POM文件

每个maven项目都会有一个pom.xml文件, 在这个文件里面是通过坐标来唯一标识Maven依赖,坐标元素包括groupId、artifactId、version、packaging、classifier(前三个为必选),这些元素的含义:

  • groupId:定义当前Maven项目所属的实际项目
  • artifactId:定义实际项目中的一个Maven模块
  • version:定义Maven项目当前所处的版本
  • packaging:定义Maven项目打包方式, 通常打包方式与所生成构件扩展名对应,包括:jar(默认)、war、pom、maven-plugin等
  • classifier:用来帮助定义构建输出的一些附属构件(如javadoc、sources),不能直接定义项目的classifier,须有插件的帮助

这里提一下version版本的两种类型:

  • SNAPSHOT:泛指以-SNAPSHOT为结尾的版本号,用于保存开发过程中的不稳定版本号,在mvn deploy时会主动发布到快照版本号库中;而使用快照版本号的模块,在不更改版本号的情况下直接编译打包时,maven会自己主动从镜像server上下载最新的快照版本号
  • RELEASE:所有非-SNAPSHOT结尾的版本号则都被认定为RELEASE版本,即正式版,在mvn deploy时会自己主动发布到正式版本号库中;而使用正式版本号的模块在不更改版本号的情况下,编译打包时假设本地已经存在该版本号的模块则不会主动去镜像server下载

1.3 Maven依赖

Maven最著名的就是Maven的依赖管理,它使得我们不必再到开源项目的官网一个个下载开源组件,然后再放入classpath。一个依赖声明可以包含如下元素:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.2.7.RELEASE</version>

    <type>jar</type>
    <scope>compile</scope>
    <optional>false</optional>
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

依赖范围Scope

Scope 是用来限制Dependency的作用范围的, 他会影响maven项目在各个生命周期时导入的package的状态。常用scope见下图:

依赖范围Scope

依赖传递性

比如下图有Maven项目junit,项目commons-logging依赖junit,项目spring-core依赖commons-logging,项目my-app依赖spring-core;那么我们可以说my-app依赖junit;我们执行项目my-app时,会自动把spring-core、commons-logging、junit都下载导入到my-app项目的jar包文件夹中,这就是依赖的传递性。

依赖传递示例

假如现在不想执行my-app时把junit下载进来,那么我们可以用<exclusions>标签。

依赖调节的原则:

  • 如果依赖路径的长度不同,则短路优先
  • 依赖路径长度相同情况下,则先声明优先

依赖分析

mvn dependency:list
查看当前项目的已解析依赖
mvn dependency:tree
查看当前项目的依赖树
mvn dependency:analyze
自动化分析当前项目的依赖

IDEA可以安装一个很方便的插件Maven Helper来帮助我们进行依赖管理、排包等操作。

1.4 Maven仓库

Maven仓库只有两大类:

  1. 本地仓库:Maven在本地存储构件的地方;
  2. 远程仓库:在远程仓库中又分成了2种:
    a. 中央仓库:中央仓库是默认的远程仓库,maven在安装的时候,自带的就是中央仓库的配置;
    b. 私服:私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用;私服的特性有:
  • 节省外网带宽
  • 加速Maven构建
  • 部署第三方构件
  • 提高稳定性,增强控制
  • 降低中央仓库负荷

1.5 常用Maven指令

mvn clean compile
清理+编译
mvn clean test
清理+编译+执行测试
mvn clean package
清理+编译+打包
mvn clean install
清理+编译+打包+放置本地仓库
mvn archetype:generate
创建项目骨架

二、Maven生命周期和插件

Maven生命周期

Maven有三个内置的生命周期:default、clean和site。在default的生命周期处理你的项目部署,在clean的生命周期处理项目的清理,在site的生命周期处理你的项目站点文档的创建。

Maven生命周期

Maven插件

Maven本身是一个框架,实际的任务都由插件完成。插件与生命周期阶段绑定,用户通过指定生命周期阶段就能够隐式的通过插件执行任务,如:$mvn compiler:compile,冒号前是插件前缀,后面是该插件目标(即: maven-compiler-plugin的compile目标),而该目标绑定了default生命周期的compile阶段。

Maven 默认插件目标绑定源码:

<component> 
  <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>  
  <role-hint>jar</role-hint>  
  <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>  
  <configuration> 
    <lifecycles> 
      <lifecycle> 
        <id>default</id>  
        <!-- START SNIPPET: jar-lifecycle -->  
        <phases> 
          <process-resources>org.apache.maven.plugins:maven-resources-plugin:2.6:resources</process-resources>  
          <compile>org.apache.maven.plugins:maven-compiler-plugin:3.1:compile</compile>  
          <process-test-resources>org.apache.maven.plugins:maven-resources-plugin:2.6:testResources</process-test-resources>  
          <test-compile>org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile</test-compile>  
          <test>org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test</test> 
        </phases>  
        <!-- END SNIPPET: jar-lifecycle --> 
      </lifecycle> 
    </lifecycles> 
  </configuration> 
</component>

自定义绑定

除了内置绑定以外,用户还能够自定义将某个插件目标绑定到生命周期的某个阶段上。如创建项目的源码包,maven-source-plugin插件的jar-no-fork目标能够将项目的主代码打包成jar文件,可以将其绑定到verify阶段上:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>3.0.0</version>
            <executions>
                <execution>
                    <id>attach-sources</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

其中executions下每个execution子元素可以用来配置执行一个任务。

自定义插件开发

参考:https://blog.csdn.net/zjf280441589/article/details/53044308/

三、聚合与继承

Maven的聚合特性(aggregation)能够使项目的多个模块聚合在一起构建,而继承特性(inheritance)能够帮助抽取各模块相同的依赖、插件等配置,在简化模块配置的同时,保持各模块一致。

例如,父POM:

<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.my.app</groupId>
    <artifactId>appName</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0.SNAPSHOT</version>

    <modules>
        <module>appName-client</module>
        <module>appName-core</module>
        <module>appName-web</module>
    </modules>

    <properties>
        <finalName>appName</finalName>
        <warName>${finalName}.war</warName>
        <spring.version>4.0.6.RELEASE</spring.version>
        <junit.version>4.12</junit.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <warExplodedDirectory>exploded/${warName}</warExplodedDirectory>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>

           <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>3.0.0</version>
                    <executions>
                        <execution>
                            <id>attach-sources</id>
                            <phase>verify</phase>
                            <goals>
                                <goal>jar-no-fork</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>
  • packaging: pom,否则无法聚合构建
  • modules: 实现聚合的核心,module值为被聚合模块相对于聚合POM的相对路径,离开聚合POM也能够独立构建(注: 模块所处目录最好与其artifactId一致)
  • dependencyManagement: 能让子POM继承父POM的配置的同时,又能够保证子模块的灵活性:在父POMdependencyManagement元素配置的依赖声明不会实际引入子模块中,但能够约束子模块dependencies下的依赖的使用(子模块只需配置groupId与artifactId)
  • pluginManagement: 与dependencyManagement类似,配置的插件不会造成实际插件的调用行为,只有当子POM中配置了相关plugin元素,才会影响实际的插件行为

子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">

    <parent>
        <groupId>com.my.app</groupId>
        <artifactId>appName</artifactId>
        <version>1.0.0.SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>appName-client</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

可以看到,子POM中并未定义模块groupId与version,这是因为子POM默认会从父POM继承了如下元素:

  • groupId、version
  • dependencies
  • developers and contributors
  • plugin lists (including reports)
  • plugin executions with matching ids
  • plugin configuration
  • resources

参考:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

  • Maven概述 Maven定义Maven是一个项目管理和整合,统一管理jar包的工具;Maven为开发者提供了一套...
    THQ的简书阅读 798评论 0 0
  • 使用指导 如何添加外部依赖jar包 在Maven工程中添加依赖jar包,很简单,只要在POM文件中引入对应的<de...
    静默虚空阅读 2,802评论 0 13
  • 所有项目的构建都是有生命周期的,这个生命周期包括:项目清理、初始化、编译、测试、打包、集成测试、验证、部署、站点生...
    zlcook阅读 2,769评论 0 21
  • Maven的基本了解 什么是Maven? Maven就是Apache下的一个开源项目。它是用纯java开发的。是一...
    Bcome阅读 2,820评论 0 7
  • 转自:http://www.cnblogs.com/crazy-fox/archive/2012/02/09/23...
    晴天哥_王志阅读 2,249评论 2 27