本篇文章主要通过一问一答的形式讲解maven项目的使用技巧, maven安装、创建项目、引包、命令这几点我们不讲,因为网上有足够的资料去讲解这些maven的基础,我们只讲解一些常见的使用技巧和最常用的maven插件(plug)用法。
Maven的一般使用方法可能大家都比较了解,所以我们这一篇不去啰嗦大家都已经比较熟知的技巧,主要讲解一下由日常开发中所遇到的问题而总结出来的经验。我们主要分以下几点问题去总结:
maven除了引JAR还能做什么(MAVEN能力)
maven是一种构建工具,同等能力的技术还有gradle,maven属于java构建工具的标准,它除了能够引用jar以外,还有以下几点能力:
maven是如何根据我们的配置找到JAR的(基本原理)
当我们在pom文件中声明我们项目依赖的jar资源后,maven默认会首先查找我们计算机本地的repository(可以自定义其他名字)文件夹,repository内部存放jar资源的目录结构非常简单,是与我们声明的groupId和artifactId有关,举例说明:
groupId事实上就是存储在资源库repository文件夹内的包路径,artifactId是资源库repository文件夹内这个jar文件各个版本共同存储的所在文件夹名字。Version对应资源库repository文件夹内这个jar最终存储在的文件夹的文件夹名字。
最终我们引用的jar包就会在我们找到的这个文件夹内,除了jar包以外,还会包含一个同名的POM文件,这个POM文件是为了让我们的项目引用这个jar资源时,去查找这个jar包的jar包依赖。
那么如果我们的资源库repository文件夹内并不包含我们所声明的jar包,这种情况下maven会根据我们pom文件中声明的资源库,按从上至下的顺序一个一个的到第三方资源库去查找。
第三方资源库可以是我们的私服、也是可是外网别人开放出来的maven库,比如阿里开放的库、spring开放的库,当我们本地资源库repository文件夹内找不到目标jar资源时,maven就会根据你配置的repository去查找jar资源。标签解释:
为什么引用了一个JAR资源,而项目中会出现一堆相关的JAR资源(如何定义JAR依赖)
在第一个maven引包原理的问题中我们提到过,maven在引用jar资源时,还会根据伴随它的同名POM文件去引用JAR包以来的JAR包。所以我们在引用jar时,如果我们引用的jar文件的同名POM中也声明引用了其他jar资源,那么我们的项目也会自动把这个jar包依赖的jar全部引进来。这就是为什么在maven项目当中我们只要引用spring-webmvc包后spring-aop不用声明就被引用了一样。所以很多项目发现密密麻麻把所有jar都声明出来是比较啰嗦的没必要的写法。
为什么有时候明明声明了JAR资源,却引不了JAR资源(资源库使用)
这是由于我们本地的资源库repository文件夹内和生命的第三方资源库都找不到目标jar资源,那么这个时候我们需要再找其他的资源库添加到repositories标签里。在这里我介绍一个最好的maven资源库:
最好的jar资源查找网站:
http://www.mvnrepository.com/
什么是jar冲突,如何查看jar冲突(idea使用技巧)
Jar冲突是指A引用C,B也引用C,但是他们引用的C版本不相同,以下介绍使用idea查看jar冲突,命令时也可以使用maven的tree命令查看依赖。
红线部分为jar冲突。
出现JAR版本冲突了怎么办(排除依赖)
比如我们引用的hibernate-entitymanager包它以来的hibernate-core跟我们项目中引入的hibernate-core版本不一致,发生冲突,此时我们可以使用exclusions标签把hibernate-entitymanager依赖的hibernate-core排除掉。再转回idea查看冲突会发现红线消失。
明明声明了A版本JAR事实上却引用到了B版本(引用优先级)
这是由于maven引用jar资源时的优先级问题,它的原则就是:
不知道JAR的最高版本时怎么引用到最高版本(特声明方法)
使用[versio,)去声明version即可,注意是英文符号方括号、逗号、回括号
为何Spring boot中很多jar资源不需要我们声明版本(依赖管理)
因为声明了依赖,dependencyManagerment,依赖管理事实上是引入了另一份pom文件,版本已经在这份我们引入的pom文件中已经声明好了。配置依赖管理很简单,与引入jar类似。只不过多了两个属性:
Maven的项目目录结构怎么自定义(自定义资源位置)
举例说明,上图是声明哪些目录下是我们项目的源码,这一段要放置到
通过它的配置我们可以决定文件是否属于源码,是否需要被编译进去,并且定义编译到最终的哪个文件夹内。
一个大型项目怎么分成多个模块来管理呢(maven项目的父子关系)
这里说的是pom文件的上下级关系,比如我们在springboot项目当中初始化时能够看到parent标签,点击进去我们看到是另一个pom文件。所以pom文件与pom文件之间是可以定义上下级关系的,它自然也决定着我们多项目时的项目之间的关系。甚至我们在父级pom中声明好的jar资源,子pom文件当中无需再次声明。一个父级的pom项目存在多个子pom项目,idea举例说明,图中所有项目全部是以项目:Agile项目容器作为父级maven项目。
定义父pom文件:
我们发现父级pom文件与普通pom文件没有太多区别,仅仅多了一个modules模块,这里生命的model就是子pom文件的artifactId属性。然后我们再看子pom文件:
我们也能够发现子pom文件相比正常的pom文件多了parent配置,parent中的配置就是对应的父级pom文件。这样maven项目的父子关系就建立了。
如何把非.java后缀的资源文件编译到classpath下
看问题10
如何自定义编译结果的目录结构
看问题10
怎么打散装的部署包
Maven在打包时是使用maven的打包插件maven-war-plug,它是将指定编译目录下的所有文件以约定的目录格式进行打包,而打包分两种,一种是散装exploded另一种是普通的war包。散装部署包可以支持我们在项目运行期间更新其中的.class文件。我们看一下具体的配置:
其中的configuration部分是我们要配置告诉maven怎么打包:
warName:打包以后给包起个名字
archive:项目打包以后事实上会在META-INF目录下产生一个MANITEST.MF文件,它的里面会描述一些项目相关的信息,比如main方法的位置,以来的jar包都有哪些,版本作者都是谁,是在哪个jdk版本下编译的。在war、jar打包过程中都需要生成的文件。这一部分是可有可无的配置,不去声明也OK。maven-war-plug也提供类似编译过程中指定哪些文件编译到哪个目录下的功能,但是个人建议还是使用上文提到的resource比较好比较方便,所以这里不做过多的讲解。
打散装部署包:war: exploded,直接调用命令或idea中直接点击会自动打包,但前提是要先把项目进行编译,也就是先调用编译插件。否则你打包的内容将全都是未经编译的.Java文件。
打war包:war:war
打可以运行的jar包
打可运行的jar包事实上只需要把我们打好的jar中的META-INF目录下产生一个MANITEST.MF文件中去声明main函数位置即可。Maven打jar包的插件其中常见的叫maven-jar-plugin,同maven-war-plugin基本类似,同样有archive,它其中的配置项mainClass就是声明我们主函数的所在位置的。
打出来的效果是这样的:
最新版本的maven私服怎么搭建怎么用
到官网下载安装maven私服安装包,安装过程略掉,默认私服的端口是8081
新建自己的maven库:
配置比较简单,不啰嗦,看以下配置以后的效果:
仓库组添加仓库
怎么把自己编写的jar包上传到私服里让别人用
上传:使用maven命令上传,nexus的上传不是很靠谱:
mvn deploy:deploy-file -Dpackaging=jar -Dfile=C:\Users\mydeathtrial\Desktop\agile.jar -Durl=http://localhost:8081/repository/maven-releases/ -DrepositoryId=maven-releases -DgeneratePom=true -DpomFile=C:\Users\mydeathtrial\Desktop\pom.xml
记住俩点Dfile是jar包所在路径、DpomFile是pom文件所在路径。
效果:
使用:先拷贝资源库路径,把我们的私服资源库地址添加到我们项目中的pom中:
为什么我们引用自己私服上的jar包报权限错误
私服有登陆名和密码,我们的maven想要使用私服需要自然也要把私服的账号密码配置到我们安装的maven程序中,打开maven的setting.xml配置文件:id仓库名,其余是用户名和密码。可以配置多个私服的账号信息。