springboot项⽬编译后⽆法扫描加载到⼦jar包中的注解解决⽅
法
A项⽬依赖B项⽬,B项⽬中存在@service等注解,在本地eclipse中运⾏A项⽬时可以正常扫描B项⽬的注解创建对象。
但经过打包后,B项⽬和A项⽬的⽬录结构变成
+BOOT-INF
+classes
+lib
+META-INF
+org.springframework.boot.loader
B项⽬本⾝⼜作为A项⽬BOOT-INF/lib下的jar包,A项⽬使⽤java -jar从⼊⼝启动类启动后⽆法扫描到B项⽬的注解,
且B项⽬中的lib也与A项⽬中的lib下jar包存在重复。
解决⽅法,在B项⽬的l⽂件中添加<classifier>exec</classifier>
这样B项⽬编译后target⽬录下会产⽣两个⽂件
B.jar B-exec.jar
其中B-exec.jar和之前的结构⼀样
B.jar的⽬录结构是⾮springboot编译项⽬,只有B项⽬⾃⾝的⽂件
+META-INF
+com.B项⽬包名
配置⽂件....
这样再对A项⽬打包后,A项⽬BOOT-INF/lib⽬录下只会加⼊B.jar,实测启动可以正常扫描到B项⽬中的注解
如果需要单独执⾏B项⽬,只需执⾏B-exec.jar即可
--------------------------------------------------------------------------------
场景2:
因为之前⽤到的是,基于springboot框架所搭建的maven⼯程,⽽且都是相互独⽴的。现研发经理要求将所有⼯程进⾏整合和规范化,所以抽出⼀个parent⽗⼯程,base基础模块(包含⼀些公⽤的实体类和⼯具类等),以及其他⼦模块(Module A、 Module B ...)。Module A 以及Module B⼯程都需要依赖base⼯程。
问题:
在对Module A进⾏打包时,出现问题:Module A中所依赖的base⼯程的util程序包不存在。即使能打包成功,⽤java -jar启动jar包也会报Class Not Found,依赖的base⼯程的类不到。
解决⽅案:
未解决之前在base⼯程的l中maven插件的配置如下:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
解决base⼯程的l的maven配置如下:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
原因分析:
spring-boot-maven-plugin打包出来的jar是不可依赖的
我们现在整合后的maven项⽬有⼀个parent⼯程,打包类型为pom,下⾯多个spring-boot⼯程作为它的module,分别为base和moduleA,moduleB。假如moduleA依赖于base。如果你在base中使⽤了spring-boot-maven-plugin的默认配置build,或者在parent⼯程中使⽤spring-boot-maven-plugin的默认配置build。那么在clean package的时候会发现moduleA不到base中的类。原因就是默认打包出来的jar是不可依赖的。
解决⽅案:
官⽅告诉我们,你如果不想移代码,好吧,我这样来给你解决,给你打两个jar包,⼀个⽤来直接执⾏,⼀个⽤来依赖。于是,你需要指定⼀个属性classifier,这个属性为可执⾏jar包的名字后缀。⽐如我设置<classifier>exec</classifier>,原项⽬名为Vehicle-business。那么会得到两个jar:Vehicle-business.jar和Vehicle-bussiness-exec.jar
官⽅⽂档位置:84.5 Use a Spring Boot application as a dependency
总结:回到聚合maven上,如果你在parent⼯程中使⽤了spring-boot-maven-plugin作为builder,那么你的依赖module⼀定要⽤解决⽅案⼆来设置。否则你不在parent⼯程中⽤spring-boot-maven-plugin作为builder,⽽在需要打包的module上使⽤。
⼀般parent⼯程的maven插件配置如下:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
被依赖的maven⼦模块的maven插件配置如下(其余maven⼦模块就不需要配置):
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
其他的坑:
1.jdk8⼀定要指明
不指明的话在开发⼯具⾥运⾏没有⼀点问题,如果你没有⽤到java8的特性打包也没有问题。⼀旦你⽤到了java8的特性,⽽且使⽤spring-boot-maven-plugin作为builder,⼀定要指明jdk版本。不然你会收到类似不识别Lambda,请使⽤resource8这样的错误。
<properties>
<java.version>1.8</java.version>
<mavenpiler.source>1.8</mavenpiler.source>
<mavenpiler.target>1.8</mavenpiler.target>
</properties>
maven打包本地jar包2.BOOT-INF陷阱
这个问题就很恶⼼了。这个时候你已经打包成功,你会发现运⾏jar的时候报错为file not found,⽽且不告诉你是什么⽂件。你打开jar去看,发现需要的lib,配置⽂件,class⼀样也不缺。
其实这⾥要说⼀个概念,spring-boot在打包后,会把⽂件拷贝到BOOT-INF/Classes之下,这个时候你原来定义的扫描包路径将失效。⽽这个问题官⽅⽂档根本没讲,还是我没有看到。
这个陷阱在你使⽤packages定义扫描路径的时候等着你。或者获取⼯程下⽂件的时候。对于获取⽂件的话,可以在原路径前加上classes,当然你要区分开发环境或⽣产环境的话,你可以使⽤profile或者conditional来解决。如果是扫描包路径就恶⼼了,因为你加上classes之后,不报file not found了。⽽是不报错,只是警告你不到hibernate的某些xml。但是你很可能根本没有使⽤hibernate。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论