目录

maven_quickstart

[TOC]

Summary

maven的安装

  1. 检查JAVA_HOME变量, maven也是用java写的,需要用到jdk
  2. 解压压缩包
  3. 配置maven环境变量 MAVEN_HOME或M2_HOME, path
  4. 查看是否安装成功 mvn -v

maven基本概念

Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。

  • 构建 以“java源文件”,“框架配置文件”,“jsp”,“html”,“图片”等资源为原材料,去生产一个可以运行的项目的过程。

  • 部署 我们需要通过浏览器访问java程序时,必须要把web工程编译的结果拿到服务器上指定的目录下并启动服务器才行,这个拿的过程就叫部署。实际项目中还包括第三方框架的jar以及各种配置文件,所有这些资源都必须按照正确的目录结构部署到项目服务器上,项目才可以运行。

  • 构建过程的各个环节

    • 清理 将以前编译得到的旧字节码文件删除,为下一次编译做准备
    • 编译 将java源程序编译成字节码文件
    • 测试 自动测试
    • 报告 测试程序执行的结果
    • 打包 动态web工程打的war包,java工程打jar包
    • 安装 maven特定的概念——将打包得到的文件复制到仓库指定的位置
    • 部署 将动态web工程生成的war包复制到servlet容器的指定目录下

maven核心概念

约定的目录结构

https://gitee.com/lienhui68/picStore/raw/master/null/20200706165328.png

  1. main 主程序
  2. java java源文件
  3. resource 各种配置文件

为什么要遵守约定的目录结构? maven要负责这个项目的自动化构建,如果自定义的东西想让框架或工具知道,有两种办法:

  1. 以配置的方式明确告诉框架, 比如在xml配置核心文件的路径
  2. 遵守框架内部已经存在的约定, 比如log4j的配置文件位置

约定大于配置,配置大于编码

pom

project object model maven工程的核心配置文件,与构建过程相关的一切设置都在这个文件中配置

坐标

也就是GAV

  • groupid 公司或组织域名倒序+项目名
  • arifactid 模块名
  • version 版本

maven工程的坐标与自己在仓库的路径对应

仓库

  • 本地仓库
  • 远程仓库
    • 私服 一般用Nexus,搭建在局域网环境,为当前局域网范围内的所有Maven工程服务。
    • 中央仓库 架设在internet上,为全世界所有maven工程服务
    • 中央仓库镜像 分担中央仓库流量,提升用户访问速度 仓库中保存的内容:maven工程
  • maven自身需要的插件
  • 第三方框架或工具的jar包(第一方是jdk,第二方是我们)
  • 我们自己的maven工程

依赖

maven解析依赖信息会到本地仓库中查找被依赖的jar包, 对于我们自己开发的maven工程,使用install命令安装后就可以进入仓库。

  • 依赖的范围(一般就下面3个) https://gitee.com/lienhui68/picStore/raw/master/null/20200706170304.png
依赖范围 对主程序是否有效 对测试程序是否有效 是否参与打包 典型例子
compile
test × × junit.jar
provided × servlet-api.jar,由servlet容器提供
  • 依赖的传递性 好处:可以传递的依赖不必在每个模块工程中都重复声明,在最小面的工程模块中依赖一次即可。非compile范围的依赖不能传递,所以在各个工程模块,如果有需要就得重复声明,例如单元测试相关。

  • 依赖的排除 依赖的排除也有传递性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
       <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.24</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
  • 依赖的原则 作用:解决模块之间的jar包冲突问题 路径最短者优先: 路径相同时先声明者优先,声明指的是dependency标签

  • 统一管理依赖的版本 建议配置方式,使用properties标签使用自定义标签统一声明版本号,在需要使用版本号的位置使用${自定义标签名}代替版本号 注意:properties标签配合自定义标签声明数据的配置并不只是用于声明依赖的版本号。

继承

现状 假设现在有3个模块都依赖junit,由于test范围的依赖不能传递,所以必然会分散在各个模块工程中,很容易造成版本不一致。 需求 统一管理各个模块工程中对Junit依赖的版本 解决思路 将Junit依赖统一提取到一个父工程中,在子工程中声明Junit依赖时不指定版本,以父工程中统一设定的为准。同时也便于修改。 操作步骤

  1. 创建一个maven工程为父工程。注意打包方式为pom
1
2
3
4
    <groupId>com.eh</groupId>
    <artifactId>Emmanuel</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
  1. 在子工程声明对父工程的引用
1
2
3
4
5
    <parent>
        <artifactId>Emmanuel</artifactId>
        <groupId>com.eh</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
  1. 在父工程中统一管理Junit的依赖
  2. 子工程自动继承父工程的全部依赖
  3. 子工程的artifactId必须声明,因为对该子项目来说它是唯一的。groupId和version如果没有定义则从父POM继承。

注意:配置集成后,执行安装命令要先安装父工程。

聚合主要是为了快速构建项目;继承主要是为了消除重复。

聚合

  1. 作用:一键安装各个模块工程
  2. 配置方式:在一个“总的聚合工程”中配置各个参与聚合的模块
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<modules>
        <module>jdk_foundation</module>
        <module>spring</module>
        <module>design_pattern</module>
        <module>dataStructures_algorithms</module>
        <module>jsp_servlet</module>
        <module>redis</module>
        <module>springMVC</module>
        <module>rabbitMQ</module>
        <module>MybatisDemo</module>
    </modules>
  1. 使用方式:在聚合工程的pom.xml上右键->run as -> maven install或者在聚合工程根目录下执行maven install

生命周期

  1. Maven 构建生命周期 Maven 构建生命周期就是 Maven 将一个整体任务划分为一个个的阶段,类似于流程图,按顺序依次执行。也可以指定该任务执行到中间的某个阶段结束。 Maven 的内部有三个构建生命周期,分别是 clean, default, site。其中 default 生命周期的核心阶段如下所示: https://gitee.com/lienhui68/picStore/raw/master/null/20200706180926.png

  2. 如何使用构建生命周期来完成构建工作 2.1. 可以指定某个生命周期的阶段 执行 mvn install 命令,将完成 validate, compile, test, package, verify, install 阶段,并将 package 生成的包发布到本地仓库中。其中某些带有连字符的阶段不能通过 shell 命令单独指定。例如:(pre-, post-, or process-*) 2.2. 可以指定多个不同构建生命周期的阶段 执行 mvn clean deploy 命令,首先完成的 clean lifecycle,将以前构建的文件清理,然后再执行 default lifecycle 的 validate, compile, test, package, verify, insstall, deploy 阶段,将 package 阶段创建的包发布到远程仓库中。

  3. 阶段与插件的关系 如上所述,Maven将构建过程定义为default lifecycle,并将default lifecycle划分为一个个的阶段phase,这一系列phase仅仅是规定执行顺序,至于每个阶段做什么工作?由谁来做?答案就在插件(plugins)中。 Maven 对工程的所有操作都是由插件来完成的。一个插件可以支持多种功能,称之为目标(goal),例如:compiler插件有两个目标:compile和testCompile,分别实现编译源代码和编译测试代码。 如何将插件与Maven的构建生命周期绑定在一起呢?通过将插件的目标(goal)与build lifecycle中phase绑定到一起,这样,当要执行某个phase时,就调用插件来完成绑定的目标。如下图所示:从图中可以看出,每一个阶段可以绑定0个或多个目标,每个插件可以提供1个或多个目标。 https://gitee.com/lienhui68/picStore/raw/master/null/20200706181912.png

  4. 如何为自己的工程创建构建生命周期 4.1. 设置不同的packaging 类型 在pom.xml文件中,packaging类型支持jar, war, ear, pom等多种类型,不同的packaging类型会使得不同的phase绑定不同的plugin goal。下面是packaging类型为jar时,phase与plugin goal的映射关系。

阶段与插件的关系 目标
process-resources resources:resources
compile compiler:compile
process-test-resources resources:testResources
test-compile compiler:testCompile
test surefire:test
package jar:jar
install install:install
deploy deploy:deploy

小结

仔细查看上面的输出结果截图,可以发现,

  • mvn clean package依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)等7个阶段。
  • mvn clean install依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install等8个阶段。
  • mvn clean deploy依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install、deploy等9个阶段。

由上面的分析可知主要区别如下,

  • package命令完成了项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库
  • install命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库
  • deploy命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库

配置 plugin

在 pom.xml文件中,<build> <plugins> 元素下可以添加 <plugin>,通过指定goal和phase来进行绑定。 例如:将插件modello-maven-plugin的java目标绑定到generate-sources阶段。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<plugin>
  <groupId>org.codehaus.modello</groupId>
  <artifactId>modello-maven-plugin</artifactId>
  <version>1.8.1</version>
  <executions>
    <execution>
      <configuration>
        <models>
          <model>src/main/mdo/maven.mdo</model>
        </models>
        <version>4.0.0</version>
      </configuration>
      <phase>generate-sources</phase>
      <goals>
        <goal>java</goal>
      </goals>
    </execution>
  </executions>
</plugin>

默认的pom.xml文件并没有配置各种plugin,但是也能正常构建工程是因为Maven自己默认指定了plugin。下面是一个没有配置任何plugin的pom.xml,执行mvn install的输出日志,从日志中可以看到 一系列的插件(plugin):版本号:目标(phase),例如maven-resources-plugin:2.6:resources (default-resources),maven-compiler-plugin:3.1:compile (default-compile) ,maven-resources-plugin:2.6:testResources (default-testResources),maven-compiler-plugin:3.1:testCompile (default-testCompile),maven-surefire-plugin:2.12.4:test (default-test),maven-jar-plugin:2.4:jar (default-jar) ,maven-install-plugin:2.4:install (default-install)

 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
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/zhangguanghui/git/my-app/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/zhangguanghui/git/my-app/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/zhangguanghui/git/my-app/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ my-app ---
[INFO] Surefire report directory: /Users/zhangguanghui/git/my-app/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mycompany.app.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ my-app ---
[INFO] Building jar: /Users/zhangguanghui/git/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ my-app ---
[INFO] Installing /Users/zhangguanghui/git/my-app/target/my-app-1.0-SNAPSHOT.jar to /Users/zhangguanghui/.m2/repository/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.jar
[INFO] Installing /Users/zhangguanghui/git/my-app/pom.xml to /Users/zhangguanghui/.m2/repository/com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.726 s
[INFO] Finished at: 2016-11-20T00:41:11+08:00
[INFO] Final Memory: 15M/310M
[INFO] ------------------------------------------------------------------------

插件管理

如同 <dependencyManagement><pluginManagement> 声明了其他 POM 可以使用的 信息,如代码清单 A-2 所示。但是这只适用于子 POM,因为对于插件来说,没有导入声明。和 依赖一样, <version> 坐标是继承的。

代码清单 A-2 pluginManagement

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.2</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.2.1</version>
                </plugin>

            </plugins>
        </pluginManagement>
    </build>

代码清单 A-3 展示了代码清单 A-2 中的 POM 片段的子 POM 是如何使用其父 POM 的 <pluginManagement> 配置的,它只引用了其构建所需的插件。子 POM 还可以重写它需要自 定义的任何插件配置。

代码清单 A-3 插件继承

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

在声明由 Maven 项目生成的插件时,可以省略 groupId (org.apache.maven.plugins),如代码清单 A-2 中的 maven-compiler-plugin 的声明中所示。此外,保留了以“maven”开头的 artifactId , 仅供 Maven 项目使用。例如,第三方可以提供一个 artifactId 为 exec-maven-plugin 的插件, 但是不能为 maven-exec-plugin 。

POM 定义了一个大多数插件都需要遵从的插件配置格式。

maven常用命令

https://cloud.tencent.com/developer/article/1670548

注意:执行与构建过程相关的maven命令,必须进入pom.xml所在的目录。 maven的核心程序仅仅定义了抽象的生命周期,但是具体的工作必须由特定的插件来完成。而插件本身并不包含在maven的核心程序中。当我们执行maven命令时需要用到某些插件时,maven核心程序会首先到本地仓库中查找。如果本地没找到会到中央仓库下载。

常用命令

  • mvn clean 清理 构建得到的产品会放在target, clean会删除target

  • mvn compile 编译

  • mvn test-compile 编译测试文件

  • mvn test 执行测试程序

  • mvn package 打包

  • mvn install 把生成的jar/war包复制到本地repository(就是~/.m2/repository下面)

  • mvn deploy 把生成的jar/war包发送到远程repository(建议配置了私服,那就是往私服发送了)

  • mvn site 生成站点

  • mvn cargo:run 通过cargo插件,把生成的war包部署到本地服务器,并启动。(注意要先运行 mvn clean package 打包)

  • mvn cargo:redeploy 通过cargo插件,把生成的war包部署到远程服务器:如果已经有了,就先undeploy再deploy,如果没有直接deploy(注意要先运行 mvn clean package 打包,并且远程服务器是启动的)

    cargo配置

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <version>1.4.9</version>
            <configuration>
                <container>
                    <containerId>tomcat7x</containerId>
                    <type>remote</type>
                </container>
                <configuration>
                    <type>runtime</type>
                    <properties>
                        <cargo.remote.uri>http://192.168.128.137:8080/manager/text</cargo.remote.uri>
                        <cargo.remote.username>admin</cargo.remote.username>
                        <cargo.remote.password>admin</cargo.remote.password>
                    </properties>
                </configuration>
            </configuration>
        </plugin>
    

    参考:https://www.cnblogs.com/formyjava/p/4626259.html

maven web工程自动部署

 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
<!--配置当前工程构建过程中的特殊设置 -->
  <build>
    <finalName>AtguiguWeb</finalName>
    <!-- 配置构建过程中需要使用的插件 -->
    <plugins>
        <plugin>
            <!-- cargo是一家专门从事启动Servlet容器的组织 -->
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <version>1.2.3</version>
            <!-- 针对插件进行的配置 -->
            <configuration>
                <!-- 配置当前系统中容器的位置 -->
                <container>
                    <containerId>tomcat6x</containerId>
                    <home>D:\DevInstall\apache-tomcat-6.0.39</home>
                </container>
                <configuration>
                    <type>existing</type>
                    <home>D:\DevInstall\apache-tomcat-6.0.39</home>
                    <!-- 如果Tomcat端口为默认值8080则不必设置该属性 -->
                    <properties>
                        <cargo.servlet.port>8989</cargo.servlet.port>
                    </properties>
                </configuration>
            </configuration>
            <!-- 配置插件在什么情况下执行 -->
            <executions>  
                <execution>  
                    <id>cargo-run</id>
                    <!-- 生命周期的阶段 -->  
                    <phase>install</phase>  
                    <goals>
                        <!-- 插件的目标 -->  
                        <goal>run</goal>  
                    </goals>  
                </execution>  
            </executions>
        </plugin>
     </plugins>
    </build>

执行mvn deploy命令

中央仓库地址

我们可以到 http://mvnrepository.com/ 搜索需要的 jar 包的依赖信息。

参考

理解maven命令package、install、deploy的联系与区别

深入理解maven构建生命周期和各种plugin插件

Maven 依赖树的解析规则