maven 踩坑小记

474 阅读4分钟

最近一段时间在使用maven的过程中,连续遇到几个特别的异常情况,现记录下来,加深印象以防再有此类问题发生,也希望给有相同遭遇的小伙伴一点帮助。

问题一:使用外部 jar 包作为依赖时,服务在本地可以运行,在测试环境无法运行。

在与合作方对接时,会有直接使用由对方提供的jar包作为依赖的情况发生,使用方法很简单:

  1. 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。怎么解决这个问题呢,请往下看。

image.png

  1. 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

image.png

已经有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 配置中,我发现了一个不得了的东西:

image.png

【internal内部的; 里面的;】

这玩意儿居然内置了 java8 并且默认使用(以我使用的 IntelliJ IDEA 2018.2 为例),并且完全无视你的项目使用的 jdk 是哪个版本,这不

image.png

而 maven 的 标签取值就是来源于此,所以使用idea运行项目时,JDK为1.8,激活上面的profile,而在测试环境运行时,JDK 为10,激活下面的profile,于是出现了虽然两个环境代码相同,但引用的依赖不同的问题。

索幸将此处(JDK for importer)修改为 JDK10 问题就解决了!

问题三:maven 项目无法编译,出现异常信息:Exception in thread "main" java.lang.AssertionError

其实这个问题倒是不难处理,后来发现是仓库里的某个依赖损坏了,删除之后重新下载即可,只是这个提示信息简洁地过分了,直接

image.png

当然经过我的不懈努力(指百度(不是)),终于还是找到了能够打印详细错误信息的方法,在 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>