什么是Maven

Maven是一款服务于Java平台自动化构建工具。

自动化构建工具发展趋势:make->Ant->Maven->Gradle

参考:

知乎:Maven最全教程,看了必懂

知乎:IDEA+MAVEN踩坑指南

博客园:2021年Maven国内源配置大全

博客园-佩奇er:maven配置多个镜像

博客园-QiaoZhi:Maven的默认中央仓库以及修改默认仓库&配置第三方jar包从私服下载

脚本之家-itprobie-菜鸟程序员:maven 配置多个仓库的方法

maven依赖项版本查询

配置国内源

首先要想在国内顺利的使用Maven,我们首先要进行一些配置,才可以进行各种Maven所需Jar包的下载,当然无论是IDEA自带的Maven或者是自己替换一个Maven(不建议这么做),但始终都有一个问题就是在国内因为wall封锁,导致自己写入POM配置不能很快的更新jar,我们首先要做的就是解决这个问题:

  1. 找到自己intellij-idea的存储路径,我的Arch Linux上的路径为:/opt/intellij-idea-ultimate-edition/plugins/maven/lib/maven3/conf/settings.xml

  2. 修改这个文件找到<mirrors></mirrors>标签。

  3. 将以下内容写入这个标签之间:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <mirrors>
    <!-- mirror
    | Specifies a repository mirror site to use instead of a given repository. The repository that
    | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
    | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
    |
    <mirror>
    <id>mirrorId</id>
    <mirrorOf>repositoryId</mirrorOf>
    <name>Human Readable Name for this Mirror.</name>
    <url>http://my.repository.com/repo/path</url>
    </mirror>
    -->

    <mirror>
    <id>aliyunmaven</id>
    <mirrorOf>apache snapshots</mirrorOf>
    <name>aliyun apache</name>
    <url>https://maven.aliyun.com/repository/apache-snapshots</url>
    </mirror>

    </mirrors>

    当然IDEA启动时候就会自动加载这个配置文件,重新启动IDEA即可发现配置加载速度比之前快了好多,此时已经不用去Maven官网中心仓库去下载,而是从国内源下载。

经过测试发现

当我配置一个带有本地jar(不能从外网获取)依赖的项目时,填多个mirror只能访问其中的一个,除非mirror不能访问,才会自动访问另一个。

建议了解一下Nexus。

Java项目的构建

把在动态web项目工程经过编译后得到的编译结果部署到服务器上的整个过程。

编译:Java源文件(.java)经过编译成为class字节码文件(.class)

部署:将编译后的动态web项目导入到服务器中上线。

构建的各个环节:

  • 清理clean:将以前编译得到的旧文件class字节码文件删除
  • 编译compile:将java源程序编译成class字节码文件
  • 测试test:自动测试,自动调用junit程序
  • 报告report:测试程序执行的结果
  • 打包package:动态Web工程打War包,java工程打jar包
  • 安装install:Maven特定的概念—–将打包得到的文件复制到“仓库”中的指定位置
  • 部署deploy:将动态Web工程生成的war包复制到Servlet容器下,使其可以运行

为什么使用Maven

以前的方式 现在的方式
一个项目之间进行相互依赖比较麻烦 借助Maven可以将一个项目拆分成多个工程(比如之前的项目拿来多当前项目的依赖调用其中的方法)
项目之间的Jar包需要复制粘贴 借助于Maven直接将jar包保存在“仓库”中,直接导入到POM配置文件中即可
项目jar包需要去官网下载 Maven中的项目直接写入配置文件POM中
jar包之间不一致的风险 Maven直接调库中唯一名称唯一版本标识的唯一jar包文件即可
jar包依赖jar包需要手动导入 Maven直接继承下之前jar包所需的依赖

安装Maven

ArchLinux下安装

1
pacman -S maven

完成后在/opt/maven目录接可使用IDEA导入即可使用。

验证:

1
maven -v	#查看Maven版本信息

本地仓库存于:

  • Windows C:\<User Name>/.m2/repository
  • Linux ~/.m2/repository

第一个Maven

根目录:工程名
|—src:源码
|—|—main:存放主程序
|—|—|—java:java源码文件
|—|—|—resource:存放框架的配置文件
|—|—test:存放测试程序
|—pom.xml:maven的核心配置文件(Project Object Model 项目对象模型)

使用IDE直接可以自动创建这些文件夹以及必要maven所需文件,当热为了方便理解还是手动创建比较好。

IDEA自动构建maven目录

初始化pom.xml文件以及内容直接可被IDeA生成。

常用的maven命令:

以下 的命令必须在含有pom.xml的目录中执行。

命令 描述
mvn clean 清理
mvn compile 编译主程序
mvn test-compile 编译测试程序
mvn test 执行测试
mvn package 打包
mvn install 安装
  • 执行mvn compile表示即编译又进行依赖的处理,编译完成后Maven的目录会多出一个target目录(IDEA也是一样的)。
  • 执行mvn test-compiletarget 目录下会多出一个test-classes文件夹
  • mvn package,target文件夹下面又多了一个打好的jar包(将当前项目打包成jar文件)。
  • mvn clear清空整个编译后的任何文件。

Maven专业名词

坐标

pom.xml:Project Object Model 项目对象模型。它是maven的核心配置文件,所有的构建的配置都在这里设置。

坐标:使用三个向量在仓库中唯一的定位一个maven工程

1
2
3
4
5
6
7
8
<dependencies>	
<!-- 1.公司或组织域名倒序+项目名称-->
<groupId>com.baomidou</groupId>
<!-- 模块名称-->
<artifactId>mybatis-plus-boot-starter</artifactId>
<!--3.版本-->
<version>3.2.0</version>
</dependencies>

maven坐标和仓库对应的映射关系:

  1. 处理 groupId,每一个 . 转化为一级文件夹。比如‘org.springframework’,就是首先在repository 文件夹下创建一个 org 文件夹(已有的话不用创建),然后在 org 文件夹下创建 springframework 文件夹;
  2. 再下一级创建以 artifactId 命名的文件夹,即在 springframework 文件夹下创建 spring-core 文件夹;
  3. 创建版本号文件夹;
  4. 把 artifactId 和 version 用连字符连接(如果有 classifier 也要连接),然后加上扩展名,就是实际文件的地址。

仓库

  1. 本地仓库:

    自己本机电脑上的仓库。

  2. 远程仓库:

    • 私服:搭建在局域网中,一般公司都会有私服,私服一般使用nexus来搭建。
    • 中央仓库:架设在Internet上,像刚才的springframework就是在中央仓库上。

依赖

  1. maven解析依赖信息首先会去中央仓库查找被依赖的jar包。
  2. 对于本地仓库中没有的回去中央仓库查找,查到之后下载到本地。
  3. 如果依赖是自己或者团队开发项目,先在被依赖项目使用install把被依赖的maven工程的jar包导入到本地仓库。

依赖范围

scope标签就是依赖的范围:

scope标签

  • compile默认值,适用于所有阶段(开发、测试、部署、运行),本jar会一直存在所有阶段。

  • provided只在开发、测试阶段使用,目的是不让Servlet容器和你本地仓库的jar包冲突 。如servlet.jar。

  • runtime只在运行时使用,如JDBC驱动,适用运行和测试阶段。

  • test只在测试时使用,用于编译和运行测试代码。不会随项目发布。

  • system类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它。

生命周期

maven 有三套互相独立的生命周期,分别是:Clean LifecycleDefault LifecycleSite Lifecycle

  • Clean Lifecycle 在进行真正的构建之前进行一些清理工作。

    • pre-clean 执行一些需要在clean之前完成的工作
    • clean 移除所有上一次构建生成的文件
    • post-clean 执行一些需要在clean之后立刻完成的工作
  • Default Lifecycle构建的核心部分,编译,测试,打包,部署等等。

    不论你要执行生命周期的哪一个阶段,maven都是从这个生命周期的开始执行。

    • validate
    • generate-sources
    • process-sources
    • generate-resources
    • process-resources 复制并处理资源文件,至目标目录,准备打包
    • compile 编译项目的源代码
    • process-classes
    • generate-test-sources
    • process-test-sources
    • generate-test-resources
    • process-test-resources 复制并处理资源文件,至目标测试目录
    • test-compile 编译测试源代码
    • process-test-classes
    • test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署
    • prepare-package
    • package 接受编译好的代码,打包成可发布的格式,如 JAR
    • pre-integration-test
    • integration-test
    • post-integration-test
    • verify
    • install 将包安装至本地仓库,以让其它项目依赖。
    • deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享
  • Site Lifecycle 生成项目报告,站点,发布站点。

    • pre-site 执行一些需要在生成站点文档之前完成的工作
    • site 生成项目的站点文档
    • post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
    • site-deploy 将生成的站点文档部署到特定的服务器上

maven工程的依赖高级特性

依赖与被依赖间处理

处理依赖

WebMavenDemo(子)项目依赖JavaMavenService1 JavaMavenService1(父)项目依赖JavaMavenService2(曾祖父)。

pom.xml文件配置好依赖关系,必须首先mvn install后,依赖的jar包才能使用,即:

  • WebMavenDemo的pom.xml文件想能编译通过,JavaMavenService1必须mvn install

  • JavaMavenService的pom.xml文件想能编译通过,JavaMavenService2必须mvn install

依赖间属性

  • 依赖传递性

    依赖传递规则
    为JavaMavenService2(曾祖父)中增加了一个spring-core.jar包后,会惊喜的发现依赖的两个项目(父 子)都自动的增加了这个jar包,这就是依赖的传递性。

    注意:非compile范围的依赖是不能传递的

  • 路径最短者优先

    路径最短者优先

    JavaMavenService2(曾祖父)中解除旧版Log4j 1.2.7.jar,自己添加一个新版Log4j 1.2.9.jar,此版本只会影响自己及后代(父 子),不会影响前辈(曾祖父)。

统一管理依赖的版本

依赖版本管理

为了统一管理版本号,可以使用properties标签,里面可以自定义版本的标签名。在使用的地方使用${自定义标签名}。

build配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<build>
  <!-- 项目的名字 -->
  <finalName>WebMavenDemo</finalName>
  <!-- 描述项目中资源的位置 -->
  <resources>
    <!-- 自定义资源1 -->
    <resource>
      <!-- 资源目录 -->
      <directory>src/main/java</directory>
      <!-- 包括哪些文件参与打包 -->
      <includes>
        <include>**/*.xml</include>
      </includes>
      <!-- 排除哪些文件不参与打包 -->
      <excludes>
        <exclude>**/*.txt</exclude>
          <exclude>**/*.doc</exclude>
      </excludes>
    </resource>
  </resources>
  <!-- 设置构建时候的插件 -->
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.1</version>
      <configuration>
        <!-- 源代码编译版本 -->
        <source>1.8</source>
        <!-- 目标平台编译版本 -->
        <target>1.8</target>
      </configuration>
    </plugin>
    <!-- 资源插件(资源的插件) -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-resources-plugin</artifactId>
      <version>2.1</version>
      <executions>
        <execution>
          <phase>compile</phase>
        </execution>
      </executions>
      <configuration>
        <encoding>UTF-8</encoding>
      </configuration>
    </plugin>
    <!-- war插件(将项目打成war包) -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-war-plugin</artifactId>
      <version>2.1</version>
      <configuration>
        <!-- war包名字 -->
        <warName>WebMavenDemo1</warName>
      </configuration>
    </plugin>
  </plugins>
</build>

执行mvn package之后,在maven工程指定的target目录里war包和文件都按照配置的生成了:

打包结果