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

歡迎關注


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM