Maven

Maven简介

什么是 Maven?

Maven 是一个项目管理的工具。Maven 为我们开发人员提供了构建一个完整的生命周期的框架。Maven 使用标准的目录结构和默认构建生命周期,我们可以使用它自动完成项目的基础工具建设。

  • 包含一个项目对象模型(Project Object Model)
  • 一组标准集合
  • 一个项目生命周期(Project Lifecycle)
  • 一个依赖管理系统(Dependency Management System)
  • 用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑

Maven 是干什么的?

它是 Apache 的开源项目,主要做 Java 平台的三类事情:项目构建依赖管理以及项目信息管理,可以防止我们做一些重复的事情。

举个例子:假如有两个项目,需要引入相同的 jar,我们在两个地方都引入,那就是做了重复的事情,我们可以在一个公共的地方引入一次 jar 即可,例如父 pom.xml 中或者公共的 jar 中。

Maven除了具备Ant的功能外,还增加了以下主要功能:

  1. 使用Project Object Model来对软件项目管理
  2. 内置了更多的隐式规则,使得构建文件更加简单
  3. 内置依赖管理和Repository实现依赖的管理和统一存储
  4. 内置了软件构建的生命周期

Project Object Model(pom)

  • 一个项目所有的配置都放在POM文件中
  • 定义项目的类型、名字、管理依赖关系,定制插件的行为等
  • 在POM中,groupId、artifactId、packagin、version叫做maven坐标
  • 它能唯一的确定一个项目
  • 有了maven坐标,我们就可以用它来指定我们的项目所依赖的其他项目、插件、或者父项目

Maven内置隐式规则

目录 目的
${basedir} 存放pom.xml和所有的子目录
${basedir}/src/main/java 项目的java源代码
${basedir}/src/main/resources 项目的资源,比如说property文件,springmvc.xml
${basedir}/src/test/java 项目的测试类,比如说Junit代码
${basedir}/src/test/resources 测试用的资源
${basedir}/src/main/webapp/WEB-INF web应用文件目录,web项目的信息
比如存放web.xml、本地图片、jsp视图页面
${basedir}/target 打包输出目录
${basedir}/target/classes 编译输出目录
${basedir}/target/test-classes 测试编译输出目录
Test.java Maven只会自动运行符合该命名规则的测试类
~/.m2/repository Maven默认的本地仓库目录位置

Maven生命周期的各个阶段

image-20201009193656362

image-20201009193803208

Maven依赖管理

  • 我们能够通过maven坐标确定一个项目
  • 可以用它来解决依赖关系
  • 在POM中,依赖关系是在dependencies部分中定义的

Maven 下载和安装

maven是依赖于jdk,在安装 maven 之前,请先安装好 jdk。

官网下载安装包

Maven 官网下载地址 ,选择自己想要的版本和系统的安装包进行下载。

image-20201009191407144

解压安装包

下载的安装包为:apache-maven-x.x.x-bin.zip

配置环境变量

Mac版如下:

1
2
3
bogon:~ jinglv$ cat ~/.bash_profile
export M2_HOME=$HOME/apache-maven-3.6.1
export PATH=$PATH:$M2_HOME/bin

验证maven版本

1
2
3
4
5
6
bogon:~ jinglv$ mvn -v
Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-05T03:00:29+08:00)
Maven home: /Users/jinglv/apache-maven-3.6.1
Java version: 1.8.0_211, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "mac os x", version: "10.15.5", arch: "x86_64", family: "mac"

仓库配置

配置 Maven 本地仓库

在maven目录下:/maven-x.x./conf/settings.xml 中找到如下内容

1
<localRepository>/path/to/local/repo</localRepository>

把注释去掉改为自己本地的创建仓库的位置

localRepository 主要存放本地 jar 的缓存,如果本地有了就不去远程私服拉取,如果没有从私服拉,私服还没有从官网或者配置的阿里代理拉取。默认存放路径为:${user.home}/.m2/repository

mvn install 命令,可以把我们本地的项目自动打包成 jar,存放到上面的 jar 路径中。

运行命令mvn help:system,当控制台出现 build success 时,创建仓库位置就会多了很多jar包

设置远程仓库

Maven 默认的远程地址是 http://my.repository.com/repo/path

这个是国外的地址,使用该地址下载会比较慢,一般我们用阿里云提供的地址替代。

打开 maven 解压的文件,找到 config 目录下面的 settings.xml 文件

在 settings.xml 文件中添加阿里云的地址,搜索到<mirrors>位置

1
2
3
4
5
6
7
8
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>

检验刚才的配置是否生效,运行命令mvn help:system,当控制台出现 build success 时,说明配置生效

Maven 常用的一些命令

创建 Maven 的普通 Java 项目:

1
2
3
mvn archetype:create
-DgroupId=com.xhm.test(包名)
-DartifactId=xhm-test(项目名)

创建 Maven 的 Web 项目:

1
2
3
4
mvn archetype:create
-DgroupId=com.xhm.test(包名)
-DartifactId=xhm-test(项目名)
-DarchetypeArtifactId=maven-archetype-webapp

编译项目:

1
mvn compile

运行测试:

1
mvn test

切换到 pom 文件根目录,对项目进行打包:

1
mvn package

如果有多个模块,针对其中一个模块进行打包,一般生产环境跳过单元测试,同时指定环境为 pro:

1
mvn -pl 模块名 -am clean package -Dmaven.test.skip=true -P pro

编译项目,并打包项目,同时会把 jar 安装到本地:

1
mvn install

清除 target 中的 class 文件、jar、配置文件等:

1
mvn clean

生成 eclipse 项目:

1
mvn eclipse:eclipse

生成 idea 项目:

1
mvn idea:idea

组合使用 goal 命令,如只打包不测试:

1
mvn -Dtest package

编译测试的内容:

1
mvn test-compile

只打 jar 包:

1
mvn jar:jar

只测试而不编译,也不测试编译:

1
mvn test -skipping compile -skipping test-compile
  • -skipping 的灵活运用,当然也可以用于其他组合命令)

查看当前项目已被解析的依赖:

1
mvn dependency:list

上传到私服:

1
mvn deploy

强制检查更新,快照可能会经常更新,如果想强制更新就可以使用该命令:

1
mvn clean install-U

mvn compile、mvn install、mvn deploy,他们的主要区别如下:

  • mvn compile,编译类文件
  • mvn install,具有 mvn compile、mvn package 功能,把把 jar 安装到本地仓库
  • mvn deploy,具有 mvn install 所有功能,如果配置了私服,会把打包后的 jar 上传到私服

Maven 对工程的拆分和聚合

工程拆分和聚合的思想

首先,为什么我们要把项目拆分,在最早我们做开发时,web/service/dao/html/css/config 等等,全部混合在一起,前端后端都维护一个项目,到后来我们做前后端分离。再到后来我们使用 mvc,分的越明细,分工也越明细,维护就越简单。而我们把公共的东西抽离出去,避免了重复造轮子的问题,很多公共的东西大家都可以重复使用,例如 date、http、md5 等常用工具类,一些公共业务逻辑可以放到 common-service,dao 层代码我们只需要一个人添加大家都可以公共等,拆分的思想让我们可以脚踩很多轮子,快速构建一个类似的工程。

例如之前我搭建了一个卖商标的商城,我把支付、在线聊天、用户系统等都拆分成一个个的 jar,半年后公司又转了业务要搭建一个做企业服务的商城,支付模块,在线聊天,用户系统等都是可以直接复用的,大大的减少了我们的开发成本。

其次,说到了拆分,必须就要提到聚合,拆分是为了代码可重用,而聚合就是我们构建一个完整的功能。这里的聚合不单单是说我们聚合成一个完整的项目,例如我在构建支付这个模块的时候,也把项目拆分为了 util/dao/service/三个模块,最终提供出去的就是 service 的几个方法支付、退款等,但是 util 中实现了我调第三方接口 http 的工具类、签名校验的工具类等,dao 层我实现了支付、退款记录保存到 db 功能,service 层实现具体的业务逻辑。但几个模块聚合到一起形成了一个完整的支付模块。

image

Maven的聚合思想

maven 在解决代码可重用和便于维护问题上是这么解决的: .

  • maven把一个完整的项目,分成不同的独立模块,这些模块都有各自独立的坐标,哪个地方需要其中某个模块,就直接引用该模块的坐标即可。

  • 今后如果公司开发一个新项目,我们先考虑问题不是dao, service, utils, domain如何编写,我们要考虑的是,dao, service, utils, domain 这些模块是否已经存在,如果存在直接弓|用。

以上说的就是 maven 拆分的思想,我们可以把拆分零散的模块聚合到一起编写一个完整的项目 ,这就是maven聚合思想

聚合

如果我们想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合。

例如:对项目的Hello、HelloFriend、MakeFriends这三个模块进行聚合

1
2
3
4
5
<modules>
<module>../Hello</module>
<module>../HelloFriend</module>
<module>../MakeFriends</module>
</modules>

继承

继承为了消除重复,我们把很多相同的配置提取出来,例如:grouptId,version等。

  1. 继承配置代码:

    1
    2
    3
    4
    5
    6
    <parent>  
    <groupId>me.gacl.maven</groupId>
    <artifactId>ParentProject</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath>../ParentProject/pom.xml</relativePath>
    </parent>
  1. 继承代码中定义属性:

    1
    2
    3
    4
    5
    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <junit.version>4.9</junit.version>
    <maven.version>0.0.1-SNAPSHOT</maven.version>
    </properties>
  1. 访问属性的方式为${junit.version}:

    1
    2
    3
    4
    5
    6
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
    </dependency>
  1. 父模块用dependencyManagement进行管理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>${junit.version}</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>cn.itcast.maven</groupId>
    <artifactId>HelloFriend</artifactId>
    <version>${maven.version}</version>
    <type>jar</type>
    <scope>compile</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>