【程序员必备】Maven学习笔记

49 阅读15分钟

笔记基于视频: 黑马程序员Maven全套教程,maven项目管理从基础到高级,Java项目开发必会管理工具maven

一、Maven的作用

依赖管理:自动管理项目所需要的依赖库,自动管理依赖的版本,避免同一个依赖库不同版本的冲突。

构建项目:可以管理项目的编译、测试、打包、部署等构建过程。

统一项目结构:提供标准的、统一的项目结构

二、Maven下载和安装

  1. 下载地址

官网:maven.apache.org/

下载地址:maven.apache.org/download.cg…

  1. 解压到任意位置
  2. 配置环境变量
    1. Maven 是用 Java 写的,因此需要配置JAVA_HOME
    2. 系统变量中新建一个MAVEN_HOME,值是Maven的安装目录

  1. 在Path中添加一个路径%MAVEN_HOME%\bin

  1. cmd中输入mvn,如果出现任务指令,则说明配置成功

三、Maven基本概念

1.Maven 软件路径介绍

  • bin:可运行指令
  • boot:里面有一个jar包,是Maven的类加载器
  • conf:存放Maven的配置文件
  • lib:存放Maven运行的jar包

2.仓库

用于存储资源,包含各种jar包

1.仓库的分类

  • 远程仓库:为本地仓库提供资源
    1. 中央仓库:Maven官方的服务器,存放着所有的的jar包
    2. 私服:部门/公司范围内存储资源的仓库,从中央仓库获取资源
  • 本地仓库:保存在自己计算机上的jar包

2.私服的作用

  • 保存具有版权的资源,包含购买或自主研发的jar
  • 中央仓库中的jar都是开源的,不能存储就有版权的资源
  • 一定范围内共享资源,仅对内部开发,不对外共享

计算机先访问本地仓库,如果有直接获取;没有会让从私服获取;私服没有就回去访问中央仓库,私服获取之后,返回给本地服务器

2.坐标

1.坐标的概念

  • 概念Maven中的坐标用于描述仓库中资源的位置
  • 作用:通过该标识,可以将资源的识别与下载工作交给机器完成

2.坐标的主要组成

  • groupId:当前Maven项目隶属组织名称+项目名(通常是域名反写,例如:org.mybatis)
  • artifactId:定义当前Maven模块名称(通常是模块名称)
  • version:定义当前版本号
  • packaging:定义该项目的打包方式(不属于坐标的组成)

3.获取jar包的坐标

  1. 访问maven的仓库地址:mvnrepository.com
  2. 输入需要的jar包名称
  3. 选择jar包的版本号
  4. 新的页面中有一个Maven的框,复制即可

四、仓库配置

1、本地仓库配置

该配置用来指定资源下载到哪里

  1. 在任意位置创建一个文件夹
  2. 打开maven安装目录下的conf文件夹
  3. 打开里面的settings.xml文件
  4. 复制下面的代码到里面
<localRepository>创建的文件夹地址</localRepository>

2、远程仓库配置

该配置用来指定资源从哪里下载

  1. 打开maven安装目录下的conf文件夹
  2. 打开里面的settings.xml文件
  3. 找到mirror标签
  4. 复制注释中的一份到mirror标签中
<mirror>
     <id>alicloud</id>
     <name>aliyun</name>
         <mirrorOf>central</mirrorOf>
     <url>https://maven.aliyun.com/repository/public</url>
 </mirror>

五、第一个Maven项目(IDEA生成)

1.第一步:配置Maven

新建项目-->Empty Project

创建完成后修改项目的sdk

修改Maven的版本为自己下载的,并且覆盖掉Idea的配置文件为自己的

2.第二步:创建java项目

2.1 第一种:手工创建 Maven 项目

  1. 创建模块,选择Maven

  1. 选择填写模块的Maven的坐标,然后一路next

  1. 设置界面进入项目结构,给包配置对应的属性

  1. 进入pom.xml配置文件,打上需要用的jar包,写完之后需要点击右边的刷新

  1. 构建项目

2.2 第二种:使用Maven模板创建java工程

  1. 选择模块,新建一个maven模块,勾选Create From archetype(使用模板),然后选择quickstart

  1. 修改GroupId和ArtifactId,然后一路next

  1. 然后在项目目录的main、test包下新建resources包
  2. 右键新建的resources包,选择Mark Directory as--》Sources Root

2.3 第三种:使用Maven模板创建web工程

  1. 选择模块,新建一个maven模块,勾选Create From archetype(使用模板),然后选择webapp

  1. 修改GroupId和ArtifactId,然后一路next

  1. 在main包下创建java包,在src目录下创建test包,在test包下创建java、resources包
  2. 然后给包相应的颜色

3. 第三步:添加插件运行项目【可选】

  1. 修改模块下的pom.xml文件,将里面的东西先删除一部分
<?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/maven-v4_0_0.xsd">


    <modelVersion>4.0.0</modelVersion>
    <packaging>war</packaging>

    <name>web01</name>
    <groupId>com.junqing</groupId>
    <artifactId>web01</artifactId>
    
    <dependencies>
    </dependencies>

</project>
  1. 打开maven坐标库,搜索 tomcat maven,找到 org.apache.tomcat.maven 的包,复制依赖
  2. pom.xml 文件的 build 标签中的 plugins 标签中新增加一个 plugin标签,如果没有就字节写一部分,把赋值的依赖粘贴进去,如下面代码所示,然后配置启动端口和路径
<!--构建-->
<build>
  <!--设置插件-->
  <plugins>
    <!--设置具体插件-->
    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.2</version>
      <configuration>
        <port>8080</port>
        <path>/</path>
      </configuration>
    </plugin>
  </plugins>
</build>
  1. 然后刷新maven,加载资源
  2. 然后使用maven的tomcat插件,运行项目,启动成功之后就会给一个地址,点击就可以访问项目

  1. 如果需要修改端口:在配置第 3 步里面添加configuration标签
<!--配置-->
<configuration>
  <!--修改端口号-->
  <port>80</port>
  <!--修改路径-->
  <path>/</path>
</configuration>
  1. 如果嫌启动麻烦:可以配置一个按钮

  1. 最终的 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/maven-v4_0_0.xsd">
  <!--指定pom的模型版本(不用修改)-->
  <modelVersion>4.0.0</modelVersion>
  <!--打包方式:web工程为war,java工程为jar-->
  <packaging>war</packaging>
  <!--name没用-->
  <name>Test02</name>
  <!--通常为域名反写-->
  <groupId>com.junqing</groupId>
  <!--项目id:通常是项目名-->
  <artifactId>Test02</artifactId>
  <!--版本号(随便写):release(完成版),SNAPSHOT(开发版)-->
  <version>1.0-SNAPSHOT</version>
  <!--设置当前工程的所有依赖-->
  <dependencies>
    <!--当前工程的具体依赖-->
    <dependency>
      <groupId></groupId>
      <artifactId></artifactId>
    </dependency>
  </dependencies>
  <!--构建-->
  <build>
    <!--设置插件-->
    <plugins>
      <!--设置具体插件-->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <!--配置-->
        <configuration>
          <!--修改端口号-->
          <port>80</port>
          <!--修改路径-->
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

六、依赖管理

依赖的概念:指当前项目运行所需要的jar,一个项目可以设置多个依赖

1.项目依赖配置

配置依赖的方式:在pom.xml中的 dependencies 中添加 dependency(可以有多个)

<dependencies>
    <!--具体依赖(可以有多个)-->
    <dependency>
      <groupId>log4j</groupId><!--群组id-->
      <artifactId>log4j</artifactId><!--项目id-->
      <version>1.2.14</version><!--版本号-->
    </dependency>
    <!--第二个具体依赖-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
  </dependencies>

2.依赖传递

1.依赖传递的概念

  • 场景解释:项目 1 需要用到项目 2,这个时候需要把项目 2 作为依赖配置到项目 1 中。这个时候项目 1 中引用到的依赖同时也会被项目 2 引用
  • 直接依赖:在当前项目中通过配置依赖建立的依赖关系【项目 2 依赖项目 1】
  • 间接依赖:通过依赖传递,传递过来可以用的【项目 2 间接依赖项目 1 中使用到的依赖】

2.依赖传递的配置方法

把被调用的项目坐标配置到调用项目的dependency中(项目坐标:group、artifactId、version),被调用的项目坐标也会通过依赖传递引用过来

<!--配置依赖-->
<dependency>
  <groupId>com.junqing</groupId>
  <artifactId>Test01</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

3.依赖传递冲突问题

  • 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高
  • 声明优先:当资源在同层被依赖时,谁先被配置,谁先被使用
  • 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的【同一个配置文件,同一个软件配置了两个版本,后面的覆盖前面的】

3.可选依赖

  • 可选依赖的概念:对外隐藏当前所依赖的资源(别人能不能看见)
  • 场景解释:项目 1 有一个依赖,不想让其他项目也引用这个依赖,于是主动使用 option标签隐藏了起来。后面项目 2 引用项目 1 的时候,这个被隐藏的依赖不会被引入到项目 2 中
  • 可选依赖操作:对应的依赖中加一个optional标签即可
<dependency>
  <groupId>com.junqing</groupId>
  <artifactId>Test01</artifactId>
  <version>1.0-SNAPSHOT</version>
  <optional>true</optional><!--隐藏起来,别人就看不见了-->
</dependency>

4.依赖排除

  • 依赖排除的概念:主动断开依赖的资源(主动排除另一个项目的某个依赖)
  • 场景解释:项目 2 引入了项目 1,但是项目 1 中的某个依赖项目 2 不想要,于是项目 2 主动把项目 1 中某个依赖排除了
  • 依赖排除操作:引入依赖的时候加上一个 exclusions标签,然后里面使用 exclusion排除指定依赖

案例:项目 1 中的log4j依赖,项目2不需要,因此在项目 2 的依赖中排除掉项目 3 的log4j

<!--不要它里面的log4j-->
<dependency>
  <groupId>com.junqing</groupId>
  <artifactId>Test01</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!--依赖排除-->
  <exclusions>
    <exclusion>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
    </exclusion>
  </exclusions>
</dependency>

5.依赖范围

依赖的jar默认情况可以在任何地方使用,可以通过scope标签设定其作用范围

作用范围

  1. 主程序范围有效(main文件夹范围内)
  2. 测试程序范围有效(test文件夹范围内)
  3. 是否参与打包(package指令范围内)

6.依赖范围传递性(了解即可)

带有依赖范围的资源在进行传递时,作用范围将受到影响

七、生命周期与插件

  • 各个构件环节执行的顺序不能被打乱,必须按照规定的正确顺序来执行
  • Maven的核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务由插件来完成
  • Maven核心程序为了更好的实现自动化构建,按照这样的特点执行生命周期中的各个阶段:不论要执行哪一阶段,都会从第一步开始执行(生命周期的第一步开始)

1.项目构建生命周期

  • clean:清理工作
  • default:核心工作,例如编译,测试,打包,部署
  • site:产生报告,发布站点

1.1、clean生命周期

  • pre-clean:执行一些需要在clean之前完成的工作
  • clean:移除上一次构建生成的文件
  • post-clean:执行一些需要在clean之后立刻完成的工作

1.2、default(构建)生命周期

1.3 特别说明

执行后置的声明周期执行的时候会把前面的声明周期都执行

例如:

  1. test会把上面的都执行
  2. package会把他上面的都执行

2.插件

  • 插件与生命周期内的阶段绑定,在执行到对应生命周期时执行对应的插件功能
  • 默认maven在各个生命周期上已经绑定了预设功能
  • 通过插件可以自定义其他功能
<!--构建-->
<build>
  <!--设置插件-->
  <plugins>
    <!--设置具体插件-->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-source-plugin</artifactId>
      <version>2.2.1</version>
      <!--执行什么动作-->
      <executions>
        <!--具体执行什么动作-->
        <execution>
          <goals>
            <!--将源码打包-->
            <goal>jar</goal>
          </goals>
          <!--什么时候执行-->
          <phase>generate-resources</phase>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

八、分模块开发

1.分模块开发概念

原本一个项目里面有 DTO、Service、Controller 包,现在给他拆分成几个模块,多个模块中相互引用完成整体功能。

2.模块具体拆分过程

  1. pojo 模块:直接将实体类复制过来。为了给其他模块使用,因此还需要执行 install,将包保存到本地仓库。
  2. dao 模块:将类及配置文件复制过来,然后将需要的依赖写入配置文件。由于需要实体类,因此配置文件中还需要需要引入 pojo 模块。
  3. service 模块:基本跟 dao 层操作类似。
  4. controller 模块:基本跟 dao 层操作类似

九、聚合

使用场景:我们现在已经把一个项目拆分成了多个模块,并且每个模块都 install到了本地仓库中。现在的问题是多个模块之间都有依赖,其中一个模块更新之后,其他的模块不知道这个模块的更新。因此,是否可以有一个模块管理这几个模块之间的合作。

结论:将这几个模块都移动到父模块中,父模块管理这几个子模块

  1. 创建一个父模块,由于父模块没有代码,因此 src 可以删除。
  2. 父模块的 pom文件,packaging标签的值改为 pom
<packaging>pom</packaging>
  1. 父模块pom文件,新增 modules标签,然后里面新增 module模块用来指定管理哪些模块
<modules>
  <module>模块1的名字</module>
  <module>模块2的名字</module>
  <module>模块3的名字</module>
  <module>模块4的名字</module>
</modules>
  1. 后面其他模块代码进行改动的时候,编译、安装父模块即可

十、继承

使用场景:一个项目拆分成多个模块之后,两个模块之间可能会引用同一个技术的不同版本。例如:模块 1 使用了 spring 5.1.9,模块 2 使用了 spring 5.2.0。不同版本之间可能会出现兼容性问题。因此,是否可以有一个模块管理其他模块使用技术的版本。

结论:父工程定义使用的技术,及版本号。子模块需要使用什么技术,直接声明技术名就行,版本号直接使用父模块定义的。

  1. 父模块的 pom文件 新增 dependencyManagement标签和 dependencies,用来声明,子模块可以使用哪些技术。
<!--声明对依赖进行版本管理-->
<dependencyManagement>
  <!--声明管理哪些依赖-->
  <!--技术1-->
  <dependencies>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
  </dependencies>
  <!--技术2-->
  <dependencies>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
  </dependencies>
  <!--技术3-->
  <dependencies>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
  </dependencies>
</dependencyManagement>
  1. 子模块的 pom文件,新增 parent标签,用来声明父模块是谁
<parent>
  <groupId>父模块groupId</groupId>
  <artifactId>父模块artifactId</artifactId>
  <version>父模块version</version>
  <!--relativePath 用来说明父模块的pom文件在哪里-->
  <relativePath>父模块pom文件路径</relativePath>
</parent>
  1. 子模块的pom文件中,dependency标签中的 version就可以删除了
  2. 父模块的pom文件中,build标签新增 pluginManagement标签,用来管理插件
<build>
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <version>2.2.1</version>
        <!--执行什么动作-->
        <executions>
          <!--具体执行什么动作-->
          <execution>
            <goals>
              <!--将源码打包-->
              <goal>jar</goal>
            </goals>
            <!--什么时候执行-->
            <phase>generate-resources</phase>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </pluginManagement>
</build>
  1. 子模块的pom文件中,build标签,只用写必要的信息即可

十一、属性

使用场景:父模块中声明的依赖,可能有很多技术的版本号一致,其中一个修改其他的也需要同步修改。因此,如果我们一个一个该,可能会漏掉,因此是否有一个方案,能解决改一个地方,其他地方同步修改呢?

结论:在 pom 文件中,定义属性,其他地方引用属性即可。如果属性修改了,其他引用属性的地方会同步修改

  1. pom文件中使用 properties标签,在其内部自定义属性
<properties>
  <spring.version>5.1.9</spring.version>
  <project.version>1.0</project.version>
</properties>
  1. 需要使用的地方 使用 ${自定义属性名} 引用自定义属性即可
<dependency>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-source-plugin</artifactId>
  <!--使用${}引用自定义属性-->
  <version>${spring.version}</version>
</dependency>

十二、私服

1.Nexus 下载

Nexus 是一款 Maven 私服产品

下载地址:直接 docker 下载

2.仓库分类

  • 宿主仓库(hosted):保存无法从中央仓库获取的资源【存放自主研发、第三方非开源项目】
  • 代理仓库(proxy):访问其他公共仓库【如访问中央仓库】
  • 仓库组(group):将若干仓库组成一个群组,简化配置【不保存资源,属于理论存在的仓库】

3.创建仓库

  1. 点击设置找到仓库,点击添加仓库

  1. 选择仓库类型,这里我创建了一个宿主仓库

  1. 录入仓库名字,仓库类型,然后点击确定

  1. 然后主页就显示出来了

  1. 点击 maven-public,将我们新创建的仓库添加到组中

4.手动上传依赖

  1. 选中我们自己创建的仓库

  1. 点击上传

  1. 将我们自己的 jar 包选中,然后录入依赖的坐标,即可完成

5.本地访问私服配置

  1. 在 Maven 的 setting配置文件中找到 servers标签。配置私服的地址及账号密码
<servers>
  <server>
    <!--id可以随便-->
    <id>myDevRep</id>
    <username>admin</username>
    <password>123456</password>
  </server>
</servers>
  1. 在 Maven 的 setting配置文件中找到 mriiors标签,配置哪些资源从私服下载
<!--如果配置了多个仓库地址,会从上往下找资源-->
<mirrors>
  <!--之前配置-->
  <mirror>
    <id>alicloud</id>
    <name>aliyun</name>
    <mirrorOf>central</mirrorOf>
    <url>https://maven.aliyun.com/repository/public</url>
  </mirror>

  <!--本次配置的-->
  <mirror>
    <!--id随便-->
    <id>myRep</id>
    <!--name随便-->
    <name>myRep</name>
    <!--mirrorOf:表示哪些资源从这个仓库下载(central-表示中央仓库的资源 *-表示所有资源)-->
    <mirrorOf>*</mirrorOf>
    <!--群组的url:从nexus中复制-->
    <url>http://127.0.0.1:8081/repository/maven-public/</url>
  </mirror>
</mirrors>

6.IDEA 资源上传、下载

IDEA 资源下载是走的 Maven,在上面我们已经给 Maven 私服配置好了,因此这里只需要配置资源上传。

  1. 在项目的 pom.xml中增加 distributionManagement标签,然后正式版依赖仓库信息用 repository标签,快照版的依赖仓库信息用 snapshotRepository标签
<distributionManagement>
  <!--正式版本依赖仓库-->
  <repository>
    <!--Maven中server中配置的id-->
    <id>myDevRep</id>
    <!--仓库地址:从私服中复制过来即可-->
    <url></url>
  </repository>
  <!--标准版本仓库依赖-->
  <snapshotRepository>
    <!--Maven中server中配置的id-->
    <id></id>
    <!--仓库地址:从私服中复制过来即可-->
    <url></url>
  </snapshotRepository>
</distributionManagement>
  1. 运行 Maven 的 deploy声明周期即可将依赖发布到对应仓库