筆者第三個Spring Cloud(版本爲Spring Boot 1.2)類項目升級最新版本時遇到很多問題,本文內容是做者翻譯Spring Cloud官網一位國外友人文章產生。git
原文地址:github
做者:DAVE SYERspring
Spring Boot 1.3中有一些有趣的新功能,如今能夠在Brixton版本系列的Spring Cloud中使用。Spring Cloud的Angel版本系列與Spring Boot 1.3部分不兼容,所以在升級時須要注意一些重要事項。本文可幫助您更改並更新任何現有應用程序以使用新功能。在嘗試將新版本的Spring項目引入現有代碼庫時,它一般也會有所幫助。app
提示:您可使用
mvn dependency:tree
或gradle dependencies
列出項目中的依賴項並檢查版本。框架
若是你使用的是舊版本的Spring Boot,你可能在你的Maven POM中有這樣的東西:curl
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.7.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent>
要麼maven
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.7.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
或者,若是您使用的是Gradle,spring-boot
buildscript { ext { springBootVersion = '1.2.7.RELEASE' } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } }
要升級到Spring Boot 1.3.0,您能夠將上面的「1.2.7」更改成「1.3.0」。到目前爲止這麼簡單。工具
提示:要查看具備最新版Spring Boot的「典型」Maven POM,您能夠
curl start.spring.io/pom.xml
。要添加Spring Cloud,您能夠添加-d style=cloud-config-client
。能夠經過添加-d bootVersion=1.3.1.BUILD-SNAPSHOT
(例如)來更改Spring Boot版本。爲Gradle使用build.gradle
而不是pom.xml
。gradle
因爲Spring Cloud構建在Spring Boot之上,所以很難找到能夠協同工做的組合。在下文中,咱們將介紹幾個升級場景,並展現您能夠經過依賴關係管理實現的目標。
一般,最大的變化是升級時(Spring Boot 1.2升級到1.3,或者Spring Cloud Angel升級到Brixton)。若是您從Spring Initializr下載了一個項目,那麼它將使用Spring Boot父POM:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
和部分中的Spring Cloud BOM <dependencyManagement>
:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Angel.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
在Gradle中你會看到這樣的東西:
buildscript { ext { springBootVersion = '1.2.7.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Angel.SR4" } }
在任何一種狀況下簡單地更新Spring Boot版本都不會起做用,由於Spring Cloud Angel BOM具備舊版本的Spring Boot和Spring(以及其餘內容)。所以,咱們確實須要升級Spring Boot和Spring Cloud。例如在Maven中:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Brixton.M3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
在Gradle:
buildscript { ext { springBootVersion = '1.3.0.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Brixton.M3" } }
注意:Brixton.M2和全部早期版本的Spring Cloud 與Spring Boot 1.3.0.RELEASE 不兼容。你至少須要Brixton.M3。
假設您要使用Spring Boot快照,或者在發佈時升級到1.3.1,但Spring Cloud沒有明確依賴於您想要的Boot版本的版本。
在Maven中,請記住,若是您使用其中包含的現成父POM之一<dependencyManagement>
並將優先使用。考慮到這一點,若是您使用這些父POM,請確保使用具備最接近所需依賴關係的父級(在此方案中爲Boot one)。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.BUILD-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Brixton.M3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
在Gradle中,事情原則上更簡單,由於沒有「父母」的概念。實際上,Spring Boot插件不能使用與依賴項管理不一樣的版本,除非您也手動應用依賴項管理插件。因此你必須在如下方面作一點舞蹈build.gradle
:
buildscript { ext { springBootVersion = '1.3.0.RELEASE' } repositories { mavenCentral() } dependencies { classpath "io.spring.gradle:dependency-management-plugin:0.5.3.RELEASE" classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: "io.spring.dependency-management" ... dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Brixton.M3" mavenBom "org.springframework.bootspring-boot-starter-parent:1.3.1.BUILD-SNAPSHOT" } } apply plugin: 'spring-boot'
規則是你必須a)手動導入依賴管理插件,而後在Spring Boot 插件以前,b)dependencyManagement
在應用Spring Boot插件以前聲明。一旦你這樣作,你能夠列出dependencyManagement
聲明中的依賴項,最後一個獲勝(與Maven相反)。
注意:這種對聲明順序的敏感性是當前版本工具的「特徵」。在未來的版本中可能會有所不一樣。有關詳細信息,請參閱Gradle工具中的此問題。
若是您不使用現成的父POM,您能夠自由使用不包含的POM <dependencyManagement>
,這使事情更容易控制。在這種狀況下,您須要將Spring Boot和Spring Cloud都放入其中<dependencyManagement>
而且順序很是重要:第一個獲勝(Gradle的最後一個)。例如,在Maven中使用Spring Boot 1.3.1.BUILD-SNAPSHOT和Spring Cloud Brixton.M3:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.BUILD-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-parent</artifactId> <version>Brixton.M3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
請注意,在Maven和Gradle中,BOM的順序很是重要:若是頂層存在衝突(顯式聲明的依賴關係),則首先聲明的那個一般在Maven中獲勝(Gradle中的最後一個)。與Maven的一個重大區別是父母是特殊的:若是它包含<dependencyManagement>
它老是獲勝。
要了解特定的依賴版本是否會以您須要的方式解析,這很複雜。它取決於BOM的順序,以及傳遞依賴關係樹中聲明依賴關係的深度。例如,Spring Boot BOM聲明瞭一個顯式(級別1)依賴關係管理,spring-core
但沒有聲明任何其餘Spring Framework jar(經過對Spring Framework BOM的引用引入)。規則是第一次聲明獲勝,可是包括整個樹(包括全部BOM),從頂部逐層搜索。
注意:沒有Spring Boot(或Spring Dependency Management)插件,Gradle沒有這個「最後一個勝利」規則。要使用「本機」Gradle構建作一樣的事情,一般須要手動修復傳遞依賴版本的細緻而繁瑣的工做。
若是您但願將依賴項版本超出Spring Boot和Spring Cloud BOM中指定的版本,那麼事情就會變得複雜。從廣義上講,有兩個選項:屬性和其餘BOM。第一個(屬性)與現成的父POM一塊兒工做,而另外一個不工做。第二(更BOM表)只有在有工做是可供你有興趣,而且僅當傳遞依賴不符合您的要求相沖突的相關性的BOM。例如,全部Spring Cloud項目都有本身的BOM,就像Spring Framework同樣,因此這是一個開始。
Spring Boot父POM(若是您使用它,則使用Spring Cloud,由於它繼承自Boot one)將其全部依賴版本提取出來<properties/>
。所以,您一般只需更改屬性值便可。Maven中的示例:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <spring.version>4.2.4.BUILD-SNAPSHOT</spring.version> </properties>
Gradle中的相應功能是ext
屬性,例如
ext['spring.version'] = '4.2.4.BUILD-SNAPSHOT'
Spring Framework有本身的BOM,所以咱們可使用它來管理Spring版本。在Maven中使用自定義父級(不包含<dependencyManagement>
):
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>4.2.4.BUILD-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
注意:此示例實際上不適用於Spring Boot父POM(除非碰巧具備相同的
<spring.version/>
),由於Spring框架版本已由父級修復。要將Spring Boot父級與Spring Framwork快照一塊兒使用,最好使用屬性方法(上面)。
在Gradle中它更簡單(由於沒有父設置衝突版本):
dependencyManagement { imports { mavenBom "org.springframework:spring-framework-bom:4.2.4.BUILD-SNAPSHOT" mavenBom "org.springframework.boot:spring-boot-starter-parent:1.3.0.RELEASE" } }
依賴管理很難,但但願咱們經過概述升級Spring Boot和Spring Cloud的幾個常見場景來緩解這一打擊。根據您是選擇Maven仍是Gradle,有一些略有不一樣的行爲,但至少若是您選擇Gradle並使用Spring Boot插件,則差別會最小化。在一天結束時,Spring項目有不一樣的發佈時間表,因此總會有衝突,但它們一般老是會趨向收斂,因此若是等待的時間足夠長,事情就會平等。像Spring Cloud,Spring Boot和Spring IO Platform這樣的Umbrella項目也有助於消除顛簸:若是你可使用其中一個來管理全部依賴項,那麼事情會變得更加簡單。
Spring指南中的示例應用程序現已所有更新到Spring Boot 1.3,即便這意味着它們依賴於Spring Cloud的里程碑(這僅適用於Zuul代理示例)。許多人再也不須要Spring Cloud了。若是您須要GA版本的Spring Cloud,您須要當即使用Spring Boot 1.2。該組合的樣本能夠從git歷史中解除。