最近一段时间在使用maven的过程中,连续遇到几个特别的异常情况,现记录下来,加深印象以防再有此类问题发生,也希望给有相同遭遇的小伙伴一点帮助。
问题一:使用外部 jar 包作为依赖时,服务在本地可以运行,在测试环境无法运行。
在与合作方对接时,会有直接使用由对方提供的jar包作为依赖的情况发生,使用方法很简单:
- pom.xml 中按以下方式添加依赖
<!-- 引入第三方jar -->
<dependency>
<groupId>com.xxx.ifi</groupId>
<artifactId>xxx-api-sdk</artifactId>
<version>1.1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/xxx-api-sdk-1.1.0.jar</systemPath>
</dependency>
这里需要注意的是,
- 一般在 jar 包中会包含 pom.properties 文件,提供 groupId、artifactId 及 version(俗称GAV) 三要素的具体信息,需要引用该 jar 时直接使用即可(当然你随便填个 GAV 也没有关系);
- scope:必须指定为 system,表示此类依赖不是通过Maven仓库解析的;
- systemPath:显式地指定依赖文件的路径。
这样配置就可以把本机上的 jar 包作用依赖直接使用,但也导致了我这次遇到的问题 —— 项目在本地可以正常运行,但打包放到测试环境上则无法运行。使用mvn package
命令打包完成后,检查发现图中目录下并没有外部提供的xxx-api-sdk。怎么解决这个问题呢,请往下看。
- spring-boot-maven-plugin 插件设置加上includeSystemScope
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
- includeSystemScope:scope为system的maven默认是不打包进去的,所以导致上面说的,项目打包完成后,对应的lib目录下并没有外部提供的xxx-api-sdk。使用该配置,将指定maven把scope为system的依赖同样打到jar包中去。
此时再看一下打包的jar
已经有xxx-api-sdk的jar包了。扔到测试环境,正常运行,问题解决。
问题二:idea 运行 maven 项目,测试环境可以正常运行,本地程序无法启动。
maven 项目本地运行时提示缺少某个依赖,无法正常启动。但是打包后扔到测试服务器上却可以正常运行。本地与测试环境都是使用 JDK10,同一个 maven 仓库,按理说不应该出现这样的情况。
经过不断跟踪挖掘,终于定位到问题出现在 javassist 这个依赖上,逐行分析 pom 文件,发现了这样一段代码
<profile>
<id>default-tools</id>
<activation>
<jdk>[,1.8]</jdk>
</activation>
<dependencies>
...
</dependencies>
</profile>
<profile>
<id>java9-tools</id>
<activation>
<jdk>[1.9,]</jdk>
</activation>
<dependencies>
...
</dependencies>
</profile>
activation 表示满足条件时才激活,也就是说,当你的jdk版本为1.8及以下,会激活上面的profile,从而加载相应的依赖,而当你的jdk为1.9及以上时,则会激活下面的 profile,加载相应的依赖。
前面说过测试环境和我本地使用的都是 JDK10,正常来说应该都是激活下面的profile,也就不会出现问题。既然测试环境使用 JDK10(这个一般情况下不会有人动)可以正常启动,那么肯定是本地的 jdk 有问题,经过再三确认本地的jdk 没有配置错误之后,我陷入了深思:如果是 profile 的标签取值有问题呢?于是又是漫长的搜寻之路,终于,在 idea 的 maven 配置中,我发现了一个不得了的东西:
【internal内部的; 里面的;】
这玩意儿居然内置了 java8 并且默认使用(以我使用的 IntelliJ IDEA 2018.2 为例),并且完全无视你的项目使用的 jdk 是哪个版本,这不
而 maven 的 标签取值就是来源于此,所以使用idea运行项目时,JDK为1.8,激活上面的profile,而在测试环境运行时,JDK 为10,激活下面的profile,于是出现了虽然两个环境代码相同,但引用的依赖不同的问题。
索幸将此处(JDK for importer)修改为 JDK10 问题就解决了!
问题三:maven 项目无法编译,出现异常信息:Exception in thread "main" java.lang.AssertionError
其实这个问题倒是不难处理,后来发现是仓库里的某个依赖损坏了,删除之后重新下载即可,只是这个提示信息简洁地过分了,直接
当然经过我的不懈努力(指百度(不是)),终于还是找到了能够打印详细错误信息的方法,在 maven-compiler-plugin 配置中,加上 forceJavacCompilerUse,强制打印中出现异常的位置,这样就不会只有一句废话 Exception in thread "main" java.lang.AssertionError 了。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
</plugin>