springboot2.0+dubbo-spring-boot-starter聚合項目打可執行的jar包
springboot2.0+dubbo聚合項目打可執行的jar包
springboot2.0+dubbo-spring-boot-starter項目服務方打包和以前老版本的dubbo打包方式不一樣,不需要將dubbo的配置文件放到META-INF下的spring文件夾中,和普通的springboot項目打包相似。
一般dubbo項目都是聚合形式的,下面看一下springboot+dubbo-spring-boot-starter聚合打可執行的jar:
一、spring-boot-maven-plugin打包出來的jar是不可依賴的
列如我有一個parent工程,type為pom,下面兩個spring-boot工程作為它的module,分別為moduleA和moduleB。假如moduleA依賴於moduleB。如果你在moduleB中使用了spring-boot-maven-plugin的默認配置build,或者在root中使用spring-boot-maven-plugin的默認配置build。很遺憾,你在clean package的時候會發現moduleA找不到moduleB中的類。原因就是默認打包出來的jar是不可依賴的。
解決方案:
1、調整你的代碼,把spring-boot的東西從moduleB中移走,但是這麽幹是不可能的。
2、官方告訴我們,你如果不想移代碼,好吧,我這樣來給你解決,給你打兩個jar包,一個用來直接執行,一個用來依賴。於是,你需要指定一個屬性classifier,這個屬性為可執行jar包的名字後綴。比如我設置exec,原項目名為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一定要用解決方案二來設置。否則你不在root工程中用spring-boot-maven-plugin作為builder,而在需要打包的module上使用。
二、jdk8一定要指明
不指明的話在開發工具裏運行沒有一點問題,如果你沒有用到java8的特性打包也沒有問題。一旦你用到了java8的特性,而且使用spring-boot-maven-plugin作為builder,一定要指明jdk版本。不然你會收到類似不識別Lambda,請使用resource8這樣的錯誤。
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
三、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。
目前我的解法是使用register方法代替packages方法,但是問題就是,如果你的類很多,那將是一件痛苦的事情。還好我這裏只需要配置兩個基於jersey的公共類。
順便吐槽一下官方文檔在配置jersey的時候根本沒有提到packages方法,自然也就把這個BOOT-INF陷阱給忽略了。官方關於jersey的配置章節為27.2 JAX-RS and Jersey
假設工程結構如下:
parent
moduleA
moduleB
moduleC
其中moduleB被moduleA依賴,A使用jersey,moduleA和moduleC需要打包為可執行jar
那麽我們有兩種方式聚合
方式一 在parent中指定spring-boot-maven-plugin
parent的pom.xml中的builder
<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>
moduleB的pom.xml中的builder
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
</plugins>
</build>
其余工程不需要builder
方法二 parent的pom.xml不提供builder
moduleA和moduleC的pom.xml中的builder
<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>
最後,兩種方法都需要把jersey配置文件中的packages方法換成register方法
public class JerseyConfig extends ResourceConfig{
public JerseyConfig() {
register(RequestContextFilter.class);
//配置restful package.
//packages("com.zs.vehicle.rpc");
//packages("classes/com/zs/vehicle/rpc");
register(Base.class);
register(Route.class);
}
}
運行maven命令:
mvn clean package
springboot2.0+dubbo-spring-boot-starter聚合項目打可執行的jar包