Java 並不遜色 - 駕馭 JVM

工程 | Brian Dussault | 2015 年 2 月 11 日 | ...

最近 James Ward 撰寫了一篇很棒的部落格文章,「Java 並不遜色 – 只是你用錯方法了」,其中重點說明了企業 Java 開發人員在日常例行工作中建置 Java 應用程式時面臨的眾多挑戰。好消息是,擺脫開發困境比您想像的要容易得多。在過去幾年中,Spring 重新定義了現代 Java 應用程式的建置方式,同時大幅提高了開發速度。在這篇文章中,我將以 James Ward 的部落格文章為背景,說明 Spring 如何幫助開發人員駕馭 JVM(使用 Java),同時解決 James 概述的每個問題。

##即時開發環境設定非常棒 在 James 的部落格中,他斷言「設定開發環境的 10 頁 Wiki 文件很糟糕」。我們都曾在職業生涯中的某個時候建立過這些 Wiki 頁面,並且努力嘗試保持它們的更新。這些 Wiki 文件長期以來一直是新團隊成員感到沮喪的根源,因為它們經常充斥著過時的資訊。好消息是,Spring Boot 的建置支援使自動化此過程變得非常容易。

開始使用現有的應用程式就像複製原始碼儲存庫並執行應用程式一樣簡單。Spring Boot 為 Java 最流行的建置工具 Maven 和 Gradle 提供支援。使用您最喜愛的建置工具執行完全可運作的應用程式非常簡單,只需

Maven 範例

mvn spring-boot:run

Gradle 範例

gradle bootRun

由於 Spring Boot 應用程式是一個獨立的工作負載,它將應用程式碼、伺服器和第三方相依性組合到一個單一的建置和部署單元(可執行 .jar 檔案)中,因此開發團隊可以確保獲得直接、可重複的開發體驗,而與 IDE 無關。開發人員可以從繁瑣的環境設定指示中解放出來,並專注於建置出色的應用程式。在建置之外執行 Spring Boot 應用程式可以透過執行以下命令來完成

java -jar target/my-application-1.0.1-SNAPSHOT.jar

提示:想自己試試看嗎?請依照 spring.io 上的眾多入門指南之一進行操作。對於 Spring Boot 的新手開發人員來說,一個很好的起點是使用 Spring Boot 建置應用程式指南。

##一致的部署環境非常棒 James Ward 強調的下一個挑戰是「為了最大限度地降低將建置從開發環境升級到預備環境再到生產環境時的風險,每個環境之間唯一應該改變的是組態」。手動修改部署成品是災難的根源,最終會導致部署延遲或失敗。環境特定的組態應該外部化,確保在開發環境中測試的相同程式碼是將進入生產環境的「黃金副本」。這是證明您測試的內容就是您部署的內容的唯一符合成本效益的方法!

Spring Boot 使外部化您的組態變得輕而易舉,它使用非常特殊的 PropertySource 順序,該順序旨在允許合理地覆寫值。通常希望在您的專案中為本機開發提供預設組態,但在將程式碼升級到各個環境時覆寫這些值。Spring Boot 透過命令列引數、JNDI 屬性、Java 系統屬性、作業系統環境變數、組態檔案、設定檔驅動的組態變體和更多,為外部化組態提供全面的支援。Spring Boot 對環境變數的支援使遵循十二要素應用程式組態最佳實務(將程式碼與組態嚴格分離)變得輕而易舉。

提示 1:當使用 Cloud Foundry 等雲端平台時,Spring Boot 應用程式可以利用Spring Cloud Connectors自動繫結到 Cloud Foundry 服務,例如資料庫和訊息傳遞系統。這樣做的好處是減少了應用程式需要維護的環境特定組態屬性的數量,從而顯著降低了在跨環境升級程式碼時出錯的風險。

提示 2:想知道為什麼十二要素應用程式很重要嗎?請查看這篇部落格文章:為什麼 12 要素應用程式模式、微服務和 CloudFoundry 很重要

##快速伺服器啟動非常棒 Spring Boot 為輕量級、可嵌入的容器/伺服器提供支援,這些容器/伺服器可以快速啟動。一個簡單的 REST 應用程式可以在短短 3 秒內啟動。截至 Spring Boot 1.2,它支援嵌入式應用程式伺服器,適用於 Tomcat(預設容器)、Jetty 和 Undertow。Spring Boot 不僅為領先的輕量級容器提供支援,而且它還讓開發人員完全掌控這些決策,因為它可以直接更換預設容器。

以下 Gradle 建置組態啟用對完整堆疊 Web 開發的支援,包括對嵌入式 Tomcat 和 spring-webmvc 的支援。

Gradle 範例

...

apply plugin: 'java'

repositories { jcenter() }
dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.2.0.RELEASE")
}

...

正如 James Ward 在他的原始部落格文章中指出的那樣,透過將單體式部署分解為微服務,可以進一步縮短啟動時間。稍後在這篇文章中,將更詳細地討論微服務的主題(請參閱標題為微服務風格架構非常棒的部分)。

受管理的相依性非常棒

現代開發人員需要工具和技術,使他們能夠以最少的阻力快速入門。他們還需要模組化、輕量級和有主見的技術來最佳化生產力。Spring Boot 的目標是解決快速啟動和執行的問題,同時大幅提高開發速度。

正如 James Ward 正確指出的那樣,「如果您的任何程式庫相依性未由建置工具管理,那就糟了」。Spring Boot 不僅支援現代建置技術,還提供稱為 starter POM 的便利相依性描述符,使這種最佳實務成為首要實務。Starter POM 為常見的開發工作負載提供相依性群組,您可以簡單地將它們包含在您的應用程式中。

若要開始使用 Spring Boot,您可以將瀏覽器指向 Spring Initializer - http://start.spring.io。Spring Initializer 提供了一個基於 Web 的介面,允許開發人員選擇應用程式/工作負載和相關的相依性。然後,它將產生一個具有建置支援的 starter 應用程式(支援 Maven POM、Maven 專案、Gradle Config、Gradle 專案)。

Spring Initializer 的螢幕擷取畫面:Spring Initializer

對於喜歡命令列的開發人員,您可以透過發出以下命令來安裝 Spring Boot CLI

curl http://start.spring.io/install.sh | sh

可以使用命令列來初始化新專案,只需發出以下命令即可

spring init --dependencies=web,data-jpa my-project

此初始化(透過 Spring Initializer 或 Boot CLI)的結果是一個完全可運作的應用程式,其中所需的相依性已包含在內並由 Spring Boot 自動組態。

Spring IO Platform(包括 Spring Boot)也提供了由 Spring Boot 的 starter POM 管理的相依性的超集。Spring IO 在 Spring 產品組合中對相依性版本進行了水平調整,並且發佈週期比 Spring Boot 更長,這為企業提供了相依性版本的快照,這些版本經過測試並且已知可以協同工作。Spring IO Platform 發行版不是程式庫的單體式下載,開發人員可以自由選擇他們在應用程式中僅需要的部分。Spring IO 發行版包含 Spring 模組、測試程式庫、記錄框架、資料庫管理、SQL/No-SQL 以及更多內容的版本。Spring IO 發行版非常適合希望以更漸進的節奏使用 Spring IO Platform 相依性的企業。

以下 Gradle 組態示範了如何組態 Spring IO Platform 材料清單並利用 Spring Boot 的 web starter POM


buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'io.spring.gradle:dependency-management-plugin:0.3.0.RELEASE'
    }
}

apply plugin: 'io.spring.dependency-management'

repositories {
    mavenCentral()
}

dependencyManagement {
    imports {
        mavenBom 'io.spring.platform:platform-bom:1.1.0.RELEASE'
    }
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
}

##短開發/驗證週期真的非常棒 大多數現代應用程式都是使用豐富的使用者介面建置的,這些介面與後端服務進行通訊。以這種方式建置應用程式的好處是在 UI 和伺服器端邏輯之間實現了強大的關注點分離。大多數現代 IDE 都提供靜態資源的動態重新載入,允許開發人員在無需重新啟動伺服器的情況下查看變更。

Spring Boot 也支援伺服器端範本技術,例如 Thymeleaf、Freemarker 和 Groovy。Spring Boot 允許動態重新載入這些範本技術,而無需重新啟動伺服器。對於 Thymeleaf,這就像在 application.properties 檔案中設定以下屬性一樣簡單

spring.thymeleaf.cache: false

在伺服器端,將您的單體式應用程式分解為微服務將縮短 Spring Boot 應用程式的啟動時間(由於它使用了輕量級嵌入式容器,因此啟動時間已經非常快)。此外,Spring Boot 還為測試公用程式的自動組態提供了支援。啟用 Boot 的測試自動組態就像包含 spring-boot-starter-test starter POM 一樣輕鬆。這啟用了 Spring Test、JUnit、Hamcrest 和 Mockito 相依性,使將測試驅動開發 (TDD) 納入日常工作流程變得容易。TDD 使開發人員能夠立即收到有關程式碼變更的回饋。

最後,JRebel 為類別重新載入提供全面的支援,並支援 80 多個 Java 框架(包括 Spring)。請查看網路研討會Spring Boot 和 JRebel 6,其中 Josh Long 和 Adam Koblentz 提供了更多詳細資訊。

##微服務風格架構非常棒 James 的「單體式發佈很糟糕」的說法對於大型或複雜的分散式系統來說是正確的。大多數開發人員希望以更迭代的方式(敏捷)工作並更頻繁地發佈。微服務風格架構已越來越受歡迎,成為應對單體式應用程式挑戰的一種方法。對於微服務的新手來說,Martin Fowler 在他的部落格中對這種架構風格進行了很好的描述。

在建置分散式應用程式(包括微服務風格應用程式)時,會出現許多常見的系統模式。Spring Cloud 透過提供現成的服務來解決最常見的挑戰,從而簡化了這些模式的採用。Spring Cloud 實作了組態管理、服務探索、斷路器、智慧路由、微型 Proxy 和控制匯流排等模式。Spring Boot 使將這些功能整合到您的應用程式中變得異常簡單。

例如,Spring Cloud Netflix 專案使使用 Netflix 的 Eureka 建立服務探索服務變得像這樣簡單


@SpringBootApplication 
@EnableEurekaServer

public class Application {
    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

用戶端應用程式可以透過簡單地使用 @EnableEurekaClient 註冊為 Eureka 用戶端


@SpringBootApplication
@EnableEurekaClient
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello world";
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

提示 1:Spring Cloud 為眾多分散式處理模式提供支援。為了幫助您入門,請查看 Spring Cloud 範例 github 儲存庫。Dave Syer 和 Spencer Gibb 的 Spring Cloud、Spring Boot 和 Netflix OSS SpringOne 會議是另一個了解和學習如何運作微服務風格架構的好方法。

提示 2:如果您正在尋找建置超媒體風格的 REST API,請務必查看入門指南使用 REST 存取 JPA 資料Spring Data REST 將幫助您加速服務開發。Spring Data REST 同時支援 SQL 和 No-SQL 儲存庫。

擁有允許您快速編寫微服務程式碼的技術只是成功的一半。開發人員經常因將程式碼放入生產平台時的眾多延遲而感到困擾。一些最常見的障礙包括手動部署、測試、基礎架構佈建和服務佈建。持續交付旨在自動化將程式碼升級到生產環境的過程,同時最大限度地降低風險。這允許組織對應用程式進行增量變更,使部署成為業務決策,而不是資源決策。這本身就是一個很大的主題,但我強烈推薦 Matt Stine 的演講 使用 Spring 和 Cloud Foundry 開發適用於 PaaS 的微服務,該演講出色地突出了將敏捷工程實務與 Pivotal Cloud Foundry 自動化相結合的好處。

##無狀態應用程式非常棒 James 指出,「黏性會話和伺服器狀態通常是損害效能和彈性的最佳方法之一。會話狀態(在傳統 Servlet 意義上)使持續交付和水平擴展變得非常困難」。

從您的應用程式中移除會話狀態可以大幅簡化運作,允許重新部署、終止或擴展應用程式,而無需擔心遺失會話資料。維護狀態有有效的用例,例如共用驗證狀態,但此狀態應持久儲存在應用程式外部(通常在高效能儲存庫中,例如 NoSQL、分散式快取,甚至記憶體內資料儲存區)。外部化應用程式狀態不一定是一項繁瑣的工作,Spring Session 提供了常見的基礎架構,使此過程變得簡單且可移植。Spring Session 提供

  • 以與供應商無關的方式支援叢集
  • RESTful API 支援 - 支援標頭中的會話 ID
  • 用於判斷會話 ID 的可插拔策略
  • 當 WebSocket 處於活動狀態時,支援保持 HttpSession 存活
  • 支援 Redis 和 Hazelcast 後端會話儲存區
  • 能夠管理單一瀏覽器中的多個同時會話(即類似於多個 Google 帳戶支援)

使用 Redis 組態 Spring Session 非常簡單,只需

@EnableRedisHttpSession
public class Config {

    @Bean
    public JedisConnectionFactory connectionFactory() {
        return new JedisConnectionFactory();
    }
}

提示:Spring Session 1.0 最近已正式發佈 (GA),因此請試用 Spring Session 範例,以查看其所有實際運作情況。Dave Syer 最近發表了一篇名為 API 閘道模式:Angular JS 和 Spring Security 第 IV 部分 的部落格文章,其中詳細介紹了共用驗證狀態用例。強烈推薦閱讀!

最後,如果您使用 Pivotal Cloud Foundry,Cloud Foundry Java 建置套件提供了另一個選項,可以透過自動組態的 CF 會話狀態儲存區輕鬆地外部化狀態。請查看此部落格文章以取得詳細資訊。

##非阻塞應用程式非常棒 許多現代應用程式架構可以從請求的非同步和非阻塞處理中受益匪淺。這些用例可以包括組合多個後端服務呼叫和 WebSocket 風格的應用程式。

Project Reactor(Spring IO Platform 的一部分)為建置這些非同步、非阻塞應用程式提供了基礎。在 2.0 版中,Reactor 將提供 Reactive Streams 規範的完整實作,這開啟了與其他 Reactive Streams 實作的整合,例如 Akka StreamsRatpackRxJava

以下程式碼片段展示了如何使用 Reactive Streams API 建立串流、向其新增業務邏輯,然後將資料發佈到其中

// by default Streams use the Disruptor RingBufferDispatcher
Broadcaster<String> helloStream = Streams.broadcast(env);

helloStream.map(s -> "Hello " + s + "!")
           .consume(log::info);

helloStream.onNext("World");

提示:Spring Boot 為 Project Reactor 提供支援,使其易於入門。請依照使用 Reactor 建立非同步、事件驅動應用程式入門指南進行操作,以建立您的第一個反應式應用程式。另請務必查看網路研討會 使用 Reactor 進行非同步、非阻塞微服務

Spring Framework 4 引入了對 WebSocket 風格、事件驅動應用程式的支援。這種務實的方法遠遠超出了 JSR-356,並且包括使用 SockJS 的用戶端後備選項、對訊息傳遞子協定 (STOMP) 的支援、安全性 (Spring Security 4)、訊息代理支援、基於 Reactor 的 MessageChannel 用於訊息傳遞、用戶端斷線處理以及熟悉的 Spring 程式設計模型。

提示:Spring Boot 使組態 WebSocket 應用程式變得輕而易舉。請依照使用 WebSocket 建置互動式 Web 應用程式指南開始使用。

Java 語言非常棒

Spring Boot 為開發人員提供使用 Java 6、7、8 以及 Groovy 建置下一代應用程式的選項。在 James 的文章中,他表示「Java 語言有點糟糕」,但隨著 Java 8 的發佈,Java 已向前發展,並提供了許多強大的語言功能,這些功能將提高生產力。一些很棒的 Java 8 功能包括對 Lambda 運算式、串流和並行性改進的支援。Spring Boot 使開始使用 Java 8 或 Groovy 變得毫不費力。

提示:如果您不熟悉 Java 8 的功能,我強烈推薦 Venkat Subramaniam 的書 Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions 和他的 SpringOne2GX 2014 演講

##結論 建置現代 Java 應用程式不必是一種痛苦的體驗。Spring Boot 消除了建置應用程式的繁文縟節,使 Java 再次變得有趣。Spring 消除了應用程式每一層的樣板程式碼 - 業務邏輯(Spring Foundation 專案)、組態和執行階段 (Spring Boot) 以及分散式系統模式 (Spring Cloud)。入門的最佳方法是深入研究 Spring 的入門指南並部署到 Pivotal Web Services(Cloud Foundry 的公開託管版本,可免費使用 60 天)。

取得 Spring 電子報

保持與 Spring 電子報的聯繫

訂閱

領先一步

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將舉行的活動

查看 Spring 社群中所有即將舉行的活動。

查看全部