Maven实战问题和最佳实践
静默虚空Java后端2019-11-07
点击上方Java后端,选择
设为星标
优质文章,及时送达
作者| dunwu
来源 | github.com/dunwu/java-tutorial
一、常见问题
1、dependencies 和 dependencyManagement, plugins 和 pluginManagement 有什么区别?
dependencyManagement是表示依赖jar包的声明,即你在项目中的dependencyManagement下声明了依赖,maven不会力口 载该依赖,dependencyManagement声明可以被继承。
dependencyManagement的一个使用案例是当有父子项目的时候,父项目中可以利用dependencyManagement声明子项目中 需要用到的依赖jar包,之后,当某个或者某几个子项目需要加载该插件的时候,就可以在子项目中dependencies节点只配置 groupId和artifactId就可以完成插件的引用。
dependencyManagement主要是为了统一管理插件,确保所有子项目使用的插件版本保持一致,类似的还有plugins和 pluginManagemento
2、IDEA修改JDK版本后编译报错
错误现象
修改 JDK 版本,指定 maven-compiler-plugin 的 source 和 target 为 1.8。
然后,在Intellij IDEA中执行maven指令,报错:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.0:compile (default-compile) on project ap <1 1 J
错误原因
maven的JDK源与指定的JDK编译版本不符。
排错手段
■查看 Project Settings
Project SDK是否正确
■查看Settings > Maven的配置
JDK for importer 是否正确
Runner是否正确
3.、重复引入依赖
在Idea中,选中Module,使用Ctrl+Alt+Shift+U,打开依赖图,检索是否存在重复引用的情况。如果存在重复引用,可以将多余 的引用删除。
Tips:关注微信公众号:Java后端,每日获取技术博文推送。
4、如何打包一*个可以直接运行的Spring Boot jar包
org.springframework.boot
spring-boot-maven-plugin
repackage
如果引入了第三方jar包,如何打包?
首先,要添加依赖
io.github.dunwu
dunwu-common
1.0.0
system
${project.basedir}/src/main/resources/lib/dunwu-common-1.0.0.jar
接着,需要配置 spring-boot-maven-plugin 插件:
org.springframework.boot
spring-boot-maven-plugin
repackage
true
5、去哪儿找 maven dependency ?
问:刚接触maven的新手,往往会有这样的疑问,我该去哪儿找jar?
答:官方推荐的搜索maven dependency网址:
■ https://search.maven.org
■ https://repository.apache.org
■ https://mvnrepository.com
6、如何指定编码?
问:众所周知,不同编码格式常常会产生意想不到的诡异问题,那么maven构建时如何指定maven构建时的编码?
答: 在 properties 中指定 project.build.sourceEncoding
〈properties〉
〈/properties〉
7、如何指定JDK版本?
问:如何指定maven构建时的JDK版本?
答:有两种方法:
(1) properties 方式
〈project〉
…
〈properties〉
〈/properties〉
…
〈/project〉
(2)使用 maven-compiler-plugin 插件,并指定 source 和 target 版本
〈build〉
…
〈p山gins〉
〈pEgin〉
〈groupId〉org.apache.maven.p山gins〈/groupId〉
〈artifactId〉maven-compiler-pEgin〈/a rtifactId〉
〈version〉3.3〈/version〉
〈configuration〉
〈source〉1.7〈/source〉
〈/configuration〉
〈/p山gin〉
〈/pEgins〉
…
〈/build〉
8、如何避免将dependency打包到构件中?
答:指定maven dependency的scope为provided ,这意味着:依赖关系将在运行时由其容器或JDK提供。
具有此范围的依赖关系不会传递,也不会捆绑在诸如WAR之类的包中,也不会包含在运行时类路径中。
9、如何跳过单元测试
问:执行mvn package或mvn install时,会自动编译所有单元测试(src/test/java目录下的代码),如何跳过这一步?
答:在执行命令的后面,添加命令行参数-Dmaven.test.skip=true或者-DskipTests=true
10、IDEA修改JDK版本后编译报错
错误现象
然后,在Intellij IDEA中执行maven指令,报错:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.0:compile (default-compile) on project api
W I E
错误原因
maven的JDK源与指定的JDK编译版本不符。
排错手段
■查看 Project Settings
Project SDK是否正确
SDK路径是否正确
■查看Settings > Maven的配置
JDK for importer 是否正确
11、重复引入依赖
在Idea中,选中Module,使用Ctrl+Alt+Shift+U,打开依赖图,检索是否存在重复引用的情况。
12、如何引入本地jar
问:有时候,需要引入在中央仓库找不到的jar,但又想通过maven进行管理,那么应该如何做到呢?
答:可以通过设置dependency的scope为system来引入本地jar。
例:
■将私有jar放置在resouces/lib下,然后以如下方式添加依赖:
■ groupId和artifactId可以按照jar包中的package设置,只要和其他jar不冲突即可。
〈dependency〉
xxx
〈artifactId >xxx
1.0.0
system
${project.basedir}/src/main/resources/lib/xxx-6.0.0.jar
〈/dependency〉
13、如何排除依赖
问:如何排除依赖一个依赖关系?比方项目中使用的libA依赖某个库的1.0版。libB以来某个库的2.0版,如今想统一使用2.0
版,怎样去掉1.0版的依赖?
答:通过exclusion排除指定依赖即可。
例:
〈dependency〉
org.apache.zookeeper
zookeeper
3.4.12
true
org.slf4j
slf4j-log4j12
〈/dependency〉
二、最佳实践
1、通过bom统一管理版本
采用类似spring-boot-dependencies的方式统一管理依赖版本。
spring-boot-dependencies 的 pom.xml 形式:
1.2 Maven是什么
Maven是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),反映在配置中, 就是一个pom.xml文件。是一组标准集合,一个项目的生命周期、一个依赖管理系统,另外还包括定义 在项目生命周期阶段的插件(plugin)以及目标(goal)。
当我们使用Maven的使用,通过一个自定义的项目对象模型,pom.xml来详细描述我们自己的项目。
Maven中的有两大核心:
•依赖管理:对jar的统一管理(Maven提供了一^个 Maven的中央仓库,https://mvnrepository.com/,当我们在项目中添 加完依赖之后,Maven会自动去中央仓库下载相关的依赖,并且解决依赖的依赖问题)
•项目构建:对项目进行编译、测试、打包、部署、上传到私服等
2. Maven 安装
• Maven是Java项目,因此必须先安装JDK。
Ic:\Users\javaboy>java -version
Ijava version ^13.0.1" 2019-10-15
Ijava ™ SE Runtime Environment (bui1d 13. 0. 1+9)
[java HotSpot™ 64-Bit Server VM (build 13. 0.1+9, mixed mode, sharing) 1c: \User s \ j av ab oy>—
•下载Maven
下载地址:http://maven.apache.org/download.cgi
★"
首先配置MAVEN_HOME:
然后配置环境变量:
如果使用了 IntelliJ IDEA,可以不用去额外下载Maven,直接使用IDEA中自带的
Maven 插件即可。IntelliJ IDEA 中自带的 Maven 插件在 \ideaIU-2019.2.4.win\plugins\m
aven\lib\maven3 ‘’
Maven的安装整体上来说比较简单,只需要下载安装包,然后解压并配置环境变量即可。不过,我一般其实建议大 家使用IDEA自带的Maven插件,主要是用着方便。
| 3. Maven 配置
实际上,没有特殊需求的话,安装好之后直接就可以用了。一般来说,还是需要稍微配置一下,比如中央仓 库的问题。默认使用Maven自己的中央仓库,使用起来网速比较慢,这个时候,可以通过修改配置文件, 将仓库改成国内的镜像仓库,国内仓库使用较多的是阿里巴巴的仓库。
说明
就是你自己电脑上的仓库,每个人电脑上都有一个仓库,默认位置在当前用户名.m2\repository 一般来说是公司内部搭建的Maven私服,处于局域网中,访问速度较快,这个仓库中存放的jar 一般就是公司内部自己 开发的jar
有Apache团队来维护,包含了大部分的jar,早期不包含Oracle数据库驱动,从2019年8月开始,包含了 Oracle驱 动
现在存在3个仓库,那么jar包如何查找呢?
3.2本地仓库配置
当前用户名.m2\repository,这个位置可以自定义,但是不建议大家自定义这个
1 .虽然所有的本地的jar都放在这个仓库中,但是并不会占用很大的空间。
2 .默认的位置比较隐蔽,不容易碰到
技术上来说,当然是可以自定义本地仓库位置的,在conf/settings.xml中自定义本地仓库位置:
3.3远程镜像配置
由于默认的中央仓库下载较慢,因此,也可以将远程仓库地址改为阿里巴巴的仓库地址:
nexus-aliyun
central
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
这段配置,加在settings.xml中的mirrors节点中:
| 4. Maven常用命令
Maven中有一些常见的命令,如果使用Eclipse需要手动敲命令,如果使用IDEA的话,可以不用命令, 直接点点点就可以了。
常用命令 中文含义说明
mvn clean 清理 这个命令可以用来清理已经编译好的文件
mvn compile 编译 将Java代码编译成Class文件
mvn test 测试 项目测试
mvn 打包 根据用户的配置,将项目打成jar包或者war
package 包
mvn install 安装 手动向本地仓库安装一个jar
mvn deploy 上传 将jar上传到私服
这里需要注意的是,这些命令都不是独立运行的,它有一个顺序。举个简单例子:
我想将jar上传到私服,那么就要构建jar,就需要执行package命令,要打包,当然也需要测试,那就要 走mvn test命令,要测试就要先编译…,因此,最终所有的命令都会执行一遍。不过,开发者也可以手动 配置不执行某一个命令,这就是跳过。一般来是,除了测试,其他步骤都不建议跳过。
4.1通过命令来构建项目
可以直接通过命令来构建一个Maven项目,不过在实际开发中,一般使用Eclipse或者IDEA就可以直 接创建Maven项目了。
项目创建成功后,就两个文件:
说明对一个任何一个项目而言,最最核心的就是这两个。
firsts pp
""Java代码和项目资
mam
java
“论"项目测试相关代码
java
pom.xml中,则定义了所有的项目配置。
org.3avaboy
f irstapp
jar
l.0-SNAPSHOT
firstapp
httD://maven.auache.oraV/UH1>
〈dependencies〉
3unit
juni t
3.6.l
test
4.2 对项目进行打包
接下来,我们通过mvn package命令可以将刚刚创建的项目打成一个jar包。
在打包之前,需要配置JDK的版本至少为7以上,因此,我们还需要手动修改一下pom.xml文件,即添 加如下配置:
添加完成后,执行打包命令,注意执行所有命令时,命令行要定位到pom.xml文件所在的目录,看到如下 提示,表示项目打包成功。
[INFO] Building jar: F:\workspace5\workspace\maven\firstapp\target\firstapp-l.O-SNAPSHOT, jar
[INFO]
[INFO] BUILD SUCCESS
[INFO]
[INFO] Total time: 24. 575 s
[INFO] Finished at: 2019-12-02711:39:36+08:00
[工阪]
4.3 将项目安装到本地仓库
如果需要将项目安装到本地仓库,可以直接执行mvn install命令,注意,mvn install命令会包含上面 的 mvn package 过程。
安装到本地仓库之后,这个时候,点开自己的本地仓库,就可以看到相关的jar 了。
| 5. IDEA 中使用 Maven
不同于Eclipse, IDEA安装完成后,就可以直接使用Maven 了。
5.1 Maven相关配置
IDEA 中,Maven 的配置在 File->Settings->Build,Execution,Deployment->Build Tools->Mav
Pl Settings
Build, Execution, Deployment > Build Tools > Maven
Appearance & Behavior
Keymap
Editor
Plugins
Version Control
Compiler
Debugger
Remote Jar Repository
Deployment
Arquillian Containers
Application Servers
Gradle-Android Compiler
Instant Run
Java Profiler
Required Plugins
Language & Frameworks
OK | Cancel
5.2 JavaSE工程创建
首先在创建一个工程时,选择Maven工程:
如果勾选上Create from archetype,则表示可以根据一个项目骨架(项目模板)来创建一个新的工程,
不过,如果只是创建JavaSE项目,则不用选择项目骨架。直接Next即可。然后填入项目的坐标,即
groupId 和 artifactId。
填完之后,直接Next即可。这样,我们就会获取一个JavaSE工程,项目结构和你用命令创建出来的项目 一模一样。
। v BgSecondapp F:\workspace5\workspace\maven\sec > ■ Jdea
v
▼・ main ■ java / resource 5
v tatest
I java pom.xml j^secondapp.iml
5.3 JavaWeb工程创建
在IDEA中,创建Maven Web项目,有两种思路:
•首先创建一个JavaSE项目,然后手动将JavaSE项目改造成一个JavaWeb项目
•创建项目时选择项目骨架,骨架就选择webapp
两种方式中,推荐使用第一种方式。
5.3.1改造JavaSE项目
这种方式,首先创建一个JavaSE项目,创建步骤和上面的一致。
项目创建完成后,首先修改pom.xml ,配置项目的打包格式为war包。这样,IDEA就知道当前项目是
JavaSE工程,右键单击,选择Open Module Settings,或者直接按F4,然后选择Web,
项目创建完成后,接下来就是部署了。
部署,首先点击IDEA右上角的Edit Configurations:
然后,配置Tomcat:
接下来选择Deployment选项卡,配置要发布的项目:
最后,点击IDEA右上角的三角符号,启动项目。
5.3.2通过webapp骨架直接创建
这种方式比较简单,基本上不需要额外的配置,项目创建完成后,就是一个web项目。只需要我们在创建项 目时,选择webapp骨架即可。
选择骨架之后,后面的步骤和前文一致。
项目创建成功后,只有webapp目录,这个时候,自己手动创建java和resources目录,创建完成后, 右键单击,选择Mark Directory As,将java目录标记为sources root,将resources目录标记为 resources root 即可。
凡是在IDEA右下角看到了 Enable Auto Import按钮,一定点一下
| 6. Maven依赖管理
Maven项目,如果需要使用第三方的控件,都是通过依赖管理来完成的。这里用到的一个东西就是 pom.xml文件,概念叫做项目对象模型(POM,Project Object Model),我们在pom.xml中定义了 Maven项目的形式,所以,pom.xml相当于是Maven项目的一个地图。就类似于web.xml文件用来 描述三大web组件一样。
这个地图中都涉及到哪些东西呢?
6.1 Maven 坐标
〈dependencies〉
〈dependency〉
junit
junit
4.11
test
〈/dependency〉
〈/dependencies〉
• dependencies
在dependencies标签中,添加项目需要的jar所对应的maven坐标。
• dependency
—个dependency标签表示—个坐标
• groupId
团体、公司、组织机构等等的唯一标识。团体标识的约定是它以创建这个项目的组织名称的逆向域名(例如 org.javaboy)开头。—个 Maven坐标必须要包含groupId。一些典型的groupId如apache的 groupId 是 org.apache.
• artifactId
artifactId相当于在一个组织中项目的唯一标识符。
• version
一个项目的版本。一个项目的话,可能会有多个版本。如果是正在开发的项目,我们可以给版本号加上一个 SNAPSHOT,表示这是一个快照版(新建项目的默认版本号就是快照版)
• scope
表示依赖范围。
我们添加了很多依赖,但是不同依赖的使用范围是不一样的。最典型的有两个,一个是数据库驱动,另一个是 单元测试。
数据库驱动,在使用的过程中,我们自己写代码,写的是JDBC代码,只有在项目运行时,才需要执行 MySQL驱动中的代码。所以,MySQL驱动这个依赖在添加到项目中之后,可以设置它的scope为 runtime,编译的时候不生效。
单元测试,只在测试的时候生效,所以可以设置它的scope为test,这样,当项目打包发布时,单元测试的 依赖就不会跟着发布。
6.2依赖冲突
•依赖冲突产生的原因
在图中,a.jar依赖b.jar,同时a.jar依赖d.jar,这个时候,a和b、d的关系是直接依赖的关系,a和 c的关系是间接依赖的关系。
6.2.1冲突解决
1 .先定义先使用
2 .路径最近原则(直接声明使用)
以spring-context为例,下图中x表示失效的依赖(优先级低的依赖,即路径近的依赖优先使用):
上面这两条是默认行为。
我们也可以手动控制。手动控制主要是通过排除依赖来实现,如下:
org.springframework
spring-context
5.1.9.RELEASE
o rg.springfra mewo rk
spring-core
这个表示从spring-context中排除spring-core依赖。
| 7. Maven 私服
Maven仓库管理也叫Maven私服或者代理仓库。使用Maven私服有两个目的:
1 .私服是一个介于开发者和远程仓库之间的代理
2 .私服可以用来部署公司自己的jar
7.1 Nexus 介绍
Nexus是一个强大的Maven仓库管理工具,使用Nexus可以方便的管理内部仓库同时简化外部仓库的 访问。官网是:https://www.sonatype.com/
7.2 安装
• 下载
下载 地址:https://www.sonatype.com/download-oss-sonatype
• 解压
将下载下来的压缩包,拷贝到一个没有中文的路径下,然后解压。
• 启动
解压之后,打开cmd窗口(以管理员身份打开cmd窗口),然后定位了 nexus解压目录,执行 nexus.exe/run命令启动服务。
F:\nexus-3. 14. 0-04-win64\nexus-3.14. 0-04\bin>nexus. exe/run
Preparing JRE …
2019-12-03 09:57:16, 929+0800 INFO [FelixStartLevel] * SY STEN org. sonatype. nexus, pax. logging. NexusLogActivator - start 2019-12-03 09:57:20,508+0800 WARN [FelixStartLevel] "SYSTEM uk. org. lidalia. sysoutslfij. context. Sys0ut0verSLF4JInitialis er - Your logging framework class org. ops4j. pax. logging. slf4j. Slf4jLogger is not known. - if it needs access to the stand ard print In methods on the consols you will need, to register it by calling r e g i st erLog g ing Syst enPa ckage
2019-12-03 09:57:20, 511+0800 INFO [FelixStartLevel] *SYSTEW uk. org. lidalia. sysoutslf4j. context. Sys0ut0verSLF4J - Packag e org. ops4j. pax. logging. slf4j registered; all classes within it or subpackages cif it will be allowed to print to System
★"文
这个启动稍微有点慢,大概有1两分钟的样子
启动成功后,浏览器输入http://lcoalhost:8081打开管理页面。
打开管理页面后,点击右上角上的登录按钮进行登录,默认的用户名/密码是admin/admin123。当然,用 户也可以点击设置按钮,手动配置其他用户。
点击Repositories可以查看仓库详细信息:
7.2.1仓库类型
名称说明
proxy表示这个仓库是一个远程仓库的代理,最典型的就是代理Maven中央仓库
hosted宿主仓库,公司自己开发的一些jar存放在宿主仓库中,以及一些在Maven中央仓库上没有的jar group仓库组,包含代理仓库和宿主仓库
virtual虚拟仓库
7.2.2 上传 jar
上传jar,配置两个地方:
• Maven 的 conf/settings.xml 文件配置:
releases
admin
admin123
snapshots
admin
admin123
在要上传jar的项目的pom.xml文件中,配置上传路径:
releases
http:〃localhost:8081/repository/maven-releases/
snapshots
http://localhost:8081/repository/maven-snapshots/
配置完成后,点击deploy按钮,或者执行m vn deploy命令就可以将jar上传到私服上。
7.2.3 下载私服上的jar
直接在项目中添加依赖,添加完成后,额外增加私服地址即可:
local-repository
http://localhost:8081/repository/maven-public/
true
true
| 8.聚合工程
所谓的聚合工程,实际上也就是多模块项目。在一个比较大的互联网项目中,项目需要拆分成多个模块进 行开发,比如订单模块、VIP模块、支付模块、内容管理模块、CMS、CRM等等。这种拆分方式,实际上更 接近于微服务的思想。在一个模块中,还可以继续进行拆分,例如分成dao、service、controller等。
有人可能会说,这个分包不就行了吗?
小项目当然可以分包,大项目就没法分包了。比如,在一个大的电商系统中,有一个子模块叫做用户管理、 还有一个子模块叫做订单管理,这两个子模块都涉及到用户,像这种情况,我们就需要将用户类单独提取 出来,做成单独的模块,供其他模块调用。
8.1 多模块项目展示
卜-javaboy-parent
卜-javaboy-cms
卜-javaboy-crm
卜-javaboy-manger
|-- javaboy-manager-model
|-- javaboy-manager-dao
|–javaboy-manager-service
|-- javaboy-manager-web
以javaboy-manger为例,javaboy-manager本身并不提供功能,它只负责管理他自己的子模块, 而他的子模块每一个都无法独立运行,需要四个结合在一起,才可以运行。项目打包时,model、dao、 service都将打包成jar,然后会自动将打包好的jar复制到web中,再自动将web打包成war 包。
8.2 IDEA中创建聚合工程
1 .创建—个空的Maven项目:
项目创建完成后,由于parent并不参与业务的实现,只是用来管理它的子模块,因此,src目录可以将 其删除。
2 .选中当前工程,右键单击,New->Module
然后继续选择创建一个Maven项目:
在IDEA中,已经默认指明了当前Module的parent,开发者只需要填入当前Module的 artifactId 即可:
javaboy-manager创建完成后,此时,观察javaboy-parent的pom.xml文件,发现它自动加上 了 packing 属性:
pom.xml (java boy-pa rent) pom.xml (java boy-manager)
Kmlns :xsi="littp://www.w3. org/2001/XMLSchema-instance xsi:schemaLO’Cation="ihttp://maven-apache. org/POM/4„0„
4,0,0
< groupldl>o rg… j ava boy< / groupld>
javaboy-pa rent if act Idl>
pom
eversion^140-SNAPSHOT
14
15
其中,它的packaging属性值为pom,这表示它是一个聚合工程,同时,他还多了 modules节点,指 明了它自己的子模块。同时,注意javaboy-manager ,它自身多了一个parent节点,这个parent 节点描述了它的父模块的属性值:
javaboy-parent
org.javaboy
1.0-SNAPSHOT
这个parent不仅仅是一个简单的父子关系描述,它存在继承关系,一般我们可以在parent中统一定
义依赖或者插件的版本号
3.由于javaboy-manager本身也是—个聚合工程,因此,javaboy-manager的src目录也可以 删除。4 .选中javaboy-manager,右键单击,New->Module创建—个新的Maven模块出来。这个步骤类 似于第二步,不在赘述。这里,新的javaboy-manager-model创建成功后,我们手动配置它的 packaging 属性值为 jar。
5 .依照第 4 步,再分别创建 javaboy-manager-service 以及 javaboy-manager-dao 6.继续仓I」 建javaboy-manager-web模块,不同于其他模块,web模块需要打包成waro web模块创建可以 参考【第五篇文章】。7.web工程创建完成后,完善模块之间的继承关系。
javaboy-manager-web 依赖 javaboy-manager-service javaboy-manager-service 依赖 javaboy-manager-dao javaboy-manager-dao 依赖 javaboy-manager-model
注意,依赖默认是有传递性的,即在javaboy-manager-dao中依赖了 javaboy-manager- model, 在 javaboy-manager-service 也能访问到。
配置后的依赖关系如下图:
接下来就可以在不同的模块中写代码,然后进行项目部署了。部署方式参考【第五篇文章】
有一个需要注意的地方,在多模块项目中,web项目打包需要注意以下问题:
1 .不可以直接单独打包
2 .如果要打包,有两种方式:
•第一种就是先手动挨个将model、dao、service安装到本地仓库
•从聚合工程处打包,即从web的parent处打包。
-END -
推荐阅读
1 .我在华为做外包的真实经历!
2 . HashMap线程不安全的体现
3 .使用Redis搭建电商秒杀系统
4 .什么是一致性Hash算法?
5 .团队开发中Git最佳实践
优质文章,及时送达
作者|种菜得瓜
链接 | cnblogs.com/crazy-fox
我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译 源代码是由maven- compiler-p仙gin完成的。进一步说,每个任务对应了一个插件目标(goal),每个插件会有一个或者多个 目标,例如maven- compiler-plugin的compile目标用来编译位于5©m13访/|3"3/目录下的主源码,testCompile目标用来编译 位于5^^65切3"3/目录下的测试源码。
用户可以通过两种方式调用Maven插件目标。第一种方式是将插件目标与生命周期阶段(lifecycle phase)绑定,这样用户在命 令行只是输入生命周期阶段而已,例如Maven默认将maven-compiler-plugin的compile目标与compile生命周期阶段绑定,因 此命令mvn compile实际上是先定位到8^^^这一生命周期阶段,然后再根据绑定关系调用maven-compiler-plugin的
compile目标。第二种方式是直接在命令行指定要执行的插件目标,例如mvn archetype:generate 就表示调用maven-
archetype-plugin的generate目标, 这种带冒号的调用方式与生命周期无关。
认识上述Maven插件的基本概念能帮助你理解Maven的工作机制,不过要想更高效率地使用Maven, 了解一些常用的插件还是很 有必要的,这可以帮助你避免一不小心重新发明轮子。多年来Maven社区积累了大量的经验,并随之形成了一个成熟的插件生态 圈。Maven官方有两个插件列表,第一个列 表的GroupId为org.apache.maven.plugins,这里的插件最为成熟,具体地址为: http://maven.apache.org/plugins/index.htmlo 第二个列表的GroupId为0rg.codehaus.mojo,这里的插件没有那么核心, 但也有不少十分有用,其地址为:http://mojo.codehaus.org/plugins.htmlo
接下来笔者根据自己的经验介绍一些最常用的Maven插件,在不同的环境下它们各自都有其出色的表现,熟练地使用它们能让你 的日常构建工作事半功倍。
maven-antrun-plugin
http://maven.apache.org/plugins/maven-antrun-plugin/
maven-antrun-plugin能让用户在Maven项目中运行Ant任务。用户可以直接在该插件的配置以Ant的方式编写Target,然后交 给该插件的run目标去执行。在一些由Ant往Maven迁移的项目中,该插件尤其有用。此外当你发现需要编写一些自定义程度很高 的任务,同时又觉 得Maven不够灵活时,也可以以Ant的方式实现之omaven-antrun-plugin的run目标通常与生命周期绑定运 行。
maven-archetype-plugin
Archtype指项目的骨架,Maven初学者最开始执行的Maven命令可能就是mvn archetype:generate,这实际上就是让maven- archetype-phgin生成一个很简单的项目骨架,帮助开发者快速上手。可能也有人看到一些文档写了巾"口 archetype:create, 但实际上create目标已经被弃用了,取而代之的是generate目标,该目标使用交互式的方式提示用户输入必要的信息以创建项 目,体验更好。maven-archetype-phgin还有一些其他目标帮助用户自己定义项目原型,例如你由一个产品需要交付给很多客 户进行二次开发,你就可以为他们提供一个Archtype,帮助他们快速上手。
maven-assembly-plugin
http://maven.apache.org/plugins/maven-assembly-plugin/
maven-assembly-plugin的用途是制作项目分发包,该分发包可能包含了项目的可执行文件、源代码、readme、平台脚本等 等。maven-assembly-plugin支持各种主流的格式如zip、tar.gz、jar和war等,具体打包哪些文件是高度可控的,例如用户可 以 按文件级别的粒度、文件集级别的粒度、模块级别的粒度、以及依赖级别的粒度控制打包,此外,包含和排除配置也是支持
的。maven-assembly- plugin要求用户使用一个名为assembly.xml的元数据文件来表述打包,它的single目标可以直接在命令 行调用,也可以被绑定至生命周期。
maven-dependency-plugin
http://maven.apache.org/plugins/maven-dependency-plugin/
maven-dependency-plugin最大的用途是帮助分析项目依赖,dependency:list能够列出项目最终解析到的依赖列 表,dependency:tree能进一步的描绘项目依赖树,dependency:analyze可以告诉你项目依赖潜在的问题,如果你有直接使用 到的却未声明的依赖,该目标就会发出警告。maven-dependency-plugin还有很多目标帮助你操作依赖文件,例如 dependency:copy-dependencies能将项目依赖从本地Maven仓库复制到某个特定的文件夹下面。
maven-enforcer-plugin
http://maven.apache.org/plugins/maven-enforcer-plugin/
在一个稍大一点的组织或团队中,你无法保证所有成员都熟悉Maven,那他们做一些比较愚蠢的事情就会变得很正常,例如给项 目引入了外部的 SNAPSHOT依赖而导致构建不稳定,使用了一个与大家不一致的Maven版本而经常抱怨构建出现诡异问题。
maven-enforcer- plugin能够帮助你避免之类问题,它允许你创建一系列规则强制大家遵守,包括设定Java版本、设定Maven 版本、禁止某些依赖、禁止SNAPSHOT依赖。只要在一个父POM配置规则,然后让大家继承,当规则遭到破坏的时候,Maven 就会报错。除了标准的规则之外,你还可以扩展该插 件,编写自己的规则。maven-enforcer-plugin的enforce目标负责检查规 则,它默认绑定到生命周期的validate阶段。
maven-help-plugin
maven-help-plugin是一个小巧的辅助工具,最简单的help:system可以打印所有可用的环境变量和Java系统属性。
help:effective-pom和卜606作6日可6-56壮访85最 为有用,它们分别打印项目的有效POM和有效settings,有效POM是指合并了 所有父POM (包括Super POM)后的XML,当你不确定POM的某些信息从何而来时,就可以查看有效POM。有效settings同
理,特别是当你发现自己配置的 settings.xml没有生效时,就可以用help:effective-settings来验证。此外,maven-help-
phgin的describe目标可以帮助你描述任何一个Maven插件的信息,还有all-profiles目标和active-profiles目标帮助查看项目的 Profile。
Tips:关注微信公众号:Java后端,获取每日技术博文推送。
maven-release-plugin
http://maven.apache.org/plugins/maven-release-plugin/
maven-release-plugin的用途是帮助自动化项目版本发布,它依赖于POM中的SCM信息。release:prepare用来准备版本发布, 具体的工作包括检查是否有未提交代码、检查是否有SNAPSHOT依赖、升级项目的SNAPSHOT版本至RELEASE版本、为项目打 标签等等。release:perform则 是签出标签中的RELEASE源码,构建并发布。版本发布是非常琐碎的工作,它涉及了各种检查, 而且由于该工作仅仅是偶尔需要,因此手动操作很容易遗漏一 些细节,maven-release-plugin让该工作变得非常快速简便,不 易出错。maven-release-plugin的各种目标通常直接在命令行调用,因为版本发布显然不是日常构建生命周期的一部分。
maven-resources-plugin
http://maven.apache.org/plugins/maven-resources-plugin/
为了使项目结构更为清晰,Maven区别对待Java代码文件和资源文件,maven-compiler-plugin用来编译Java代码,maven- resources-plugin则用来处理资源文件。默认的主资源文件目录是src/main/resources,很多用户会需要添加额外的资源文件目 录,这个时候就可以通过配置maven-resources-plugin来实现。此外,资源文件过滤也是Maven的一大特性,你可以在资源文 件中使用${propertyName}形式的Maven属性,然后配置maven-resources-plugin开启对资源文件的过滤,之后就可以针对不 同环境通过命令行或者Profile传入属性的值,以实现更为灵活的构建。
maven-surefire-plugin
http://maven.apache.org/plugins/maven-surefire-plugin/
可能是由于历史的原因,Maven 2/3中用于执行测试的插件不是maven-test-plugin,而是maven-surefire-plugin。其实大部分 时间内,只要你的测试 类遵循通用的命令约定(以Test结尾、以TestCase结尾、或者以Test开头),就几乎不用知晓该插件的 存在。然而在当你想要跳过测试、排除某些测试类、或者使用一些TestNG特性的时候,了解巾3"6。皿向心乍初面的一些配置 选项就很有用了。例如 mvn test -Dtest=FooTest这样一条命令的效果是仅运行FooTest测试类,这是通过控制maven- surefire-plugin的1651参数实现的。
http://mojo.codehaus.org/build-helper-maven-plugin/
Maven默认只允许指定一个主Java代码目录和一个测试Java代码目录,虽然这其实是个应当尽量遵守的约定,但偶尔你还是会 希望能够指定多个源码目录(例如为了应对遗留项目),build-helper-maven-plugin的add-source目标就是服务于这个目的, 通常它被绑定到默认生命周期的generate-sources阶段以添加额外的源码目录。需要强调的是,这种做法还是不推荐的,因为它 破坏了 Maven的约定,而且可能会遇到其他严格遵守约定的插件工具无法正确识别额外的源码目录。
build-helper-maven-phgin的另一个非常有用的目标是attach-artifact,使用该目标你可以以classifier的形式选取部分项目文 件生成附属构件,并同时install到本地仓库,也可以deploy到远程仓库。
exec-maven-plugin
http://mojo.codehaus.org/exec-maven-plugin/
exec-maven-plugin很好理解,顾名思义,它能让你运行任何本地的系统程序,在某些特定情况下,运行一个Maven外部的程序 可能就是最简单的问题解决方案,这就是exec:exec的 用途,当然,该插件还允许你配置相关的程序运行参数。除yexec目标之 外,6乂60^^6口卞山8而还提供了一个java目标,该目标要求你 提供一个巾3而1355参数,然后它能够利用当前项目的依赖作为 classpath,在同一个JVM中运行该mainClass。有时候,为了简单的 演示一个命令行Java程序,你可以在POM中配置好exec- maven-plugin的相关运行参数,然后直接在命令运行mvn exec:java以查看运行效果。
jetty-maven-plugin
http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin
在进行Web开发的时候,打开浏览器对应用进行手动的测试几乎是无法避免的,这种测试方法通常就是将项目打包成war文件, 然后部署到Web容器中,再启动容器进行验证,这显然十分耗时。为了帮助开发者节省时间,jetty-maven-plugin应运而生,它 完全兼容Maven项目的目录结构,能够周期性地检查源文件,一旦发现变更后自动更新到内置的Jetty Web容器中。做一些基本 配置后(例如Web应用的contextPath和自动扫描变更的时间间隔),你只要执行mvn jetty:run,然后在IDE中修改代码,代码 经IDE自动编译后产生变更,再由jetty-maven-plugin侦测到后更新至」6壮丫容器,这时你就可以直接测试Web页面了。需要注意 的是,jetty-maven-plugin并不是宿主于Apache或Codehaus的官方插件,因此使用的时候需要额外 的配置settings.xm^
pluginGroups元素,将0rg.mortbay.jetty这个pluginGroup加入。
versions-maven-plugin
http://mojo.codehaus.org/versions-maven-plugin/
很多Maven用户遇到过这样一个问题,当项目包含大量模块的时候,为他们集体更新版本就变成一件烦人的事情,到底有没有自 动化工具能帮助完成这件 事情呢?(当然你可以使用sed之类的文本操作工具,不过不在本文讨论范围)答案是肯定
M,versions-maven- plugin提供了很多目标帮助你管理Maven项目的各种版本信息。例如最常用的,命令mvn versions:set - DnewVersion=1.1-SNAPSHOT 就能帮助你把所有模块的版本更新到1.1-SNAPSHOT。该插件还提供了其他一些很有用的目
标,display-dependency- updates能告诉你项目依赖有哪些可用的更新;类似的display-plugin-updates能告诉你可用的插件
更新;然后use- latest-versions能自动帮你将所有依赖升级到最新版本。最后,如果你对所做的更改满意,则可以使用 mvn
versions:commit提交,不满意的话也可以使用mvn versions:revert进行撤销。
小结
本文介绍了一些最常用的Maven插件,这里指的“常用”是指经常需要进行配置的插件,事实上我们用Maven的时候很多其它插 件也是必须的,例如默认的编译插件maven-compiler-plugin和默认的打包插件maven-jar-plugin,但因为很少需要对它们进 行配置,因此不在本文讨论范围。了解常用的Maven插件能帮助你事倍功半地完成项目构建任务,反之你就可能会因为经常遇到 一些难以解决的问题而感到沮丧。本文介绍的插件基本能覆盖大部分Maven用户的日常使用需要,如果你真有非常特殊的需求, 自行编写一个Maven插件也不是难事,更何况还有这么多开放源代码的插件供你参考。
本文的这个插件列表并不是一个完整列表,读者有兴趣的话也可以去仔细浏览一下Apache和Codehaus Mojo的Maven插件列 表,以的到一个更为全面的认识。最后,在线的Maven仓库搜索引擎如http://search.maven.org/也能帮助你快速找到自己感兴 趣的Maven插件。
-END-
如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「web_resource」,关注后回复「进群」或者扫描下方二维码 即可进入无广告交流群。
J扫描二维码进群1
推荐阅读
1 Java代码是如何一步步输出结果的?
1.1 ntelliJ IDEA详细图解最常用的配置
3 .Maven实战问题和最佳实践
4 12306的架构到底有多牛逼?
5 .团队开发中Git最佳实践
学Java,请关注公众号:Java后端
喜欢文章,点个在看
声明:pdf仅供学习使用,一切版权归原创公众号所有;建议持续关注原创公众号获取最新文章,学习愉快!
试试IDEA解决Maven依赖冲突的高能神器!
桔子 Java后端 2019-12-13
点击上方Java后端,选择设为星标
优质文章,及时送达
作者|桔子
链接 | segmentfault.com/a/1190000017542396
1、何为依赖冲突
Maven是个很好用的依赖管理工具,但是再好的东西也不是完美的。Maven的依赖机制会导致Jar包的冲突。举个例子,现在你 的项目中,使用了两个Jar包,分别是A和B。现在A需要依赖另一个Jar包C, B也需要依赖C。但是A依赖的C的版本是1.0, B依赖 的C的版本是2.0。这时候,Maven会将这1.0的C和2.0的C都下载到你的项目中,这样你的项目中就存在了不同版本的C,这时 Maven会依据依赖路径最短优先原则,来决定使用哪个版本的Jar包,而另一个无用的Jar包则未被使用,这就是所谓的依赖冲 突。
在大多数时候,依赖冲突可能并不会对系统造成什么异常,因为Maven始终选择了一个Jar包来使用。但是,不排除在某些特定 条件下,会出现类似找不到类的异常,所以,只要存在依赖冲突,在我看来,最好还是解决掉,不要给系统留下隐患。
2、解决方法
解决依赖冲突的方法,就是使用Maven提供的标签,标签需要放在标签内部,就像下面这样:
〈dependency)
org.apache.logging.log4j
log4j-core
2.10.0
〈exclusions)
〈exclusion)
log4j-api
org.apache.logging.log4j
〈/exclusion)
〈/exclusions)
〈/dependency)
log4j-core本身是依赖了 log4j-api的,但是因为一些其他的模块也依赖了 log4j-api,并且两个log4j-api版本不同,所以我们 使用标签排除掉log4j-core所依赖的log4j-api,这样Maven就不会下载log4j-core所依赖的log4j-api了,也就保证了我们的 项目中只有一个版本的log4j-api。
3、Maven Helper
看到这里,你可能会有一个疑问。如何才能知道自己的项目中哪些依赖的Jar包冲突了呢? Maven Helper这个lnteliJ lDEA的插件 帮我们解决了这个问题。插件的安装方法我就不讲了,既然你都会Maven了,我相信你也是会安装插件的。
在插件安装好之后,我们打开pom.xml文件,在底部会多出一^个Dependency Analyzer选项
点开这个选项
找到冲突,点击右键,然后选择Exclude即可排除冲突版本的Jar包。
4、小技巧
除了使用Maven Helper查看依赖冲突,也可以使用IDEA提供的方法一一Maven依赖结构图,打开Maven窗口,选择 Dependencies,然后点击那个图标(Show Dependencies)或者使用快捷键(Ctrl+Alt+Shift+U),即可打开Maven依赖关系 结构图
在图中,我们可以看到有一些红色的实线,这些红色实线就是依赖冲突,蓝色实线则是正常的依赖。
来源:http://suo.im/6brHfY
【END】
如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「web_resource」,关注后回复「进群」或者扫描下方二维码 即可进入无广告交流群。
推荐阅读
1我把废旧Android手机改造成了 Linux服务器
2.动画:一个浏览器是如何工作的?
3・为什么你学不会递归?
4 . 一个女生不主动联系你还有机会吗?
5 .团队开发中Git最佳实践
声明:pdf仅供学习使用,一切版权归原创公众号所有;建议持续关注原创公众号获取最新文章,学习愉快!