写在前面

相信从事Java工作的小伙伴们多多少少都会接触到Maven。使用Maven来搭建项目,能够极大的方便我们构建项目的依赖关系,对于项目中需要依赖的Jar包,也只是简单的在pom.xml中进行配置即可。可以说,Maven能够极大的提高我们的开发效率和项目的维护效率,能够统一项目的依赖环境,提高团队的协作效率。然而,尽管使用Maven的小伙伴很多,但真正掌握了Maven核心配置的又有多少呢?

项目依赖

项目依赖是指Maven 通过依赖传播、依赖优先原则、可选依赖、排除依赖、依赖范围等特性来管理项目classpath。

依赖传播特性

我们的项目通常需要依赖第三方组件,而第三方组件又会依赖其它组件遇到这种情况Maven会将依赖网络中的所有节点都会加入classpath当中,这就是Maven的依赖传播特性。

例如下面的配置

<!-- 添加spring mvc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>

项目直接依赖了spring-webmvc 叫直接依赖,而对commons-logging 依赖是通过webmvc传递的所以叫间接依赖。

依赖优先原则

基于依赖传播特性,导致整个依赖网络会很复杂,难免会出现相同组件不同版本的情况。Maven此时会基于依赖优先原则选择其中一个版本。

  • 第一原则:最短路径优先。
  • 第二原则:相同路径下配置在前的优先。

第一原则示例

<!-- 直接添加commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

上述例子中commons-logging 通过spring-webmvc 依赖了1.1.3,而项目中直接依赖了1.2,基于最短路径原则项目最终引入的是1.2 版本。

第二原则示例

主要步骤如下所示:

(1)添加一个新工程Project B

(2) 配置Project B 依赖 spring-web.3.2.9-RELEASE

(3)当前工程直接依赖 Project B

配置完之后,当前工程 project A 有两条路径可以依赖 spring-web,选择哪一条 就取决于 对 webmvc 和 Project B的配置先后顺序。

  • Project A==> spring-webmvc 5.2.9-RELEASE ==> spring-web 5.2.9-RELEASE
  • Project A==> Project B 1.0.SNAPSHOT ==>spring-web.3.2.9-RELEASE

注意:在同一pom文件,第二原则不在适应。如下配置,最终引用的是1.2 版本,而不是配置在前面的1.1.1版本。

<!-- 在1.2 之前添加 commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency> <dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

可选依赖

可选依赖表示这个依赖不是必须的。通过在<dependency></dependency>中添 加<optional>true</optional> 表示,默认是不可选的。可选依赖不会被传递。

排除依赖

即排除指定的间接依赖。通过配置<exclusions></exclusions>配置排除指定组件。

例如,我们可以使用下面的配置来排除对于spring-web的依赖。

<!-- 排除指定项目 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>

依赖范围

像junit 这个组件 我们只有在运行测试用例的时候去要用到,这就没有必要在打包的时候把junit.jar 包过构建进去,可以通过Maven 的依赖范围配置<scope></scope>来达到这种目的。Maven 总共支持以下四种依赖范围:

  • compile(默认): 编译范围,编译和打包都会依赖。
  • provided: 提供范围,编译时依赖,但不会打包进去。如:servlet-api.jar
  • runtime: 运行时范围,打包时依赖,编译不会。如:mysql-connector-java.jar
  • test: 测试范围,编译运行测试用例依赖,不会打包进去。如:junit.jar
  • system: 表示由系统中classpath指定。编译时依赖,不会打包进去。配合<systemPath></systemPath> 一起使用。示例:java.home下的tool.jar

system 除了可以用于引入系统classpath 中包,也可以用于引入系统非maven 收录的第三方Jar,做法是将第三方Jar放置在 项目的 lib 目录下,然后配置 相对路径,但因system 不会打包进去所以需要配合 maven-dependency-plugin 插件配合使用。当然,我还是推荐小伙伴们通过 将第三方Jar手动install 到仓库。

接下来,我们就列举几个简单的使用示例。

  • system 的通常使用方式
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<optional>true</optional>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
  • system 另外使用方式 ,将工程内的jar直接引入
<dependency>
<groupId>jsr</groupId>
<artifactId>jsr</artifactId>
<version>3.5</version>
<scope>system</scope>
<optional>true</optional>
<systemPath>${basedir}/lib/jsr305.jar</systemPath>
</dependency>
  • 通过插件 将system 的jar 打包进去
<plugin>
<groupId>org.apache.maven.plugins</groupId>\
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</outputDirectory>
<includeScope>system</includeScope>
<excludeGroupIds>com.sun</excludeGroupIds>
</configuration>
</execution>
</executions>
</plugin>
  • 手动加入本地仓库
mvn install:install-file -Dfile=mykit-transaction-message.jar -DgroupId=io.mykit -DartifactId=mykit-transaction-message -Dversion=1.0.0-RELEASE -Dpackaging=jar

项目聚合与继承

聚合

聚合是指将多个模块整合在一起,统一构建,避免一个一个的构建。聚合需要个父工程,然后使用 <modules></modules> 进行配置其中对应的是子工程的相对路径。例如下面的配置。

<modules>
<module>mykit-dao</module>
<module>mykit-service</module>
</modules>

继承

继承是指子工程直接继承父工程 当中的属性、依赖、插件等配置,避免重复配置。继承包括如下几种方式。

  • 属性继承
  • 依赖继承
  • 插件继承

注意:上面的三个配置子工程都可以进行重写,重写之后以子工程的为准。

依赖管理

通过继承的特性,子工程是可以间接依赖父工程的依赖,但多个子工程依赖有时并不一至,这时就可以在父工程中加入<dependencyManagement></dependencyManagement> 声明该工程需要的JAR包,然后在子工程中引入。例如下面的配置。

<!-- 父工程中声明 junit 4.12 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 子工程中引入 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>

项目属性

通过 <properties></properties> 配置属性参数,可以简化配置。例如下面的配置。

<!-- 配置proName属性 -->
<properties>
<projectName>projectName</projectName>
</properties>

我们可以在pom.xml文件中使用下面的形式来引入配置的参数。

${projectName}

接下来,我们再来看几个Maven的默认属性,如下所示。

  • ${basedir} 项目根目录
  • ${version}表示项目版本;
  • ${project.basedir}同${basedir};
  • ${project.version}表示项目版本,与${version}相同;
  • ${project.build.directory} 构建目录,缺省为target
  • ${project.build.sourceEncoding}表示主源码的编码格式;
  • ${project.build.sourceDirectory}表示主源码路径;
  • ${project.build.finalName}表示输出文件名称;
  • ${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes

项目构建配置

构建资源配置

基本配置示例:

<defaultGoal>package</defaultGoal>
<directory>${basedir}/target2</directory>
<finalName>${artifactId}-${version}</finalName>

说明:

  • defaultGoal:执行构建时默认的goal或phase,如jar:jar或者package等
  • directory:构建的结果所在的路径,默认为${basedir}/target目录
  • finalName:构建的最终结果的名字,该名字可能在其他plugin中被改变

resources 配置示例

<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.MF</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
<include>*</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>

说明:

  • resources:build过程中涉及的资源文件
  • targetPath:资源文件的目标路径
  • directory:资源文件的路径,默认位于${basedir}/src/main/resources/目录下
  • includes:一组文件名的匹配模式,被匹配的资源文件将被构建过程处理
  • excludes:一组文件名的匹配模式,被匹配的资源文件将被构建过程忽略。同时被includes和excludes匹配的资源文件,将被忽略。
  • filtering:默认false ,true 表示 通过参数 对 资源文件中 的${key} 在编译时进行动态变更。替换源 -Dkey 和pom 中的 值 或 中指定的properties 文件。

重磅福利

微信搜一搜【冰河技术】微信公众号,关注这个有深度的程序员,每天阅读超硬核技术干货,公众号内回复【PDF】有我准备的一线大厂面试资料和我原创的超硬核PDF技术文档,以及我为大家精心准备的多套简历模板(不断更新中),希望大家都能找到心仪的工作,学习是一条时而郁郁寡欢,时而开怀大笑的路,加油。如果你通过努力成功进入到了心仪的公司,一定不要懈怠放松,职场成长和新技术学习一样,不进则退。如果有幸我们江湖再见!

另外,我开源的各个PDF,后续我都会持续更新和维护,感谢大家长期以来对冰河的支持!!

使用Maven那么久了,你对企业级Maven的核心配置了解多少?的更多相关文章

  1. Maven学习总结(3)——使用Maven构建项目

    Maven学习总结(三)--使用Maven构建项目 maven作为一个高度自动化构建工具,本身提供了构建项目的功能,下面就来体验一下使用maven构建项目的过程. 一.构建Jave项目 1.1.创建J ...

  2. maven -- 学习笔记(一)之maven环境搭建

    首先先感谢博主的分享http://www.cnblogs.com/yjmyzz/p/3495762.html 基本概念: Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建 ...

  3. Maven实战(三)Eclipse构建Maven项目

    1. 安装m2eclipse插件    要用Eclipse构建Maven项目,我们需要先安装meeclipse插件    点击eclipse菜单栏Help->Eclipse Marketplac ...

  4. (转)Maven实战(三)Eclipse构建Maven项目

    1. 安装m2eclipse插件    要用Eclipse构建Maven项目,我们需要先安装meeclipse插件    点击eclipse菜单栏Help->Eclipse Marketplac ...

  5. Maven项目搭建(一):Maven初体验

    今天给大家介绍一个项目管理和综合工具:Maven. Maven: maven读作 ['meivin],本意是指可以被信任的领域专家,致力于传播知识(来自于http://en.wikipedia.org ...

  6. [maven学习笔记]第一节,认识maven,搭建maven开发环境,写第一个HelloWorld

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/40142771 maven官网:http://maven.apache.org/ 学习视 ...

  7. eclipse 创建maven 项目 动态web工程完整示例 maven 整合springmvc整合mybatis

    接上一篇: eclipse 创建maven 项目 动态web工程完整示例 eclipse maven工程自动添加依赖设置 maven工程可以在线搜索依赖的jar包,还是非常方便的 但是有的时候可能还需 ...

  8. 本地安装了Maven但Eclipse的Preferences中没有Maven怎么办?

    Maven是帮助我们进行项目构建管理的一个重要工具,Emmmmmm,因为还是个小白,这里就不装大明白了,就我目前了解Maven是用来管理jar包的,想要在Eclipse上运行就要将它集成到Eclips ...

  9. maven(二):创建一个可用的maven项目,完整过程

    环境:eclipse4.5 (内置maven插件) 创建maven项目 文件菜单--新建--其他-- maven project 下一步 选择web 结构 group id:  指项目在maven本地 ...

随机推荐

  1. e3mall商城的归纳总结6之redis

    一.说在前面的话 前面几节我们主要对该项目的后端进行了增删改查,但是所有的数据都是存放在数据库中,这样的话数据库的压力显而易见是很大的,因此本节学习nosql的缓存,也就是redis的使用,在使用之前 ...

  2. Hihocoder 小Hi小Ho扫雷作死一二三

    这里贴下不用枚举方格是否为雷的方法 a表示输入标号,初始值为-1代表未探知 b表示当前格子是否有雷,初始化为0,0表示未探知,1表示探知肯定有雷,2表示探知肯定无雷(我也不知道为什么不初始化为-1,作 ...

  3. css动画 loading

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Activiti7 流程部署

    首先先绘制一个流程图 创建bpmn文件 然后绘制好节点 然后修改节点信息 指定负责人 点击背景,修改ID和名称 保存 然后重命名成xml 使用diagram打开 导出png 然后包xml改回bpmn ...

  5. 查看带有A-Time的执行计划

    先执行 SQL> alter session set statistics_level=all; 会话已更改. 再执行SQL语句: SQL> select count(*) from tb ...

  6. 原生JDK网络编程- NIO

    什么是NIO? NIO 库是在 JDK 1.4 中引入的.NIO 弥补了原来的 I/O 的不足,它在标准 Java 代码中提供了高速的.面向块的 I/O.NIO翻译成 no-blocking io 或 ...

  7. Go Http包解析:为什么需要response.Body.Close()

    简单来讲就是:为了提高效率,http.Get 等请求的 TCP 连接是不会关闭的(再次向同一个域名请求时,复用连接),所以必须要手动关闭. 2019-01-24 10:43:32 更新 不管是否使用 ...

  8. Oracle自动存储管理ASM

    参考资料: https://docs.oracle.com/cd/B19306_01/server.102/b14231/storeman.htm#ADMIN036 什么是ASM? ASM是Autom ...

  9. Python 字符串去除相邻重复的元素

    1 def quchong(S): 2 str1=[""] 3 for i in S: 4 if i == str1[-1]: 5 str1.pop() 6 else: 7 str ...

  10. Docker学习笔记二(linux下安装Docker)

    Docker学习笔记二(linux下安装Docker) 1.在线安装linux Docker 这种方式首先要保证linux 环境下可以上网,当然,小编是在自己的电脑上安装了虚拟机,在虚拟机上安装了,l ...