maven 打的包在哪_maven打包流程学习「建议收藏」

maven 打的包在哪_maven打包流程学习「建议收藏」前言:最近工作中遇到了几次跟maven打包相关的问题,每个问题上网查资料解决都花了不少时间,很影响工作进度。既然遇到好几次,每次都能发现知识盲点,干脆总结整理一下,啃掉这个难啃的骨头。ps:最近看到了一个很有意思句子:因为今天不想跑步,所以才去跑,这是长距离跑者的思维方式。转载:正文:还是首先描述一下最近遇到的几个问题吧:一、初见springboot多模块项目mvn打包遇到的问题-存在依赖但却…

大家好,又见面了,我是你们的朋友全栈君。

前言:

最近工作中遇到了几次跟maven打包相关的问题,每个问题上网查资料解决都花了不少时间,很影响工作进度。既然遇到好几次,每次都能发现知识盲点,干脆总结整理一下,啃掉这个难啃的骨头。

ps:最近看到了一个很有意思句子:因为今天不想跑步,所以才去跑,这是长距离跑者的思维方式。

转载:

正文:

还是首先描述一下最近遇到的几个问题吧:

一、初见

springboot多模块项目mvn打包遇到的问题 – 存在依赖但却无法发现符号

这个描述跟我遇到的问题差不多,简单说就是A\B两个工程是同一个父工程(X)下的子工程,因为A是一个springboot项目,所以父工程X就把parent设置成了:

org.springframework.boot

spring-boot-starter-parent

2.0.1.RELEASE

并且在A项目中配置了打包插件:

org.springframework.boot

spring-boot-maven-plugin

true

然后A\B的都是X。另一个同事开发A,在里边写了一个XXXUtil类。我开发B,为了使用XXXUtil,于是在B的dependency里依赖了A。

本地测试正常,然后就打算mvn install一下,结果就报错:

[INFO] ————————————————————————

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project main-jar: Compilation failure: Compilation failure:

[ERROR] /Users/zhaohui/workspace/Projects/IDEA/packing-test/main-jar/src/main/java/com.zh/Main.java:[3,25] 程序包com.zh.sbt.common不存在

[ERROR] /Users/zhaohui/workspace/Projects/IDEA/packing-test/main-jar/src/main/java/com.zh/Main.java:[8,51] 找不到符号

[ERROR] 符号: 变量 Common2

[ERROR] 位置: 类 com.zh.Main

[ERROR] -> [Help 1]

[ERROR]

奇怪了,测试的时候明明可以,怎么打包的时候就找不到类了呢?于是就打开A项目打出来打jar包,看一下里边是不是真的没有这个类:

zhaohuideMacBook-Pro:target zhaohui$ jar vtf spring-boot-test-1.0-SNAPSHOT.jar

…//此处省略部分输出

350 Thu Feb 28 23:15:32 CST 2019 BOOT-INF/classes/com/zh/sbt/common/Common2.class

347 Thu Feb 28 23:15:32 CST 2019 BOOT-INF/classes/com/zh/sbt/common/Common.class

822 Thu Feb 28 23:15:32 CST 2019 BOOT-INF/classes/com/zh/sbt/Main.class

…//此处省略部分输出

发现,包内的文件夹路径跟我项目的文件夹路径不一致,用luyten-0.5.3反编译代码,发现代码里的package行没有变化,所以springboot有可能使用了自定义的类加载器,把类加载器的根目录设置为了BOOT-INF/classes/,而maven打包的时候,使用的类加载器根目录就是项目根路径,所以才找不到类。

既然是A项目打包的问题,那直接把A项目的标签注释掉不就行了。说干就干,修改完果然可以正常打包了。

然后就是提交代码,部署,结果A项目启动不起来了,报错如下:

zhaohuideMacBook-Pro:target zhaohui$ java -jar spring-boot-test-1.0-SNAPSHOT.jar

spring-boot-test-1.0-SNAPSHOT.jar中没有主清单属性

其实到这里思路已经比较混乱了,为什么spring-boot的打包插件能修改文件路径?为什么不用spring-boot插件就找不到主属性清单?应该用什么打包插件呢?有哪些打包插件呢?每个插件有什么区别呢?

今天太累了,我不想跑步了。。。

面对这么多疑问,大概就是这个感觉。具体怎么解决暂且不表,第一次遇到这个问题,也没有想明白这么多疑问,结果没想到,第二天,又遇到了打包的问题,而且这次的问题更让我郁闷。且听我慢慢道来… …

二、重逢

接下来就说说我的B项目,因为项目的任务是通过程序往hadoop集群提交一个mr任务,B项目的代码特别简单,就是调用yarn的api提交一个任务。

本地测试也没有问题,我就想把代码放到线上跑一下。因为jar包需要很多依赖,就想着直接把所有的依赖都打到一个jar文件里,这样就不用上传一堆依赖jar包了。于是我使用了这个打包插件:

org.apache.maven.plugins

maven-shade-plugin

3.1.1

package

shade

implementation=”org.apache.maven.plugins.shade.resource.ManifestResourceTransformer”>

com.zh.Main

有了昨天的经验,在plugin里边配置里主类,应该没有问题吧,于是执行了一下jar包,然后就报了一个奇怪的错误:

[WARN ] 2019-02-28 23:59:26 [main] o.a.hadoop.util.NativeCodeLoader – Unable to load native-hadoop library for your platform… using builtin-java classes where applicable

[ERROR] 2019-02-28 23:59:26 [main] c.k.dp.dataexchange.manager.Main – Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.

java.io.IOException: Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.

at org.apache.hadoop.mapreduce.Cluster.initialize(Cluster.java:120)

at org.apache.hadoop.mapreduce.Cluster.(Cluster.java:82)

at org.apache.hadoop.mapreduce.Cluster.(Cluster.java:75)

at org.apache.hadoop.mapreduce.Job$9.run(Job.java:1260)

at org.apache.hadoop.mapreduce.Job$9.run(Job.java:1256)

at java.security.AccessController.doPrivileged(Native Method)

at javax.security.auth.Subject.doAs(Subject.java:422)

at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)

at org.apache.hadoop.mapreduce.Job.connect(Job.java:1255)

at org.apache.hadoop.mapreduce.Job.submit(Job.java:1284)

at com.kuaishou.dp.dataexchange.manager.Main.main(Main.java:95)

Exception in thread “main” java.lang.RuntimeException: 集群启动发生异常,异常信息Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.

at com.kuaishou.dp.dataexchange.manager.Main.main(Main.java:102)

这报错信息是什么鬼。。。说明内容一点都不具体,看不懂,只能找到报错的代码:

private void initialize(InetSocketAddress jobTrackAddr, Configuration conf) throws IOException {

ServiceLoader var3 = frameworkLoader;

synchronized(frameworkLoader) {

Iterator i$ = frameworkLoader.iterator();

while(i$.hasNext()) {

ClientProtocolProvider provider = (ClientProtocolProvider)i$.next();

LOG.debug(“Trying ClientProtocolProvider : ” + provider.getClass().getName());

ClientProtocol clientProtocol = null;

try {

if (jobTrackAddr == null) {

clientProtocol = provider.create(conf);

} else {

clientProtocol = provider.create(jobTrackAddr, conf);

}

if (clientProtocol == null) {

LOG.debug(“Cannot pick ” + provider.getClass().getName() + ” as the ClientProtocolProvider – returned null protocol”);

} else {

this.clientProtocolProvider = provider;

this.client = clientProtocol;

LOG.debug(“Picked ” + provider.getClass().getName() + ” as the ClientProtocolProvider”);

break;

}

} catch (Exception var9) {

LOG.info(“Failed to use ” + provider.getClass().getName() + ” due to error: “, var9);

}

}

}

if (null == this.clientProtocolProvider || null == this.client) {

throw new IOException(“Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.”);

}

}

先是debug,打断点,发现不打包执行没有问题,这就比较蛋疼了,排查问题都不好排查。还好有一些debug的日志可以参考。于是执行参数增加 -Xdebug,logback日志级别改成DEBUG,再次执行jar包,中间细节不再赘述,总之找到出问题的代码在这里:

//java.util.ServiceLoader line 338 hasNextService()方法//代码逻辑简单说就是Enumeration configs = ClassLoader.getSystemResources(“META-INF/services/” + ClientProtocolProvider.class.getName());

//如果不打包,获取到的configs size为2,打印出来就是://org.apache.hadoop.mapred.LocalClientProtocolProvider//org.apache.hadoop.mapred.YarnClientProtocolProvider//如果打包,获取到的configs size为1,打印出来就是://org.apache.hadoop.mapred.LocalClientProtocolProvider

搞了半天,打包修改了META-INF/services/里的内容,所以才导致了报错。

ps:吐槽一下hadoop报错信息,完全没有描述出错的问题,导致排查浪费了很多时间。

说实话,解决这个问题,并没有很开心,一方面花了太多时间,另一方面,这次的问题给我带来了更多的困扰:META-INF里边n多东西都是干什么的?打包的时候如何处理META-INF这个文件夹?

最让我奇怪的是,我总共就配置了一个plugin,结果target里边打出来了三个包[xxx.jar\xxx-shade.jar\xxx-source.jar]除了shade以外,其他两个jar为什么会打出来呢?

三、回首

打包给自己的工作带来了这么多困扰,归根结底还是不知道maven到底是怎么打包的,所以遇到了具体的问题就不知道该怎么分析解决。所以这次正好整理了一下思路。虽然没有给出上边问题的具体解决方式,但是能够把思路说明白,后续再慢慢分析解决问题吧。

思考这个问题的入口其实就是maven的这个标签,具体配置在里边的东西都起到了什么作用呢?很幸运的找到了这篇文章maven内部运行原理解析

具体细节我就不描述了,看到这里,我的疑问是,文章中提到,每一个plugin,都要有一个和表明该插件是在哪个阶段执行的哪个方法。我的pom里边并没有配置这些,插件也照样能生效,那我怎么知道具体每个插件的这两个配置项呢?另外如果我一个plugin都没有配置,也正常打包了,这个时候使用的是什么配置呢?

在maven中,所有的PO都有一个根对象,就是Super POM。Super POM中定义了所有的默认的配置项。Super POM对应的pom.xml文件可以在maven安装目录下lib/maven-model-builder-3.0.3.jar:org/apache/maven/model/pom-4.0.0.xml中找到

第一个问题我在这个帖子里找到了解决的方法maven常用插件解析 :

maven-help-plugin

maven-help-plugin是一个小巧的辅助工具。

最简单的help:system可以打印所有可用的环境变量和Java系统属性。

help:effective-pom和help:effective-settings最为有用,它们分别打印项目的有效POM和有效settings,有效POM是指合并了所有父POM(包括Super POM)后的XML,

当你不确定POM的某些信息从何而来时,就可以查看有效POM。

有效settings同理,特别是当你发现自己配置的settings.xml没有生效时,就可以用help:effective-settings来验证。

此外,maven-help-plugin的describe目标可以帮助你描述任何一个Maven插件的信息,还有all-profiles目标和active-profiles目标帮助查看项目的Profile。

所以执行mvn help:effective-pom就可以列出所有的配置项,我对空项目执行了一下这个命令,把默认的所有插件整理了一下,总结如下:

//知乎怎么还不支持表格

| parse | plugin | goal |

| —— | —— | —— |

| clean | maven-clean-plugin | clean |

| process-test-resources | maven-resources-plugin | testResources |

| process-resources | maven-resources-plugin | resources |

| package | maven-jar-plugin | jar |

| compile | maven-compiler-plugin | compile |

| test-compile | maven-compiler-plugin | test-compile |

| test | maven-surefire-plugin | test |

| install | maven-install-plugin | install |

| deploy | maven-deploy-plugin | deploy |

| site | maven-site-plugin | site |

| site-deploy | maven-site-plugin | deploy |

这里出现了maven内部运行原理解析中没有提到的几个parse:[clean/site/site-deploy]这几个的含义在这个帖子找到了答案:maven的三大生命周期

现在知道了具体每个阶段执行的是哪个方法,剩下的只要获取插件的代码就能完整的分析整个打包流程了,代码地址:查看maven插件的源码

至此,整个思路就理清楚了。即使没有把这块硬骨头啃下来,至少已经放进锅里了~~

附录:

最开始查资料的时候,没有搞清楚打包和压缩是两件事,查了一些与压缩相关的内容,其中这个帖子很有意思:RAR和ZIP:压缩大战真相

向菲利普·卡兹致敬!!

总结:

最近工作接触了很多新东西,也遇到了各种个样的问题。天天一边解决问题,还要赶项目进度,每天都要搞到很晚,每当要开始整理一些东西的时候,总是想着:今天太累了,不搞了吧,早点休息养精蓄锐,明天总结。结果天天如此,一拖就是一个月。

因为今天不想跑步,所以才去跑,这是长距离跑者的思维方式。

而我想成为长距离跑者!

以上

最后,让我们保持独立思考,不卑不亢。长成自己想要的样子! (引用自 我非常喜欢的B站up主 ”独立菌儿“->猛戳链接

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/144013.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • JavaScript设计模式—-策略模式[通俗易懂]

    JavaScript设计模式—-策略模式[通俗易懂]声明:这个系列为阅读《JavaScript设计模式与开发实践》—-曾探@著一书的读书笔记1.策略模式的定义将不变的部分和变化的部分隔开是每个设计模式的主题。定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。2.策略模式的目的将算法的使用与算法的实现分离开来。3.传统语言中的策略模式和JavaScript中的策略模式对比3.1.传统语言中的策略模式使用策略模式来实现计算奖金v

  • jdk11的zgc_开源jdk

    jdk11的zgc_开源jdkJDK11ZGC简介注1:本文翻译自这篇"文章"注2:我有了新的独立博客"地址",欢迎访问前言ZGC是最近由Oracle为OpenJDK开源

  • Java HotSpot VM Options 参数设置

    Java HotSpot VM Options 参数设置

  • Activiti工作流使用之项目实例

    Activiti工作流使用之项目实例Activiti工作流使用之项目实例文章目录Activiti工作流使用之项目实例一、配置文件1.1pom依赖引入1.2application.properties文件二、BPMN文件三、控制层Controller四、实现类Service4.1流程启动(不进入下一环节)4.2流程启动(直接进入下一环节)4.3审批任务4.4查询我发起的流程4.5流程下任务详情4.6删除流程4.7我待审核的任务五、监听器六、流程示意一、配置文件1.1pom依赖引入<dependency>

  • linux 虚拟网络_macvlan原理

    linux 虚拟网络_macvlan原理      macvlan是Linux操作系统内核提供的网络虚拟化方案之一,更准确的说法是网卡虚拟化方案。它可以为一张物理网卡设置多个mac地址,相当于物理网卡施展了影分身之术,由一个变多个,同时要求物理网卡打开混杂模式。针对每个mac地址,都可以设置IP地址,本来是一块物理网卡连接到交换机,现在是多块虚拟网卡连接到交换机。macvlan应该很简单。1.环境准备         假设有一块物理…

  • Qt高级——QMake快速入门

    Qt高级——QMake快速入门一、QMake简介qmake是Trolltech公司创建的用来为不同的平台和编译器书写Makefile的工具。qmake是一个用来简化在不同平台间开发工程的构建过程的工具。qmake会自动生成MakeFile文件,可以用于任何软件项目中,无论是否由Qt编写。qmake会注意所有的编译器和平台的依赖性,开发者只需关注自己的代码。qmake作为Qt库和Qt所提供的工具的主要连编工具,可以自动的包含moc和uic的连编规则。二、QMake入门教程1、创建一个工程创建一个应用,包含hell

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号