活久见!64 张图带你 Maven 实战通关(三)

简介: 看完本篇文章后相信你对 Maven 的理解能更进一步

依赖的排除


如果我们在当前工程中引入了一个依赖是 A,而 A 又依赖了 B,那么 Maven 会自动将 A 依赖的 B 引入当前工程,但是个别情况下 B 有可能是一个不稳定版,或对当前工程有不良影响。这时我们可以在引入 A 的时候将 B 排除。

比如:我们在Maven_first 中添加 spring-core,maven 会自动将 commons-logging添加进来,那么由于 Maven_second 是依赖 Maven_first  的,那么 Maven_second  中将存在 spring-core(自带了commons-logging),这时候我们不想要 commons-logging,那该怎么办呢?我们上面第二大点提到了:

exclusions:用来排除传递性依赖

Maven_first 的 pom.xml 文件

51.png

由于 Maven_second 依赖 Maven_second,故 Maven_second 存在 spring-core 包

52.png

如何排除呢?我们在 Maven_second 的 pom.xml 文件中添加如下代码:

53.png

再次查看工程:Maven_second 的 commons-logging 已经移除了

54.png



依赖的冲突


在 maven 中存在两种冲突方式:一种是跨 pom 文件的冲突,一致是同一个 pom 文件中的冲突。


「跨 pom 文件,路径最短者优先」


比如我们在 Maven_first 中的 Junit 是4.9版本的,Maven_second 中的 Junit 是4.8版本的,那么Maven_third 中的 Junit 将会是那个版本呢?

55.png

由上图我们可以看出,由于 Maven_second 是 Maven_third 的直接依赖,明显相比于 Maven_first 路径要短,所以 Maven_third 的 Junit 版本与 Maven_second 保持一致


「同一个pom.xml 文件,先申明者优先」


56.png


「看 Maven_second」

57.png



可选依赖


Optional 标签标示该依赖是否可选,默认是 false。可以理解为,如果为 true,则表示该依赖不会传递下去,如果为false,则会传递下去。

58.png

我们是在 Maven_second 的 pom 文件中设定 Junit 不可传递,那么Maven_third 工程中将不会有来自 Maven_second 的 Junit 的传递。


Maven 生命周期


什么是生命周期


Maven 强大的原因是有一个十分完善的生命周期,生命周期可以理解为项目构建步骤的集合,它定义了各个构建环节的执行顺序,有了这个顺序,Maven 就可以自动化的执行构建命令。

Maven 的核心程序中定义了抽象的生命周期,生命周期中各个阶段的具体任务是由插件来完成的。有三套相互独立的生命周期,各个构建环节执行顺序不能打乱,必须按照既定的正确顺序来执行。

  • 「Clean Lifecycle : 在进行真正的构建之前进行一些清理工作」
  • 「Default Lifecycle:构建的核心部分,编译、测试、打包、安装、部署等等」
  • 「Site Lifecycle:生成项目报告,站点,发布站点」

这三个都是相互独立的。你可以仅仅调用 clean 来清理工作目录,仅仅调用 site 来生成站点。当然,也可以直接运行 mvn claen install site 运行所有这三套生命周期。下面我们分别来谈谈这三个生命周期。


Clean Lifecycle


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

我们前面讲的执行命令 mvn -clean,也就等同于 Clean 生命周期中的第一个阶段 mvn pre-clean clean。注意有 Clean 声明周期,而这个声明周期中又有 clean 阶段。

只要执行后面的命令,那么前面的命令都会执行,不需要再重新去输入命令


Default Lifecycle


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 将最终的包复制到远程的仓库,以让其它开发人员与项目共享。

这里我们强调一下:「在maven中,只要在同一个生命周期,你执行后面的阶段,那么前面的阶段也会被执行,而且不需要额外去输入前面的阶段」

我们举个例子:执行 mven compile 命令,根据上面的声明周期,它会默认执行前面五个个步骤也就是

validate
generate-sources
process-sources
generate-resources
process-resources 复制并处理资源文件,至目标目录,准备打包。
compile 编译项目的源代码。

我们在 eclipse 中执行 mvn compile 命令

59.png

看到红色框的两部分,第一个 maven-compiler-plugin:2.6:resource 就是用来执行前面几个步骤的插件,第二个插件 maven-compiler-plugin:3.1:compile 则是用来执行 mvn compile 的插件。这里我们提一下,mvn 的各个生命周期步骤都是依赖插件来完成的,后面我们会详细讲解 maven 插件。

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

这里经常用到的是 site 阶段和 site-deploy 阶段,用来生成和发布 maven 站点,这是 Maven 比较强大的功能,文档及统计数据自动生成。由于现在的系统会有专门工具来生成文档或报表。所以这个功能也是比较鸡肋吧,不够简洁和美观,用的不太多。


Maven 插件原理


什么是 Maven 插件


上面我们讲了 Maven 的生命周期,我们知道 Maven 的核心是生命周期,生命周期指定了 Maven 命令执行的流程顺序。但是真正实现流程的工程是由插件来完成的。

我们也可以说 Maven 是一个执行插件的框架,每一个任务实际上都是有插件来完成。进一步说每个任务对应了一个插件目标(goal),每个插件会有一个或者多个目标,例如 maven-compiler-plugin 的 compile 目标用来编译位于 src/main/java/ 目录下的主源码,testCompile 目标用来编译位于src/test/java/目录下的测试源码。


配置编译插件


一般我们创建一个 Maven 工程,就算指定了 JDK 的版本,但是你执行 update project 操作,一般 Maven 工程会自动恢复到默认的 JDK 版本,有可能是1.4,有可能是1.5(和 Maven 版本有关)。

那么我们如何指定其 JDK 版本呢?在 pom.xml 中添加如下代码:

<build>
    <plugins>
        <!-- 编译插件,指定 JDK 的版本为1.7 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

下面我们来添加一个 tomcat 插件,首先我们要知道如何创建 Maven Web 工程。


创建 Maven Web 工程


第一步:New maven project,注意打包方式为 war

60.png

第二步:右击项目名,选择 properties,选择Project Facets

61.png

第三步:将 Dynamic Web Module 取消,点击 Apply

62.png

第四部:将 Dynamic Web Module 重新勾选,点击 下方生成的超链接

63.png

第五步:点击超链接,修改目录结构,然后点击 OK,创建 Maven Web 工程完成

64.png

创建的 Web 工程目录结构如下:

65.png


添加 tomcat 插件


我们在上面创建的 web 工程,可以输入  tomcat:run 来使用默认的 tomcat 插件去启动 web 工程,但是默认的插件版本有点低,我们可以手动添加插件。

<build>
    <plugins>
        <!--配置tomcat 插件  -->
    <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <configuration>
            <port>8080</port><!--端口号  -->
            <path>/</path>
        </configuration>
    </plugin>
</plugins>

执行命令是输入:tomcat7:run

66.png


Maven 继承和聚合



继承


有三个 Maven 工程,每个工程都依赖某个 jar 包,比如 Junit,由于 test 范围的依赖不能传递,它必然会分散在每个工程中,而且每个工程的jar 包版本可能不一致。那么如何管理各个工程中对于某个 jar 包的版本呢?

「解决办法:」

将那个 jar 包版本统一提取到 工程中,在子工程中声明依赖时不指定版本,以父工程中统一设定的为准,同时也便于修改。

操作步骤:

创建父工程

67.png

在子工程中声明对父工程的引用

<!--子工程中声明对父工程的引用  -->
<parent>
  <groupId>com.ys.maven</groupId>
  <artifactId>Parent</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <!-- 以当前工程文件为基准的父工程 pom.xml文件的相对路径(可以不配置) -->
  <relativePath>../Parent/pom.xml</relativePath>
</parent>

将子工程的坐标中与父工程坐标重复的内容删除(不删除也可以,为了简洁)

68.png

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

dependencyManagement标签管理的依赖,其实没有真正依赖,它只是管理依赖的版本。

在子工程中删除 Junit 的版本号

69.png以后要更改版本号,我们只需要更改父工程中的版本号即可!!!

父工程通过 properties 统一管理版本号

70.png

我们可以通过<properties></properties>自定义标签,然后在标签里面填写常量,这种方法不仅可以用来管理版本号,还可以用来管理比如设置某种编码等等。


聚合


需求场景:

在真实项目中,一个项目有表现层、业务层、持久层等。我们在用Maven 管理项目的时候,通常为创建多个 Maven 工程,也就是一个项目的多个模块。但是这样分成多个模块了,当我们进行项目打包发布的时候,那么要每一个模块都执行打包操作吗?这种重复的操作我们怎么才能避免呢?

解决办法:

创建一个聚合工程,将其他的各个模块都由这个聚合工程来管理,那么我们在进行项目发布的时候,只需要打包这个聚合工程就可以了。

第一步:创建聚合工程(注意聚合工程的打包方式也必须为 pom,通常由 上面所讲的父工程来充当聚合工程)

71.png

第二步:创建子工程:业务层

选择 Maven Module

72.png

填写子工程模块名,打包方式选择 jar(子工程除了 web 层我们打包方式选择 war ,其余的都选择 jar)

73.png

第三步:创建子工程:表现层和持久层

创建步骤和前面一样,注意表现层打包方式我们要选择 war,因为要发布到 tomcat 容器运行。

第四步:在聚合工程中添加子工程的引用

<modules>
  <module>Service</module>
  <module>Controller</module>
  <module>Mapper</module>
</modules>

注意:这里虽然各个模块有依赖关系,但是可以不让依赖顺序添加,maven会自动识别依赖关系进行编译打包。

这里总的聚合工程随便哪个工程都可以,但是通常用 Parent 工程来完成。

相关文章
|
3月前
|
XML 前端开发 Java
SpringMVC入门到实战------2、SpringMVC创建实例Hello SpringMVC(maven+tomcat)
这篇文章是SpringMVC框架的入门教程,详细指导了如何在IDEA中使用Maven和Tomcat创建SpringMVC工程,包括添加依赖、配置web.xml、编写控制器、创建配置文件、配置Tomcat服务器以及进行基本的测试,展示了一个简单的Hello SpringMVC示例。
SpringMVC入门到实战------2、SpringMVC创建实例Hello SpringMVC(maven+tomcat)
|
6月前
|
XML Java Shell
【深入浅出Maven开发实战】「入门教程系列」带你零基础学习和开发使用Maven开发工具实战指南(实战技术总结)(一)
【深入浅出Maven开发实战】「入门教程系列」带你零基础学习和开发使用Maven开发工具实战指南(实战技术总结)
212 1
|
6月前
|
XML Java Maven
【深入浅出Maven开发实战】「入门教程系列」带你零基础学习和开发使用Maven开发工具实战指南(实战技术总结)(二)
【深入浅出Maven开发实战】「入门教程系列」带你零基础学习和开发使用Maven开发工具实战指南(实战技术总结)
117 0
|
5月前
|
存储 搜索推荐 Java
rodert教你学Maven-实战这一篇就够了(上)
rodert教你学Maven-实战这一篇就够了
49 1
 rodert教你学Maven-实战这一篇就够了(上)
|
5月前
|
Java Linux 网络安全
在Linux上搭建Maven仓库的实战教程
在Linux上搭建Maven仓库的实战教程
324 0
|
5月前
|
存储 Java 测试技术
rodert教你学Maven-实战这一篇就够了(下)
rodert教你学Maven-实战这一篇就够了
34 0
|
6月前
|
Java Maven
Maven实战 Item4 -- Maven核心概念_maven junit version(1)
Maven实战 Item4 -- Maven核心概念_maven junit version(1)
|
6月前
|
前端开发 JavaScript Java
Maven实战 Item3 -- Maven项目构建2_构建一个maven2 3项目
Maven实战 Item3 -- Maven项目构建2_构建一个maven2 3项目
|
6月前
|
JavaScript 安全 前端开发
Maven实战 Item2 -- Maven项目构建(手动)_term2 配置maven(2)
Maven实战 Item2 -- Maven项目构建(手动)_term2 配置maven(2)
|
6月前
|
前端开发 Java Maven
Maven实战 Item2 -- Maven项目构建(手动)_term2 配置maven(1)
Maven实战 Item2 -- Maven项目构建(手动)_term2 配置maven(1)