美文网首页
Maven笔记

Maven笔记

作者: 斯文遮阳 | 来源:发表于2019-01-27 17:14 被阅读0次

    一、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

    参考:

    相关文章

      网友评论

          本文标题:Maven笔记

          本文链接:https://www.haomeiwen.com/subject/zingjqtx.html