最近在公司搭建了一套代码安全质量分析平台--著名的SonarQube开源版本,再配合jenkins组成自动化流程。java
jenkins调用maven作源码编译打包,而后调用SonarQube进行代码扫描,看起来一点问题都没有。web
可是问题来了,公司的项目都是非maven结构的javaweb项目。apache
上网查了一下,非maven结构的javaweb项目经过更多的定制配置,是完成能够用maven来编译打包的。json
这两天碰到公司一个javaweb项目,结构比较特殊,项目里除了引用jar包,还引用了class文件,相似下面的结构安全
在网上查了半天,找不到这样项目结构使用maven的相关实践。运气比较好的是,以前帮公司配置 pinpoint agent 的时候,刚好了解了一个jvm参数 -classpath,通过在家的一系列实验,终于把这样项目结构的工程编译打包,pom的关键配置以下:jvm
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <verbose>true</verbose> <showWarnings>true</showWarnings> <compilerArgs> <arg>-extdirs</arg> <arg>WebContent/WEB-INF/lib</arg> <arg>-classpath</arg> <arg>ImportedClasses</arg> </compilerArgs> </configuration> </plugin>
在<compilerArgs>里设置编译用的jvm参数,除了常规引用的放在WebContent/WEB-INF/lib里的全部jar包,还有ImportedClasses目录下的
全部class文件。maven
这样就能够完美的进行编译和打包了。spa
回到公司配置好,编译,报错。有一个类的一个方法找不到。code
这个项目还有一个特别之处,就是其中一个引用的class文件(且称它为a.class),跟其中一个jar包里的class文件的包名、类名如出一辙,反编译看,二者内容却不同。blog
按照上面的配置方法,maven在调用javac编译源码,会按顺序扫描依赖的文件,直到碰到第一个目标。
看下图,maven会从这个搜索路径里,按顺序去找依赖的类,请注意这里的排序:
回到那个报错,由于源码里引用的是 ImportedClasses 里的 a.class 才有的方法,而非 jar 里的a.class,当maven在扫描依赖文件时,首先会碰到 jar 里的 a.class,而后发现这个类没有这个方法,因而报错。
好了,说到这里,解决思路呼之欲出,就是让 ImportedClasses 的顺序比 lib 靠前。
这个方案网上找了一通,多是由于拙略的搜索技巧,找不到别人提供的经验。
本身各类尝试,暂时也没有找到能调整顺序的方法。
舍弃javac 的-extdirs参数,所有依赖写到-classpath里,就能够本身掌控依赖的搜索顺序了。
<compilerArgs> <arg>-classpath</arg> <arg>ImportedClasses;WebContent/WEB-INF/lib/fastjson-1.2.47.jar</arg> </compilerArgs>
把ImportedClasses写在全部jar以前,编择成功。
这个方法的缺点就是,当以来的jar包不少的时候,这个值就变得很长,由于要把每个jar的路径写上去。
碰到这样的项目结构机率通常比较小,因此这也算是一个maven的冷门使用了。遗憾的是网上彷佛找不到关于这种状况的解决方案,特地注册一个博客,以受批判。