当前位置: 首页 > 后端技术 > Java

maven基础知识总结

时间:2023-04-01 18:37:06 Java

这里记录一下maven的基础知识,一方面巩固自己所学的知识,另一方面也希望能给有同样困惑的朋友提供一些帮助。一、maven简介Maven是一个项目管理工具,包括项目对象模型POM(ProjectObjectModel)、一组标准集合、项目生命周期(ProjectLifecycle)、依赖管理系统(DependencyManagementSystem)和用户在生命周期阶段运行为插件目标定义的逻辑。当您使用Maven时,您使用定义良好的POM来描述您的项目,然后Maven可以应用来自一组共享(或自定义)插件的横切逻辑。Maven的核心并没有真正做任何实际的事情,除了解析一些XML文档、管理生命周期和插件之外,它什么都不懂。Maven旨在将主要职责委托给一组可以影响Maven生命周期的Maven插件,提供对目标的访问。绝大多数Maven操作发生在Maven插件的目标上,例如编译源代码、打包二进制代码、发布站点和其他构建任务。您从Apache下载的Maven不知道如何打包WAR文件或运行单元测试,并且Maven的大部分智能是通过从Maven存储库获得的插件实现的。事实上,当您第一次使用全新的Maven安装运行mvninstall之类的命令时,它会从中央Maven存储库下载大部分核心Maven插件。这不仅仅是最小化Maven发行版大小的技巧,它还允许您升级插件以提供项目构建功能。Maven从远程存储库获取依赖项和插件这一事实允许全局重用构建逻辑。使用以下命令查看指定插件的详细信息:mvnhelp:describe-Dplugin=install-Dfull2.Maven生命周期1.Maven默认生命周期lifecyclephasedescriptionvalidate验证项目是否正确,以及所有必要的一个完整的构建信息是否可用generate-sources生成编译过程中需要包含的所有源码在packageprocess-resources中拷贝process资源文件到Target(目标)目录下,准备打包编译项目的源码process-classes来处理编译后的class文件,比如Java类的bytecodeenhancementgenerate-test-sources生成测试编译过程中包含的所有测试源码process-test-sources对测试源码进行处理,比如过滤一些值generate-test-resources生成测试所需的资源文件process-test-resources拷贝和将测试资源文件处理到测试目标目录test-compile将测试源代码编译到测试目标目录test使用合适的单元测试框架运行不需要打包或发布的测试-integration-test执行一些动作在运行集成测试之前需要。必要时设置环境集成测试需要对包进行处理,发布到集成测试可以运行的环境中。post-integration-test执行集成测试运行后所需的一些操作。比如清理集成测试环境。verify执行所有检查以验证包是否有效并符合质量规范install将包安装到本地仓库以供本地其他项目使用作为依赖将安装包部署到远程仓库并与其他开发人员和项目共享标记在上表常用的生命周期对应idea中maven的生命周期如下图:2.mvnpackage执行时会发生什么我们可以将插件的目标绑定到maven的生命周期阶段,执行mvnpackage命令,并按照Maven中的生命周期循环一步步进行,会运行每个阶段绑定的所有目标。3、Maven项目依赖Maven可以管理内部依赖和外部依赖。内部依赖指的是maven项目内各个模块之间的依赖关系,比如三层web项目中的service模块依赖model模块,或者持久层模块;外部依赖是指对第三方库的依赖,比如对spring和mybatis的依赖等相关依赖。1.依赖范围在pom.xml文件中指定依赖依赖时,可以指定依赖的范围。范围可以控制哪些依赖项在哪些类路径中可用以及哪些依赖项包含在应用程序中。让我们详细看看每个作用域:compile(编译作用域)compile是默认的作用域。如果未提供范围,则依赖范围为编译范围。编译范围的依赖项在所有类路径上都可用,并且它们也被打包。provided(提供的范围)仅当JDK或容器提供了依赖项时才使用提供的依赖项。例如,如果你开发一个web应用程序,你可能需要编译类路径中可用的ServletAPI来编译一个servlet,但你不想在打包的WAR中包含这个ServletAPI,ServletAPIJAR由你提供由应用程序服务器或servlet容器。提供范围的依赖项在编译类路径(而非运行时)上可用,它们不可传递且未打包。runtime(runtimescope)runtimedependencies在运行时需要,但在编译时不需要。例如,您可能在编译时只需要JDBCAPIJAR接口,而在运行时只需要JDBC驱动程序实现。test(testscope)测试范围依赖在正常编译和运行时不需要,它们只在测试编译和测试运行时阶段可用。system(system-wide)system-widedependencies类似于provided,但是你必须在本地系统上显式地提供JAR文件的路径。这样做是为了允许针对属于系统类库的本机对象进行编译。这样的组件应该是一直可用的,Maven不会去仓库找。如果将依赖范围设置为系统范围,则还必须提供systemPath元素。请注意,此范围已弃用(您应该始终尝试从公共或自定义Maven存储库引用依赖项)。scope取值有效范围(compile,runtime,test)依赖传递示例compile(default)allisspring-coreprovidedcompile,testisnotservlet-apiruntimeruntime,testisJDBCdrivertesttestisnotJunitsystemcompile,testnotrecommended2.可选依赖项在pom.xml文件中指定一个依赖项时,可以通过true标签声明这个依赖项为可选依赖项。如果项目中的依赖类库包含可选依赖,我们需要在使用时显示指定的可选依赖。3.传递依赖传递依赖是对一个依赖的依赖。如果project-a依赖于project-b,而后者又依赖于project-c,那么project-c被称为project-a的传递依赖。如果project-c依赖于project-d,那么project-d也被认为是project-a的传递依赖。Maven的部分优势在于它能够管理传递依赖项并使开发人员免受跟踪所有编译时和运行时依赖项的细节的影响。可以只依赖SpringFramework等部分包,不用担心SpringFramework的所有依赖。Maven自动帮你管理,你不需要详细了解配置。Maven是如何做到这一点的?它构建一个依赖图并处理任何可能的冲突和重叠。如果Maven看到两个项目依赖相同的groupId和artifactId,它会自动选择最新版本的依赖。虽然这听起来很方便,但在某些边缘情况下,传递依赖性可能会导致一些配置问题。在这种情况下,您可以使用依赖项排除。你可以在以下情况下使用依赖排除:排除传递依赖引入但项目中没有使用的依赖排除运行时容器已经提供的依赖排除可能有多个实现的API依赖有多个版本的依赖,排除你不想使用的依赖4.依赖管理在一个复杂的maven项目中,有很多模块,如果很多模块使用相同的依赖,比如MySQL数据库驱动依赖,你需要在每个模块版本中独立列出依赖,你当您需要升级到更新版本时遇到问题。由于这些版本号分散在整个项目树中,因此您需要手动修改引用此依赖项的每个pom.xml,确保版本号随处更改。那么如何解决这个问题呢?Maven提供了dependencyManagement元素来统一管理依赖版本号。在pom.xml中使用dependencyManagement元素允许您在子项目中引用依赖项而无需显式列出版本号。Maven将在父子层次结构中向上移动,直到找到具有dependencyManagement元素的项目,并且它将使用dependencyManagement元素中指定的版本号。注意如果子项目定义了版本版本,它将覆盖顶级POM的dependencyManagement元素中的版本。dependencyManagement定义的版本只有在子项目没有直接声明版本时才会使用。顶层pom.xml文件的dependencyManagement中定义的依赖如果子项目中没有引用则不会导入,但是顶层pom.xml的dependencies中定义的依赖会被全部导入子项目,为了不添加一些不必要的必要依赖,使用dependencyManagement可以让你统一集中依赖版本管理,而不需要添加所有子项目都会继承的依赖。换句话说,dependencyManagement元素就像一个环境变量,允许您在项目中的任何位置声明依赖项而无需指定版本号。四、Maven内置属性1.Maven属性可以使用pom.xml文件或资源文件中的属性,资源文件由MavenResource插件的过滤特性处理。属性始终包含在${}中。例如,要引用project.version属性,您可以这样写${project.version}。在任何Maven项目中都有一些隐式属性,它们是:project.*您可以使用project.*前缀来引用pom.xml中的任何值。settings.*可以使用settings.*前缀来引用~/.m2/settings.xml文件中的值。env.*可以使用env.*前缀来引用PATH、M2_HOME等环境变量的值。系统属性任何可以通过System.getProperty()方法检索的属性都可以作为Maven属性引用。您可以使用mvnhelp:system命令查看所有环境变量。除了上面的隐式属性,用户还可以使用来自定义属性。2、pom.xml文件常用属性${project.groupId}:项目的groupId。${project.artifactId}:项目的artifactId。${project.version}:项目的版本,相当于${version}${project.basedir}:表示项目的根目录,即pom.xml文件所在的目录;${project.build.sourceDirectory}:项目的主源码目录,默认为src/main/java/。${project.build.testSourceDirectory}:项目的测试源码目录,默认为/src/test/java/.${project.build.directory}:项目构建输出目录,默认为target/。${project.outputDirectory}:项目主要代码编译输出目录,默认为target/classes/.${project.testOutputDirectory}:项目测试代码编译输出目录,默认为target/testclasses/。${project.build.finalName}:项目包输出文件名,默认为${project.artifactId}-${project.version}3、setting.xml文件的属性和pom的属性一样。用户可以使用以设置开头的属性。引用setting.xml文件的XML元素值。${settings.localRepository}表示本地仓库地址4.自定义属性自定义属性:pom.xml文件的标签下定义的maven属性:5.2.13.RELEASE你可以在其他地方使用自定义属性:org.springframeworkspring-context${spring}/依赖>五。POM最佳实践1.依赖分类如果你有一组依赖在逻辑上被组合在一起,你可以创建一个子模块打包为pom来将这些依赖组合在一起。例如,创建一个名为dependencies的子模块。该模块只包含一个pom.xml文件,用于对一些公共依赖的版本号进行分类管理。注意这个模块的打包类型指定为:pom。比如在dubbo项目中也有使用。它定义了一个名为dubbo-dependencies-bom的子模块。模块中只有一个pom.xml文件,如下图所示:在dubbo-dependencies-bom的父pom.xml中,通过以下方式导入使用:org.apache.dubbodubbo-dependencies-bom${project.version}pomimport2.资源过滤的问题我们在上面的maven生命周期一节中可以知道,maven会将resources:resources对象绑定到process-resources生命周期阶段。默认情况下,resources:resourcestarget的作用是将src/main/resources目录下的文件复制到target/classes目录下。除了将文件复制到输出目录之外,resources:resources目标还可以使用过滤器将资源文件中的符号变量(${变量名})替换为变量指向的值。可以使用如下方法开启过滤功能:src/main/resources目录-->test.txttruesrc/main/resources/my.properties可以使用排除指定目录下的指定文件,支持通配符匹配,如*.txt排除带.txt作为后缀。通过true启用过滤功能,然后可以从pom.xml文件、元素或中指定的properties文件中读取变量的值来替换${变量名}。需要注意的是,当pom.xml文件、元素或中存在相同的变量名时,读取变量的优先级如下:>>pom.xml如下举例说明上面的函数定义了一个hello.txt文件,其中定义了一些变量,以${变量名}的形式来验证变量替换的功能,定义了test.txt来验证文件的功能exclusion,定义了一个my.properties文件指定了变量的值,如下图:使用如下命令编译打包:mvncleanpackage输出结果如下图:来自结果,我们可以看到test.txt文件被排除,自定义变量的值被正确替换了。资源文件是要在Java代码中使用的文件。当代码执行时,会去指定的目录中寻找这些文件。一般情况下,我们使用的资源文件(各种xml、properties、xsd文件等)都放在src/mian/resources下。使用Maven打包时,Maven默认可以将这些资源文件打包到对应的jar中。包或战争包。但有时,资源文件可能会放在src/main/java下。比如Mybatis的Mapper.xml文件和Mapper.java放在一起,导致java文件打到jar包Mapper中。xml没有打入jar包。这时候就需要在pom.xml中添加具体的配置,将这些资源文件打成jar包或者war包。有两种配置方式,一种是在标签节点下添加标签节点,另一种是在中配置maven-resources-plugin等处理资源文件的插件标签节点下的标签节点。标签导入src/main/java中的属性和xml文件.........src/main/resources<排除>**/*.properties**/*.xmlfalsesrc/main/java**/*.properties**/*.xmlfalse......maven-resources-plugin插件方法导入src/main/java中的属性和xml文件maven-resources-plugin2.5copy-xmlsprocess-sourcescopy-resources${basedir}/target/classes${basedir}/src/main/java**/*.xml参考文档maven指南