DEV Community

Cyrus Tse
Cyrus Tse

Posted on

Spring Boot 4 入門教學 - Part 1 (Spring Boot 4 與 3 的差異)

從零開始建構專業的 Java Web 應用程式


第一章:Spring Boot 4 與 Spring Boot 3 的差異

1.1 前言:為什麼需要了解版本差異

在開始學習 Spring Boot 之前,了解 Spring Boot 4 與 Spring Boot 3 之間的差異至關重要。這不僅是為了選擇正確的版本,更是為了理解 Java 生態系統的演進方向。Spring Boot 3 代表了一個重要的里程碑,它標誌著 Java 企業級開發進入了一個新的時代。許多開發者仍然在使用 Spring Boot 2.x 版本,這些專案最終都需要遷移到新版,而新專案則應該直接從 Spring Boot 3 或 4 開始。

Spring Boot 3 於 2022 年 11 月發布,帶來了革命性的變化。這個版本要求 Java 17 或更高版本,這意味著它完全拥抱了現代 Java 的新特性。對於剛開始學習 Spring Boot 的你來說,直接學習 Spring Boot 4 或至少是 Spring Boot 3.2+ 是最明智的選擇。這些版本不僅提供了更好的性能,還擁有更現代化的 API 設計和更完善的安全機制。

理解版本之間的差異可以幫助你在未來的職業生涯中更好地適應變化。企業級應用通常會在版本穩定後才進行升級,因此你可能會在工作中遇到各種不同版本的 Spring Boot。了解這些差異將使你能夠快速適應任何版本的專案,成為團隊中不可或缺的技術人才。

1.2 Java 版本需求的根本性變化

Spring Boot 3 以及即將到來的 Spring Boot 4 對 Java 版本有嚴格的要求。這是 Spring 框架對現代 Java 特性的拥抱,也是推動整個 Java 生態系統前進的重要舉措。讓我們詳細探討這些變化及其對開發者的影響。

首先,Spring Boot 3.x 要求 Java 17 或更高版本。這意味著如果你仍在使用 Java 8、11 或 13、15,你需要升級你的 JDK。Java 17 是目前、長期支援版本之一,它引入了許多重要的新特性,包括 records、sealed classes、pattern matching for switch expressions 等等。這些特性不僅讓程式碼更加簡潔,還提高了開發效率和類型安全性。

Java 17 帶來的主要新特性值得我們深入了解。Records 是其中最重要的特性之一,它為簡單的資料傳輸對象提供了簡潔的語法。傳統上,我們需要為每個 POJO 撰寫大量的 getter、setter、equals、hashCode 和 toString 方法,而使用 records 這些都可以自動生成。Sealed classes 允許類設計者控制哪些類可以繼承某個類,這在設計 API 時特別有用,可以防止未經授權的子類化。Pattern matching for switch expressions 讓我們可以用更簡潔的方式處理複雜的條件邏輯。

對於 Spring Boot 4,預計會要求 Java 21 或更高版本。Java 21 是最新的 LTS 版本,引入了 virtual threads(專案 Loom)、pattern matching for switch 的完整支援、以及更多的現代化特性。Virtual threads 是 Java 並發程式設計的重大突破,它允許我們創建數以百萬計的輕量級執行緒,這對於構建高並發的 Web 應用程式來說是一個遊戲規則的改變。

升級 Java 版本需要考慮的因素包括:團隊的技能水平、現有專案的相容性、第三方庫的支援情況、以及部署環境的要求。在生產環境中升級 JDK 需要謹慎規劃和充分測試。建議使用 Docker 容器化部署,這樣可以更容易地控制執行環境。

1.3 Jakarta EE 遷移:從 javax 到 jakarta

Spring Boot 3 最大的變化之一是從 Java EE 遷移到 Jakarta EE。這不是簡單的名稱更換,而是整個生態系統的重大重構。讓我們詳細了解這個遷移的背景、過程和影響。

Java EE 曾經是企業級 Java 開發的標準規範。然而,在 2018 年 Eclipse Foundation 接手了這個規範,並將其重新命名為 Jakarta EE。這個決定是為了確保這個規範能夠在開源社區中繼續發展,而不受任何商業公司的控制。遷移過程中,所有的套件名稱都需要從 javax.* 改為 jakarta.*

這個變化影響了幾乎所有的企業級 Java 規範,包括:JPA(Jakarta Persistence)、Servlet(Jakarta Servlet)、JAX-RS(Jakarta RESTful Web Services)、Bean Validation(Jakarta Validation)、以及 CDI(Jakarta Contexts and Dependency Injection)。這意味著如果你有一個使用 Spring Boot 2.x 的專案需要遷移到 Spring Boot 3,你需要更新所有使用這些規範的程式碼。

讓我們看一些具體的遷移範例。首先是 JPA 實體的遷移:

// Spring Boot 2.x (舊版)
package com.example.demo.entity;

import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "用戶名不能為空")
    @Size(min = 3, max = 50)
    @Column(name = "username", nullable = false, unique = true)
    private String username;

    @NotBlank(message = "電子郵件不能為空")
    @Email(message = "請輸入有效的電子郵件格式")
    @Column(name = "email", nullable = false, unique = true)
    private String email;

    @NotBlank(message = "密碼不能為空")
    @Size(min = 8, message = "密碼長度至少需要 8 個字元")
    @Column(name = "password", nullable = false)
    private String password;

    // getters and setters
}

// Spring Boot 3.x/4.x (新版)
package com.example.demo.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank(message = "用戶名不能為空")
    @Size(min = 3, max = 50)
    @Column(name = "username", nullable = false, unique = true)
    private String username;

    @NotBlank(message = "電子郵件不能為空")
    @Email(message = "請輸入有效的電子郵件格式")
    @Column(name = "email", nullable = false, unique = true)
    private String email;

    @NotBlank(message = "密碼不能為空")
    @Size(min = 8, message = "密碼長度至少需要 8 個字元")
    @Column(name = "password", nullable = false)
    private String password;

    // getters and setters
}
Enter fullscreen mode Exit fullscreen mode

如你所見,主要的變化是將所有 javax 開頭的 import 語句替換為 jakarta 開頭。這看起來很簡單,但在大型專案中,這可能涉及到數百甚至數千個檔案的修改。

Servlet 和 Filter 的遷移同樣需要更新套件名稱:

// Spring Boot 2.x (舊版)
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;

// Spring Boot 3.x/4.x (新版)
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpFilter;
Enter fullscreen mode Exit fullscreen mode

Spring Security 的遷移也涉及類似的變化:

// Spring Boot 2.x (舊版)
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

// Spring Boot 3.x/4.x (新版)
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
Enter fullscreen mode Exit fullscreen mode

對於第三方庫,你需要確保它們已經支援 Jakarta EE。主流的庫如 Hibernate、Jackson、Lombok 等都已經提供了支援 Jakarta EE 的版本。在遷移過程中,你可能需要更新這些庫的版本。

1.4 Spring Security 6.x 的重要變化

Spring Security 6.x 帶來了許多重要的改進,包括更現代化的 API 設計、強化的安全預設、以及更好的效能。讓我們詳細了解這些變化。

首先是配置方式的變化。Spring Security 6.x 引入了新的 DSL(領域特定語法)風格配置,這使得安全配置更加聲明式和易讀:

// Spring Security 5.x (舊版配置方式)
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/public/**").permitAll()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic();
    }
}

// Spring Security 6.x (新版配置方式)
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/", true)
                .permitAll()
            )
            .httpBasic(Customizer.withDefaults());

        return http.build();
    }
}
Enter fullscreen mode Exit fullscreen mode

注意幾個重要的變化:WebSecurityConfigurerAdapter 已被棄用,取而代之的是返回 SecurityFilterChain Bean 的方式。authorizeRequests() 變成了 authorizeHttpRequests()antMatchers() 變成了 requestMatchers()。這些變化反映了 Spring Security 向更現代化 API 設計的演進。

另一個重要變化是 CorsFilter 的配置方式也有所改變:

// Spring Security 6.x 新版配置
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .cors(cors -> cors
            .configurationSource(corsConfigurationSource())
        )
        // ... 其他配置

    return http.build();
}

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
    configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
    configuration.setAllowedHeaders(Arrays.asList("*"));
    configuration.setAllowCredentials(true);

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}
Enter fullscreen mode Exit fullscreen mode

Spring Security 6.x 還引入了對 Spring Authorization Server 的更好整合,這是 OAuth 2.1 和 OpenID Connect 1.0 的官方實現。如果你需要實現社群登入或 OAuth2 認證,Spring Authorization Server 是推薦的解決方案。

1.5 Spring Boot 4 的新功能與未來展望

雖然 Spring Boot 4 還在發展中,但根據 Spring 團隊的公告和社區討論,我們可以預見一些重要的新功能和改進。了解這些趨勢可以幫助你為未來的技術升級做好準備。

首先是對 Java 21 的完整支援。Spring Boot 4 預計會要求 Java 21,這意味著你可以使用 virtual threads、pattern matching 的完整改進、以及其他 Java 21 的新特性。Virtual threads(專案 Loom)是 Java 並發程式設計的重大突破,它允許你創建數以百萬計的輕量級執行緒,而不會消耗大量的記憶體。這對於構建高並發的 Web 應用程式來說是一個革命性的改進。

其次是對原生映像(Native Image)的更好支援。Spring Boot 3 已經引入了對 GraalVM 原生映像的支援,而 Spring Boot 4 將進一步改進這個功能。原生的 Spring Boot 應用程式可以在毫秒級啟動,並使用更少的記憶體,這對於雲原生應用程式和 Serverless 部署來說非常有價值。

第三是對更現代化資料庫技術的支援。隨著資料庫技術的不斷發展,Spring Boot 4 可能會引入對新資料庫特性的更好支援,包括對向量資料庫的整合(這對於 AI 應用程式越來越重要)。

1.6 版本遷移實戰指南

如果你已經有使用 Spring Boot 2.x 的專案需要遷移到 Spring Boot 4,以下是完整的遷移步驟和最佳實踐。這個過程需要謹慎規劃和充分測試,以確保遷移的順利進行。

第一步是評估和規劃。在開始遷移之前,你需要:

  1. 盤點專案中使用的所有依賴,確保它們都有支援 Spring Boot 4 的版本
  2. 評估自定義程式碼中使用到的 Java EE API,準備進行 Jakarta EE 遷移
  3. 建立完整的測試套件,確保遷移後功能不受影響
  4. 制定回滾計劃,以防遷移過程中出現嚴重問題

第二步是準備遷移環境。安裝 JDK 21 或更高版本,並確保你的建構工具(Maven 或 Gradle)是最新的版本。

第三步是逐步進行遷移。首先更新 parent POM 或 build.gradle 中的 Spring Boot 版本:

<!-- Maven pom.xml -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version> <!-- 或 4.0.0 -->
    <relativePath/>
</parent>
Enter fullscreen mode Exit fullscreen mode

第四步是更新依賴版本。許多 Spring 生態系統的庫都有針對 Spring Boot 3/4 的特定版本:

<!-- 確保使用正確版本的依賴 -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-bom</artifactId>
    <version>6.2.0</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>
Enter fullscreen mode Exit fullscreen mode

第五步是進行 Jakarta EE 遷移。使用 IDE 的重構功能批量替換 javaxjakarta

第六步是更新 Spring Security 配置。將舊的配置方式遷移到新的 DSL 風格。

第七步是運行測試並修復問題。這個階段可能會發現一些遷移相關的問題,需要逐一修復。

1.7 本教學的版本選擇

本教學將以 Spring Boot 3.2+ 為主要版本,因為這是目前最穩定且被廣泛採用的版本。大部分的內容和程式碼都適用於 Spring Boot 4(當它發布時),只有極少數需要 Java 21 的特性會特別標註。

在學習本教學之前,請確保你已經:

  1. 安裝 JDK 17 或更高版本(推薦 JDK 21)
  2. 安裝 Maven 3.6+ 或 Gradle 8+
  3. 安裝 PostgreSQL 資料庫(本地或遠程)
  4. 準備好一個現代化的 IDE(推薦 IntelliJ IDEA)

Top comments (0)