maven基本用法

maven作为一个构建工具,不仅能帮我们自动化构建,还能够抽象构建过程,提供构建任务实现;它跨平台,对外提供了一致的操作接口。
中央仓库:
http://repo1.maven.org/maven2/
约定:
默认打包主目录:src/main/java
默认打包测试目录:src/test/java

一、坐标说明

<groupId>mavenStudy</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

----case---
<groupId>com.xxx.cb.web</groupId>
<artifactId>cb-web-boss</artifactId>
<version>1.1.0</version>
<scope>system</scope>
<packaging>war</packaging>
  • groupId:当前Maven项目隶属的实际项目。通常一个项目会有很多模块;groupId不应该对应项目隶属的组织或公司,因为组织或公司会有很多实际项目。
  • artifactId:实际项目中的一个maven项目(模块),推荐使用实际项目名称作为前缀。
  • version:当前项目的版本。maven定义了一套完整的版本规范,以及快照(SNAPSHOT)概念。
  • packaging:maven项目的打包方式。打包方式会影响到构建的生命周期,比如jar打包和war打包会使用不同的命令。不定义时maven默认打包为jar;
  • scope:依赖范围
    • compile:编译依赖范围。如果没有指定,就会默认该范围。该范围,对于编译、测试、运行三种classpath都有效。
    • test:测试依赖范围。此范围,只对于测试classpath有效,典型的例子是JUnit。
    • provided:已提供依赖范围。此范围,对于编译和测试classpath有效,但在运行时无效。
    • runtime:运行时依赖范围。此范围,对于测试和运行classpath有效,但在编译时无效。
    • system:系统依赖范围。此范围与provided完全一致。但是必须通过systemPath元素显示地指定依赖文件的路径。一般情况下,本地依赖,例如在项目某个文件夹下的本地依赖,比如外来sdk,我们通过这个依赖来指定它的路径。
  • optional:标记依赖是否可选。作为可选依赖,他们只会对当前项目A产生影响,当其他项目依赖项目A时,这个依赖就不会传递下去。备注:在理想的情况下是不应该使用可选依赖的。
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>5.0.6.RELEASE</version>
  <optional>true</optional>
</dependency>
  • exclusions:排除传递性依赖。例如在该依赖中,poi已经依赖了commons-codec,但是我们并不想引入这个传递性依赖,所以使用进行排除…表示这个依赖通过传递,而是自己从另外的提供,或者不提供。可声明多个子项目,排除多个。
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.15</version>
  <exclusions>
    <exclusion>
      <artifactId>commons-codec</artifactId>
      <groupId>commons-codec</groupId>
    </exclusion>
  </exclusions>
</dependency>

二、标签

  • distributionManagement:将本项目发布到仓库:在config中配置对应id的仓库,该项目使用发布命令,就能发布到对应仓库
<distributionManagement>
  <repository>
    <id>dhcao-repoReleases</id>
    <name>Proj Release Repository</name>
    <url>http://ddddddddddddddd/content/repositories/proj-releases</url>
  </repository>
  <snapshotRepository>
    <id>dhcao-repoSnapshots</id>
    <name>Proj Release Repository</name>
    <url>http://ddddddddddddddd/content/repositories/proj-snapshots</url>
  </snapshotRepository>
</distributionManagement>
  • scm标识发布版本的一些信息;利用release插件打包的时候。这个可以被识别;
    发布之后,就会声明scm地址:http://svn.myproj.tech:7000/xxxx_cb/版本号…
<scm>
  <url>http://svn.xxxx.tech:7000/xxxx_cb</url>
</scm>

三、仓库

3.1 仓库解析路径:

如果构件:
groupID= org.testing
artifactId = testing
version = 5.8
classifier = jdk15
packaging = jar
生成路径为:org/testing/testing/5.8/testing-5.8。
如果构建有classifer,就加上构件分隔符和classifer,那么路径就变成:org/testing/testing/5.8/testing-5.8-jdk5

3.2 仓库分类

  • 本地仓库
  • 远程仓库
    在这里插入图片描述

3.3 仓库配置

<servers>

    <server>
      <id>maven.xxxx.org</id>
      <username>developer</username>
      <password>xxxxx@8</password>
    </server>

    <server>
      <id>maven.xxxxx.org-releases</id>
      <username>developer</username>
      <password>xxxxxx@8</password>
    </server>

    <server>
      <id>maven.xxxxxx.org</id>
      <username>developer</username>
      <password>xxxxxxx@8</password>
    </server>

  </servers>

3.3 部署项目到仓库

<distributionManagement>
  <repository>
    <id>dhcao-repoReleases</id>
    <name>Proj Release Repository</name>
    <url>http://ddddddddddddddd/content/repositories/proj-releases</url>
  </repository>
  <snapshotRepository>
    <id>dhcao-repoSnapshots</id>
    <name>Proj Release Repository</name>
    <url>http://ddddddddddddddd/content/repositories/proj-snapshots</url>
  </snapshotRepository>
</distributionManagement>
  • <repository>:这个是发布版本(正式版本)的仓库,需要跟中配置的id一样。
  • <snapshotRepository>:这个是快照版本的仓库,如果项目声明为snapshot版本,就会部署到这里。
  • 过程:运行 mvn clean deploy 就会将项目构建时输出的构件部署到对应的远程仓库。

3.4 快照版本

<groupId>mavenStudy</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

这个就是快照版本。maven找到快照版本时,会自动为构件打上时间戳。比如2.1-20211214.221414-13.就代表2021年12月14日22点14分14秒的第13次快照。有了该快照,maven就能随时找到仓库中该构件的最新版本(每次都会找最新)。

3.5 镜像

如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。
在<mirrors>下可以配置多个<mirror>镜像

<mirrors>
    
    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>*</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>
  </mirrors>
  • <mirrorOf> * </mirrorOf>:表示他是哪个仓库的镜像,* 表示对所有的仓库的访问都会访问这个镜像。
  • <mirrorOf>external:*</mirrorOf>:匹配所有远程仓库,使用localhost的除外,使用file://协议的除外。也就是说,匹配所有不在本机上的远程仓库
  • <mirrorOf>repo1,repo2</mirrorOf>:匹配仓库repo1和仓库repo2,使用逗号分隔多个远程仓库。
  • <mirrorOf>*, ! repo1</mirrorOf>:匹配所有远程仓库,repo1除外,使用感叹号将仓库从匹配中排除。

四、传递性依赖

maven中通常会使用指定依赖的影响范围。

4.1 依赖范围

一、介绍下依赖范围

  • scope:依赖范围
    • compile:编译依赖范围。如果没有指定,就会默认该范围。该范围,对于编译、测试、运行三种classpath都有效。
    • test:测试依赖范围。此范围,只对于测试classpath有效,典型的例子是JUnit。
    • provided:已提供依赖范围。此范围,对于编译和测试classpath有效,但在运行时无效。
    • runtime:运行时依赖范围。此范围,对于测试和运行classpath有效,但在编译时无效。
    • system:系统依赖范围。此范围与provided完全一致。但是必须通过systemPath元素显示地指定依赖文件的路径。一般情况下,本地依赖,例如在项目某个文件夹下的本地依赖,比如外来sdk,我们通过这个依赖来指定它的路径。
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>1.5</version>
    <scope>system</scope>
    <systemPath>${basedir}/WebContent/WEB-INF/lib/hamcrest-core-1.3.jar</systemPath>
</dependency>

4.2 传递性依赖

假设,在现在的项目relax中引入了spring-core。例如:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>5.0.6.RELEASE</version>
</dependency>

那么它的默认范围就是compile,在spring-core项目中又依赖了commons-logging。
我们称原有项目relax对于spring-core是第一直接依赖,spring-core对于commons-logging是第二直接依赖。relax对于common-logging是传递性依赖。
在这里插入图片描述
(如果A依赖于B,B依赖于C,那么A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖)

4.3 传递性依赖范围

先上图表,再解释
在这里插入图片描述
解释这个图表
左边第一列:第一直接依赖范围。
上面第一行:第二直接依赖范围。
图表交汇点:传递性依赖范围。
规律:

  • 第二直接范围是compile时,传递性依赖的范围与第一直接依赖的范围一致;
  • 第二直接依赖的范围是test的时,依赖不得传递;
  • 第二直接依赖的范围是provided时,只传递第一直接依赖范围也为provided的依赖;
  • 第二直接依赖的范围是runtime时,传递性依赖范围与第一直接依赖的范围一致,但compile例外,此时传递性依赖的范围为runtime。

4.4 依赖调解

传递性依赖可能造成,jar包冲突?–不会
例1,项目A有这样的依赖关系:A -> B -> C -> X(1.0),A -> D -> X(2.0)。X有2个版本1.0和2.0,都是A的传递性依赖,如果不加以处理,明显会造成jar包冲突。
那么maven怎么处理呢,
maven依赖调解第一原则:路径个最优者优先。
明显X(1.0)路径长度是3,X(2.0)路径长度是2。所以maven会选择 X(2.0)。
例2,项目A又有了这样的依赖关系:A -> B -> Y(1.0),A -> D -> Y(2.0)。这时路径都是2,。怎么破。在Maven2.0.9版本之后,这个就可以处理了。
maven依赖调解第二原则:第一声明者优先。
在pom文件中,哪个先被声明,就使用哪个。

4.5 排除依赖

已经提过了
传递性依赖会给项目隐式地引入很多依赖,也会出现问题。例如当前项目有一个第三方依赖,而这个第三方依赖由于某些原因依赖了另外一个类库的SNAPSHOT的版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,而SNAPSHOT项目是很不稳定的,会影响到当前的项目。需要排除掉该SNAPSHOT。

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.15</version>
  <exclusions>
    <exclusion>
      <artifactId>commons-codec</artifactId>
      <groupId>commons-codec</groupId>
    </exclusion>
  </exclusions>
</dependency>

五、编译插件

5.1 编译插件:

maven-compiler-plugin

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-compiler-plugin</artifactId>
 <version>3.7.0</version>
 <configuration>
   <failOnError>true</failOnError>
   <verbose>true</verbose>
   <fork>true</fork>
   <compilerArgument>-nowarn</compilerArgument>
   <source>1.8</source>
   <target>1.8</target>
   <encoding>${project.build.sourceEncoding}</encoding>
 </configuration>
</plugin>

5.2 打包main方法插件

maven指定jar包的main方法,来启动项目

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>3.0.2</version>
  <configuration>
    <archive>
      <manifest>
        <!-- 指定MANIFEST.MF中的Main-Class -->
        <mainClass>com.alibaba.dubbo.container.Main</mainClass>
        <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
        <useUniqueVersions>false</useUniqueVersions>
        <!-- 在MANIFEST.MF加上Class-Path项并配置依赖包 -->
        <addClasspath>true</addClasspath>
        <!-- 指定依赖包所在目录 -->
        <classpathPrefix>lib/</classpathPrefix>
      </manifest>
      <manifestEntries>
        <Class-Path>.</Class-Path>
      </manifestEntries>
    </archive>
  </configuration>
</plugin>

maven实战书中提供:已测试
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>1.2.1</version>
  <executions>
    <execution>
      // 将插件绑定到生命周期 -- package
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>HelloWorld</mainClass>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

六、 生命周期

6.1 maven三套生命周期

maven有三套相互独立的生命周期,他们分别是clean、default和site。每个生命周期包含一些阶段(phase)

  • clean:清理项目
    • pre-clean
    • clean
    • post-clean
  • default:构建项目(阶段看后面解释)
  • site:建立项目站点
    • pre-site:执行一些在生成项目站点之前需要完成的工作
    • site:生成项目站点文档
    • post-site:执行一些在生成项目站点之后需要完成的工作
    • site-deploy:将生成的项目站点发布到服务器上

6.2 default生命周期的阶段(phase)

跟spring的applicationContext的refresh()里面的操作一样,贼多!

  • validate
  • initialize
  • generate-sources
  • process-sources:处理项目主资源文件。一般来说,是对src/main/resources目录的内容进行变量替换等工作后,复制到输出的主classpath目录中。
    例如:我们根据生产环境配置的文件跟开发环境不一致,maven打包时,发现我们在生产环境,就会将生产环境对应目录的文件复制替换,然后打包到classpath
  • generate-resources
  • process-resources
  • compile:编译项目的主源码。一般来说,编译src/main/java目录下的文件到输出的主classpath中
  • process-test-sources:处理项目测试资源文件。一般来说,是对src/test/resources目录的内容进行变量替换等工作后,复制到项目输出的测试classpath中
  • generate-test-sources
  • process-test-resources
  • test-compile:编译项目的测试代码。一般来说,是编译…src/test/java
  • process-test-classes
  • test:使用单元测试框架运行测试,测试代码不会打包或部署
  • prepare-package
  • package:接受编译好的代码,打包成可发布的格式,如jar
  • pre-integration-test
  • integration-test
  • post-integration-test
  • verify
  • install:将包安装到Maven本地仓库,供本地其他Maven项目使用。是本地哦
  • deploy:将最终的包复制到远程仓库,供其他开发人员和Maven项目使用。

6.3 命令行与生命周期

命令行就是多个生命周期的简单组合
mvn clean:调用clean的clean阶段
mvn test:default的test阶段
mvn test install:clean的clean阶段和default的install阶段
mvn clean deploy site-deploy:调用clean的clean阶段,default的deploy的阶段,site的site-deploy阶段。

6.4 插件绑定

maven的插件跟生命周期相互绑定,可以自定义插件,然后绑定maven的特定生命周期阶段。
例如maven-compiler-plugin插件,就绑定了default生命周期的compile阶段。
如果啥插件都不指定,那么就会使用内置插件绑定:
在这里插入图片描述
注意:这里只列出了拥有绑定关系的阶段,default还有很多阶段,默认他们没有绑定任何插件,因此也没有任何实际行为。

6.5 自定义绑定

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>1.2.1</version>
  // 任务执行,插件可以执行多个任务
  <executions>
    <execution>
        // 绑定了package阶段,很多插件不需要指定,因为插件的目标在编写时已经定义好默认绑定阶段
      <phase>package</phase>
      <goals>
        // 通过goals配置指定要执行的插件目标
        <goal>shade</goal>
      </goals>
      // 某些插件支持出传入参数,像mvn install -Dmaven.test.skip=true。里面的-D意味着
      //后面是参数,真正的参数是maven.test.skip=true,这个也可以使用configuration配置,全局生效。
      <configuration>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>HelloWorld</mainClass>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

七、版本管理和环境过滤

7.1 maven约定的版本号:

<主版本>.<次版本>.<增量版本>-<里程碑版本>

  • 主版本:表示了项目的重大架构变更。例如Maven2和Maven1相去甚远;Struts1和Struts2采用了不同的架构
  • 次版本:表示较大范围的功能增加和变化,及bug修复。
  • 增量版本:一般表示重大bug的修复。
  • 里程碑版本:顾名思义,某一个版本的里程碑。
    例如:1.3.4-beta-2
    主版本:1;
    次版本:3;
    增量版本:4;
    里程碑版本:beta-2;

7.2 环境过滤

7.2.1 配置

每个<profile>标签就是一个环境配置,使用id进行定位

<!-- 全局属性配置 -->
<profiles>
  <!-- 开发环境 -->
  <profile>
    <id>dev</id>
    <properties>
      <!-- 部署环境(对应配置文件版本) -->
      <env>dev</env>
      <suffix>LATEST</suffix>
      <maven.test.skip>false</maven.test.skip>
    </properties>
    <!-- 设置默认环境 -->
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
  </profile>


  <!-- 测试预发环境 -->
  <profile>
    <id>uat</id>
    <properties>
      <!-- 部署环境(对应配置文件版本) -->
      <env>uat</env>
      <maven.test.skip>false</maven.test.skip>
    </properties>
  </profile>


  <!-- 测试环境 -->
  <profile>
    <id>test</id>
    <properties>
      <!-- 部署环境(对应配置文件版本) -->
      <env>test</env>
      <suffix>BETA</suffix>
      <maven.test.skip>true</maven.test.skip>
    </properties>
  </profile>


  <!-- 生产环境 -->
  <profile>
    <id>pro</id>
    <properties>
      <!-- 部署环境(对应配置文件版本) -->
      <env>pro</env>
      <suffix>RELEASE</suffix>
      <maven.test.skip>true</maven.test.skip>
    </properties>
  </profile>
</profiles>


<resources>
  <resource>
    <directory>src/main/resources</directory>
    <targetPath>${project.build.directory}/classes</targetPath>
    // 开启过滤,就是说,类似{project.build.xxxx},{aa.bb.cc}就会生效。不然不生效
    <filtering>true</filtering>
    <includes>
      <include>**/*.xml</include>
    </includes>
  </resource>
</resources>

7.2.2 激活

配置了环境<profile>,那么如何激活,使用呢。

  • 命令行激活,使用-P加上profile的id来激活,多个id之间以逗号分开。
mvn clean install -Pdev,test  // 激活了dev和test2个环境
  • setting文件显示激活:如果用户希望某个profile默认处理激活状态,在maven的setting.xml中配置
<settings>
    ...
    <activeProfiles>
        <activeProfile>dev</activeProfile>
    </activeProfiles>
    ...
</setting>
  • 系统属性激活:配置当系统属性存在的时候,自动激活profile
<profile>
    <activation>
     <property>
        // 定义了属性anme为test,如果命令行中含有name属性,则激活
        <name>test</name>
      </property>
    </activation>
  </profile>

// 如下激活命令
mvn clean install -Dtest

或者

<profile>
    <activation>
     <property>
        // 定义了属性anme为test,如果命令行中含有name属性,则激活
        <name>test</name>
        <value>xx</value>
      </property>
    </activation>
  </profile>


// 如下激活命令
mvn clean install -Dtest=xx
  • 操作系统环境激活
<profile>
    <activation>
     <os>
        <name>Windows XP</name>
        // family 包括:windows、unix和mac
        <family>Windows</family>
        <arch>x86</arch>
        <version>5.1.2600</version>
      </os>
    </activation>
  </profile>
  • 文件存在与否激活
  <profile>
    <activation>
     <file>
        <missing>x.properties</missing>
        <exists>y.properties</exists>
     </file>
    </activation>
  </profile>
  • 默认激活:可以设置默认激活,如果有任意环境通过以上任意一种方式激活,那么默认激活就会失效。
<profile>
    <id>dev</id>
    <properties>
      <!-- 部署环境(对应配置文件版本) -->
      <env>dev</env>
      // maven环境变量
      <suffix>LATEST</suffix>
      <maven.test.skip>false</maven.test.skip>
    </properties>
    <!-- 设置默认环境 -->
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
  </profile>

7.3 Web资源过滤

有的时候,希望在构建项目的时候,为不同的客户使用不一样的资源文件。这时可以在web资源文件中使用Maven属性,例如用${client.logo}表示图片,然后使用不同的profile分别定义这些Maven属性的值
最后需要配置maven-war-plugin对src/main/webapp/这一资源目录进行过滤。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TuringK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值