maven
Maven
基本概念
仓库
用于存储资源,包含各种jar包
分类:
本地仓库:自己电脑上存储资源的仓库,连接远程仓库获取资源
远程仓库:非本机电脑上的仓库,为本地仓库提供资源,分为中央仓库和私服
中央仓库: Maven团队维护,存储所有资源的仓库
私服:部门/公司范围内存储资源的仓库,从中央仓库获取资源
私服的作用:
保存具有版权的资源,包含购买或自主研发的jar
中央仓库中的jar都是开源的,不能存储具有版权的资源
一定范围内共享资源,仅对内部开放,不对外共享
坐标
Maven中的坐标用于描述仓库中资源的位置
Maven坐标主要组成:
groupld:定义当前Maven项目隶属组织名称(通常是域名反写,例如: org.mybatis)
artifactld:定义当前Maven项目名称(通常是模块名称,例如CRM、SMS)
version:定义当前项目版本号
(packaging:定义该项目的打包方式)
Maven坐标的作用:
使用唯一标识,唯一性定位资源位置,通过该标识可以将资源的识别与下载工作交由机器完成
仓库配置
在maven的下载路径下有一个setting文件,可以更改一些基础设置,比如本地仓库的存储位置,以及配置阿里镜像仓库,即从阿里的仓库中获取资源而非中央仓库,这样快一点
Maven的工程目录结构

大概了解一下,现在一般是在idea中直接创建maven工程或spring工程
依赖管理
依赖配置
依赖是指当前项目运行所需的jar,一个项目可以设置多个依赖,这些依赖一般来自于中心仓库(私服),是前人或同事写好的jar包或工具类
依赖传递
在引入一个新的jar包时,这个jar包可能依赖其它的jar包,在导入这个jar包时,会将它的所有依赖也一起导入,这就是依赖的传递性
直接依赖:在当前项目中通过依赖配置建立的依赖关系
间接依赖:被依赖的资源如果依赖其它资源,当前项目间接依赖其它资源
这有时会导致依赖传递冲突问题,也就是可能不同级的依赖相同但版本号不同,应遵守以下原则:
路径优先:当依赖中出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高
声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的
可选依赖
可选依赖指对外隐藏当前所依赖的资源(但仍在使用)
1 | <dependency> |
排除依赖
排除依赖指不再使用当前所指的资源
1 | <dependency> |
依赖范围
依赖的jar默认情况可以在任何地方使用,可以通过scope标签设定其作用范围
作用范围:
主程序范围有效(main文件夹范围内)
测试程序范围有效(test文件夹范围内)
是否参与打包(package指令范围内)
循环依赖
- 优化模块设计: 首先,考虑你的模块设计是否合理。循环依赖通常是模块之间划分不清晰所导致的。尽量遵循单一职责原则,将模块按照功能分割,减少模块之间的直接依赖。
- 拆分和合并模块: 如果发现存在循环依赖,考虑将其中一个或多个模块进行拆分或合并,以消除循环依赖。有时,将功能合并到一个模块中,或者将一些共享的功能抽离成一个独立的模块,可以帮助解决循环依赖问题。
- 使用接口和抽象: 如果模块之间需要互相调用,尽量通过接口或抽象类来定义依赖关系,而不是直接依赖具体实现。这可以减少循环依赖的风险。
- Maven 中的
<dependencyManagement>
: 如果循环依赖是由于版本问题引起的,可以使用 Maven 的<dependencyManagement>
部分来集中管理依赖的版本,以确保一致性。 - 提取接口模块: 为了解决循环依赖,你可以创建一个独立的接口模块,其中定义了所有模块之间的接口。然后各个模块可以依赖于这个接口模块,而不会产生循环依赖。
- 调整模块依赖关系: 在
<dependencies>
部分中,可以明确声明模块的依赖关系和作用域,以便更好地控制依赖。 - 检查插件和目标: 有时,循环依赖可能是由于插件的配置或目标的执行引起的。检查是否有插件或目标的配置引发了循环依赖。
- 使用模块路径: 如果使用 Java 9 及更高版本,可以尝试使用模块路径来隔离模块,避免循环依赖。
- 重新考虑项目结构: 如果循环依赖问题无法通过上述方法解决,可能需要重新审视项目结构和模块之间的关系,进行更大范围的重构。
生命周期与插件
生命周期
生命周期指maven对项目的阶段的管理,一般分为三类:
clean:清理工作
default:核心工作,例如编译,测试,打包,部署等
site:产生报告,发布站点等
在执行某个生命周期时,会默认将这个生命周期前的所有生命周期全部执行完成,除非指定不执行某个生命周期
插件
插件与生命周期内的阶段绑定,在执行到对应生命周期时执行对应的插件功能
内置插件:默认maven在各个生命周期上绑定有预设的功能
自定义插件:通过插件可以自定义其他功能,如果内置插件无法满足特定需求,可以创建自定义插件。自定义插件通常使用 Java 编写,通过继承 Maven 插件框架来实现。
1 | <build> |
idea中执行的生命周期:
- clean: 清理项目构建生成的目录和文件,包括
target
目录。 - compile:编译项目的源代码,生成字节码文件。
- test: 运行项目的单元测试。
- package: 将编译后的代码打包成可分发的格式,如 JAR、WAR 或 EAR。
- install:将项目构建结果安装到本地 Maven 仓库,以供其他项目引用。
- deploy: 将构建结果部署到远程 Maven 仓库,以便其他项目或团队访问。
- site: 生成项目的站点文档和报告,如代码覆盖率、测试报告等。
分模块开发
分模块开发思想是将一个大型应用程序分解为更小、更易管理的模块,每个模块负责不同的功能或组件。每个模块都可以独立开发、测试和部署。如在web编程中,将实体类pojo,业务层service,数据层dao,控制层controller都分别设置为一个独立的模块
这种方式有许多好处:
- 模块化:将应用程序分为模块使得代码更加模块化和组织有序,容易理解和维护。
- 独立开发:开发人员可以专注于自己负责的模块,而不必关心整个应用程序。
- 并行开发:不同模块可以并行开发,提高了开发效率。
- 重用性:可以更轻松地将模块复用在其他项目中,从而提高了代码的重用性。
- 测试:每个模块都可以独立测试,减少了单一应用程序中的复杂度。
- 扩展性:添加新功能时,可以更容易地将新模块集成到现有应用程序中。
模块聚合
模块聚合是将分开开发的模块汇总在一起,形成一个完整的应用程序。通常情况下,会有一个父级 POM(Project Object Model),其中包含所有模块的定义和依赖关系。父级 POM 也可以定义构建的顺序和版本控制策略。对父级模块进行操作时,所有子模块也会进行相同的操作
依赖继承
在父工程中定义依赖管理,在子工程中定义依赖关系,无需声明依赖版本,版本参照父工程中依赖的版本
1 | <! --声明此处进行依赖管理--> |
继承与聚合对比
作用
聚合用于快速构建项目
继承用于快速配置
相同点:
聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中
聚合与继承均属于设计型模块,并无实际的模块内容
不同点:
聚合是在当前模块中配置关系,聚合可以感知到参与聚合的模块有哪些
继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己
属性
在pom文件中可以通过property标签自定义属性,相当于define,之后用到时就可以用#{属性名}直接引用,修改属性中的值就可以同时修改所有引用处的值
属性分为自定义属性,内置属性,setting属性,java系统属性,环境变量属性
版本管理
工程版本
SNAPSHOT(快照版本)
项目开发过程中,为方便团队成员合作,解决模块间相互依赖和时时更新的问题,开发者对每个模块进行构建的时候,输出的临时性版本叫快照版本((测试阶段版本),快照版本会随着开发的进展不断更新
RELEASE(发布版本)
项目开发到进入阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的,即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本
工程版本号约定
约定规范:
- <主版本>.<次版本>,<增量版本><里程碑版本>
- 主版本:表示项目重大架构的变更,如: spring5相较于spring4的迭代
- 次版本:表示有较大的功能增加和变化,或者全面系统地修复漏洞
- 增量版本:表示有重大漏洞的修复
- 里程碑版本:表明一个版本的里程碑(版本内部)。这样的版本同下一个正式版本相比,相对来说不是很稳定,有待更多的测试
范例: 5.1.9.RELEASE
资源加载属性值
如果想任意配置文件中加载pom文件中定义的属性,可以在配置文件中使用 ${属性名}来调用,同时,需要在pom文件中配置开启此方式,反则编译时无法获取到属性值
1 | <!--配置资源文件对应的信息--> |
跳过测试
- 使用命令跳过测试(执行的指令生命周期必须包含测试环节)
1 | mvn 某个指令 -D skipTests |
- 使用界面操作跳过测试
- 使用配置跳过测试(还可以包含或排除某些测试用例)
1 | <plugin> |