文章转载自:https://www.jianshu.com/p/e224a6dc8f20
jar包默认都是放到/lib目录下,而如果要新增一个jar包,就需要到处找相应的jar包,如果这个jar包又依赖其他jar包,就比较坑爹了,
网上很多都需要积分或者VIP。或者是如果新建一个项目,我们需要把之前的jar拷贝过去,总之,jar包管理很麻烦
上述的关于jar包的各种闹心的问题都能迎刃而解,而我们只需要关心功能和业务
Maven的功能有哪些
1、工程的创建、测试
2、依赖管理
3、仓库管理
4、自动化部署
。。。。
仓库就是一个位置,可以存储jar包、library jar、插件任何其他的工程指定的文件。
第一次运行maven命令在本地创建的一个文件夹,会把依赖的jar包放到本地仓库,避免每次构建都引用远程仓库的依赖文件
默认地址:${user.home}/.m2/repository目录下。要修改默认位置,只要在 settings.xml文件中定义另一个路径即可,例如:
<localRepository>/anotherDirectory/.m2/respository</localRepository>
Maven的远程仓库可以是任何其他类型的存储库,可通过各种协议,例如 file://
和 http://
来访问。这些存储库可以是由第三方
提供的可供下载的远程仓库,
例如Maven 的中央仓库(central repository):
repo.maven.apache.org/maven2
uk.maven.org/maven2
也可以是在公司内的FTP服务器或HTTP服务器上设置的内部存储库,用于在开发团队和发布之间共享私有的 artifacts。
Maven 的中央仓库是 Maven 社区维护的,里面包含了大量常用的库,我们可以直接引用,但是前提是我们的项目能够访问外网。
maven仓库地址:https://mvnrepository.com/
除了 Maven 的中央仓库外,还有一种就是私有仓库,这种仓库通常都是企业内部创建的一个私有库,用于一些内部jar包的维护与共享。
由于网络原因和鉴于安全性的考虑,很多公司的内外网是隔离的,要想直接访问中央仓库是不可能的,并且直接把内部资源暴露在互联网上也
是非常危险的,所以这时就需要创建一个私有库。
首先 Maven 会到本地仓库中去寻找所需要的jar吧,如果找不到就会到配置的私有仓库中去找,如果私有仓库中也找不到的话,就会到配置
的中央仓库中去找,如果还是找不到就会报错。但是这中间只要在某一个仓库中找到了就会返回了,除非仓库中有更新的版本,或者是snapshot版本。
那么 Maven 的远程仓库是怎么配置的呢?假设我们要配置一个中央仓库,可以像下面这样配置:
<profiles> <profile> <id>central</id> <repositories> <repository> <id>Central</id> <name>Central</name> <url>http://repo.maven.apache.org/maven2/</url> </repository> </repositories> </profile> </profiles> <activeProfiles> <activeProfile>central</activeProfile> </activeProfiles>
Mirror相当于代理,配置一般为了网速考虑
可以在Maven中配置该镜像来替代中央仓库。在settings.xml中配置如下代码:
<mirrors> <mirror> <id>maven.net.cn</id> <mirrorOf>maven.net.cn</mirrorOf> <name>one of the central mirrors in china</name> <url>http://maven.net.cn/content/groups/public/</url> </mirror> </mirrors>
Maven 有三个内置的构建生命周期: default
, clean
和 site
。每个生命周期都由一系列的阶段所构成
阶段的执行是按顺序的,一个阶段执行完成之后才会执行下一个阶段。比如我们执行了一个如下的指令:
mvn install
实际会执行 install
阶段之前的所有阶段,然后才会执行 install
阶段本身。
PS:当我们的项目是多模块的,我们在最顶层执行该指令时,Maven 会遍历每一个子模块,依次执行所有的阶段。
groupId:表示一个团体,可以是公司、组织等
artifactId:表示团体下的某个项目
version:表示某个项目的版本号
他们之间的关系是一对多的,即每个团体下可以有多个项目,每个项目可以有多个版本号,可以用下面这张图来表示:
Maven 核心特点之一是依赖管理。一旦我们开始处理多模块工程(包含数百个子模块或者子工程)的时候,模块间的依赖关系就变得非常复杂,
管理也变得很困难。针对此种情形,Maven 提供了一种高度控制的方法。
依赖传递
依赖传递很好理解,假设 B 依赖于 C,当 A 需要依赖 B 时,则 A 自动获得了对 C 的依赖。依赖传递有时非常好,当我们需要依赖很多jar包时,
我们可以声明一个包来依赖所有的jar,然后只要依赖这个包就可以了。但是有时又很麻烦,因为很可能会造成依赖的冲突。
依赖冲突
当同一个项目中由于不同的jar包依赖了相同的jar包,此时就会发生依赖冲突的情况,如下图所示:
当项目中依赖了a和c,而a和c都依赖了b,这时就造成了冲突。为了避免冲突的产生,Maven 使用了两种策略来解决冲突,分别是短路优先
和声明优先
。
短路优先
短路优先的意识是,从项目一直到最终依赖的jar的距离,哪个距离短就依赖哪个,距离长的将被忽略掉。例如下图所示:
声明优先
声明优先的意思是,通过jar包声明的顺序来决定使用哪个,最先声明的jar包总是被选中,后声明的jar包则会被忽略,如下图所示:
依赖排除
如果我们只想引用我们直接依赖的jar包,而不想把间接依赖的jar包也引入的话,那可以使用依赖排除的方式,将间接引用的jar包排除掉,
如下面的配置所示:
<exclusions> <exclusion> <groupId>excluded.groupId</groupId> <artifactId>excluded-artifactId</artifactId> </exclusion> </exclusions>
聚合
将多个项目同时运行就称为聚合,如下就是一个多模块的项目:
<packaging>pom</packaging> <modules> <module>module-1</module> <module>module-2</module> <module>module-3</module> </modules>
聚合的优势在于可以在一个地方编译多个 pom 文件。
PS:聚合时packaging
必须要是pom
继承
跟java类的继承类似,Maven 的继承特性也会继承父pom中的依赖,假设我们定义了一个父pom:
<groupId>com.houyi</groupId> <artifactId>maven-parent</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency> </dependencies> </dependencyManagement>
然后在子pom中引入这个父pom:
<!-- 指定parent,说明是从哪个pom继承 --> <parent> <groupId>com.houyi</groupId> <artifactId>maven-parent</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 指定相对路径 --> <relativePath>../maven-parent</relativePath> </parent> <!-- 只需要指明groupId + artifactId,就可以到父pom找到了,无需指明版本 --> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies>
使用dependencyManagement,可对依赖进行管理。子类只要不引用这个里面写的groupId + artifactId,则不会添加依赖,这样防止造成重复加了包:
如果不使用dependencyManagement,那么只要写了dependency,子pom中会全部添加到依赖中,而其中很多包可能都用不上。
插件
插件是 Maven 的核心,所有执行的操作都是基于插件来完成的。
为了让一个插件中可以实现众多的相类似的功能,Maven 为插件设定了目标,一个插件中有可能有多个目标。其实生命周期中的每个阶段都是
由插件的一个具体目标来执行的
例如可以用下面的方式配置一个插件:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.2.1</version> <!-- 配置执行 --> <executions> <execution> <phase>package</phase> <goals> <goal>jar-no-fork</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
配置目标 goal 的目的是:这样在执行 mvn package
的时候,就会自动执行 mvn source:jar-no-fork
了,jar-no-fork这个目标是用来进行源码打包的。
除了可以在build元素中配置插件,当然也可以在parent项目中,用pluginManagement来配置,然后在子项目继承即可使用。
PS:
通过插件我们可以做很多事,比如通过mybatis-generator 我们可以生成很多DAO层的代码,再配合通用Mapper+lombok使用的话就可以使你的代码
非常简洁,绝对的生产力工具!
下面列举一些常用的 maven 指令:
指令参数
上面列举的只是比较通用的命令,其实很多命令都可以携带参数以执行更精准的任务。
Maven命令可携带的参数类型如下:
-D 传入属性参数
比如命令:
mvn package -Dmaven.test.skip=true
以-D
开头,将 maven.test.skip
的值设为 true
,就是告诉maven打包的时候跳过单元测试。
同理,mvn deploy -Dmaven.test.skip=true
代表部署项目并跳过单元测试。
-P 使用指定的Profile配置
比如项目开发需要有多个环境,一般为开发,测试,预发,正式4个环境,在pom.xml中的配置如下:
<profiles> <profile> <id>dev</id> <properties> <env>dev</env> </properties> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>qa</id> <properties> <env>qa</env> </properties> </profile> <profile> <id>pre</id> <properties> <env>pre</env> </properties> </profile> <profile> <id>prod</id> <properties> <env>prod</env> </properties> </profile> </profiles> ... <build> <filters> <filter>config/${env}.properties</filter> </filters> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build>
profiles
定义了各个环境的变量id
,filters
中定义了变量配置文件的地址,其中地址中的环境变量就是上面profile
中定义的值,resources
中是定义
哪些目录下的文件会被配置文件中定义的变量替换。
通过maven可以实现按不同环境进行打包部署,命令为:
mvn package -P dev
其中 dev
为环境的变量id,代表使用Id为 dev
的 profile
。
-e 显示maven运行出错的信息
-o 离线执行命令,即不去远程仓库更新包
-X 显示maven允许的debug信息
-U 强制去远程更新snapshot的插件或依赖,默认每天只更新一次
将自己的jar包部署到远程仓库去,可以使用 deploy
指令:
mvn deploy:deploy-file -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=<type-of-packaging> -Dfile=<path-to-file> -DrepositoryId=<id-to-map-on-server-section-of-settings.xml> -Durl=<url-of-the-repository-to-deploy>
最后说下我们为什么要学习maven,大概可以收获这些好处吧:
。。。
原文:https://www.cnblogs.com/huigelaile/p/10910426.html