最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot 3.0升級指南

 更新時間:2023年02月07日 09:25:00   作者:程序那些事  
這篇文章主要為大家介紹了Spring Boot 3.0升級指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

簡介

Spring boot 3.0于2022年11月正式發(fā)布了,這次的發(fā)布對于我們普通程序員的影響有多少呢?我們是不是需要考慮立馬升級到Spring Boot3.0呢?

別急,看完這篇文章再來做決定也不遲。

對JAVA17和JAVA19的支持

相信很多小伙伴到現(xiàn)在還是使用得是JDK8,但是JDK8已經(jīng)發(fā)布很多年了,隨著oracle加速JDK版本的發(fā)布,現(xiàn)在每半年發(fā)布一次,目前最新的JDK版本已經(jīng)到了19了。其中JDK11和JDK17是LTS版本,也就是說我們常說的穩(wěn)定版本。

鑒于JDK17帶來的很多新特性,Spring boot的最低JDK版本支持已經(jīng)提升到了JDK17,如果你還在使用JDK8或者JDK11的話,那么首先需要把JDK版本升級到17才能夠使用Spring Boot 3.0。

很多小伙伴可能不是很清楚JDK17到底有些什么新的特性或者功能,這里再給大家詳細(xì)介紹一下。

record

首先是在JDK14的時候引入了record這個關(guān)鍵詞,Record是一種輕量級的class,可以看做是數(shù)據(jù)結(jié)構(gòu)體。和scala中的case有點相似。

舉個自定義User的例子看一下Record是怎么用的:

public record Address(
        String addressName,
        String city
) {
}
public record CustUser(
        String firstName,
        String lastName,
        Address address,
        int age
) {}

上面我們定義了兩個類,CustUser和Address。CustUser中引用了Address。

Record和普通的類的區(qū)別就在于Record多了一個括號括起來的定義的字段。

Record類默認(rèn)是final的,里面的字段默認(rèn)是private final的。

要想知道Record到底是怎么工作的,我們可以使用javap來對編譯好的class文件反編譯,運行javap CustUser,可以得到下面的結(jié)果:

警告: 二進(jìn)制文件CustUser包含com.flydean.records.CustUser
Compiled from "CustUser.java"
public final class com.flydean.records.CustUser extends java.lang.Record {
  public com.flydean.records.CustUser(java.lang.String, java.lang.String, com.flydean.records.Address, int);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public java.lang.String firstName();
  public java.lang.String lastName();
  public com.flydean.records.Address address();
  public int age();
}

上面可以看到final class CustUser繼承自java.lang.Record。

并且自動添加了默認(rèn)帶有所有字段的構(gòu)造函數(shù)。各個自動的獲取方法,并實現(xiàn)了toString,hashCode和equals方法。

天啦,太完美了,我們想要的它居然都有。

如果上面的javap還不是很清楚的話,大家可以借助IDE的反編譯功能,打開CustUser.class文件看一看:

public final class CustUser extends java.lang.Record {
    private final java.lang.String firstName;
    private final java.lang.String lastName;
    private final com.flydean.records.Address address;
    private final int age;
    public CustUser(java.lang.String firstName, java.lang.String lastName, com.flydean.records.Address address, int age) { /* compiled code */ }
    public java.lang.String toString() { /* compiled code */ }
    public final int hashCode() { /* compiled code */ }
    public final boolean equals(java.lang.Object o) { /* compiled code */ }
    public java.lang.String firstName() { /* compiled code */ }
    public java.lang.String lastName() { /* compiled code */ }
    public com.flydean.records.Address address() { /* compiled code */ }
    public int age() { /* compiled code */ }
}

注意,上面的反編譯我們可以看到,record中的所有字段都是final的,只能在初始化的時候設(shè)置。并且方法里面也沒有提供其他可以改變字段內(nèi)容的方法。

Text Blocks

Text Blocks是在JDK13中以第一次預(yù)覽版本引入的?,F(xiàn)在在JDK14中是第二次預(yù)覽版本 JEP 368: Text Blocks。

在我們?nèi)粘5墓ぷ髦校袝r候需要用到一大段的字符串,這些字符串需要換行,需要排版,需要轉(zhuǎn)義。在一個文本編輯器中,這當(dāng)然是非常容易的事情。但是在java代碼中,就是一個噩夢了。

雖然IDE可以自動幫我們加上換行甚至可以對字符串進(jìn)行拼接。但在java程序眼中,添加的諸多額外的代碼破壞了代碼的美感。是任何一個有潔癖的程序員都無法忍受的。

怎么辦? Text Blocks就是來解救大家的。

我們先來個直觀的例子,然后再分析Text Blocks的特點。

還是舉HTML的例子,如果我們想要打印出帶縮減,有格式的html,傳統(tǒng)方法可以這樣做:

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world</p>\n" +
              "    </body>\n" +
              "</html>\n";

上面的代碼看著特別別扭,讓我們看看用文本塊方式怎么做:

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;

是不是清爽很多,想要立即給文本塊點個贊。

別慌點贊,我們還有更多的東西要討論。

可能有人又有問題了,文本塊好用是好用,你這輸出結(jié)果中,字段前面的空格都去哪了了呀?

這里就要介紹這個概念了:英文名字叫Indentation,中文我把它翻譯為編排。

再看一下上面的代碼,這一次我們把代碼前面的空格以點來表示:

String html = """
..............<html>
..............    <body>
..............        <p>Hello, world</p>
..............    </body>
..............</html>
..............""";

Indentation的規(guī)則就是以最下面的“”“為界,對每一行都移除相同數(shù)量的空格。

上面的代碼輸出:

<html>
    <body>
        <p>Hello, world</p>
    </body>
</html>

上面的例子,最下面的”“”剛好在最左邊的位置,如果把“”“向右移動4個空格會發(fā)生什么呢?

String html = """
..............<html>
..............    <body>
..............        <p>Hello, world</p>
..............    </body>
..............</html>
..................""";

輸出結(jié)果:

<html>
    <body>
        <p>Hello, world</p>
    </body>
</html>

我們看到輸出結(jié)果是不變的,這樣我們又得到一條結(jié)論:如果”“”向右移動,則以text block中最左的那一行記錄為準(zhǔn)。

如果我們把“”“向左移動四位,就會發(fā)現(xiàn)最終的輸出結(jié)果每行前面都有四個空格。

這個功能是和String添加的新的String::stripIndent()對應(yīng)的。

Switch Expressions

switch的新特性可是源遠(yuǎn)流長,早在JDK 12就以預(yù)覽功能被引入了,最終在JDK 14成為了正式版本的功能:JEP 361: Switch Expressions (Standard)。

其實Switch新增的功能有兩個,一個就是可以連寫case,一個就是switch可以帶返回值了。

先看一個老版本的例子:

    @Test
    public void useOldSwitch(){
        switch (MONDAY) {
            case MONDAY:
            case FRIDAY:
            case SUNDAY:
                System.out.println(6);
                break;
            case TUESDAY:
                System.out.println(7);
                break;
            case THURSDAY:
            case SATURDAY:
                System.out.println(8);
                break;
            case WEDNESDAY:
                System.out.println(9);
                break;
        }
    }

上面的例子中,我們想要匹配所有的星期,然后打印出相應(yīng)的結(jié)果。寫了很多個case語句,不美觀。

再看一下新版本的例子:

    @Test
    public void useNewSwitch(){
        switch (MONDAY) {
            case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
            case TUESDAY                -> System.out.println(7);
            case THURSDAY, SATURDAY     -> System.out.println(8);
            case WEDNESDAY              -> System.out.println(9);
        }
    }

一個漂亮的連寫,將一切都帶走。

注意這里switch語句沒有返回值,所以并不需要default語句。

考慮一個在switch中賦值的情況:

    @Test
    public void oldSwitchWithReturnValue(){
        int numLetters;
        switch (MONDAY) {
            case MONDAY:
            case FRIDAY:
            case SUNDAY:
                numLetters = 6;
                break;
            case TUESDAY:
                numLetters = 7;
                break;
            case THURSDAY:
            case SATURDAY:
                numLetters = 8;
                break;
            case WEDNESDAY:
                numLetters = 9;
                break;
            default:
                throw new IllegalStateException("這天沒發(fā)見人!");
        }
    }

傳統(tǒng)方式我們需要定義一個局部變量,并在case中給這個局部變量賦值。

我們看下怎么使用新版的switch替換:

    @Test
    public void newSwitchWithReturnValue(){
        int numLetters = switch (MONDAY) {
            case MONDAY, FRIDAY, SUNDAY -> 6;
            case TUESDAY                -> 7;
            case THURSDAY, SATURDAY     -> 8;
            case WEDNESDAY              -> 9;
            default -> throw new IllegalStateException("這天沒發(fā)見人!");
        };
    }

是不是非常簡單。

注意,這里需要一個default操作,否則會報編譯錯誤。因為可能存在未遍歷的值。

上面的switch返回值的情況,如果case后面的表達(dá)式比較復(fù)雜,那么就需要使用大括號來圍起來。這種情況我們需要使用到y(tǒng)ield來返回要返回的值。

    @Test
    public void withYield(){
        int result = switch (MONDAY) {
            case MONDAY: {
                yield 1;
            }
            case TUESDAY: {
                yield 2;
            }
            default: {
                System.out.println("不是MONDAY,也不是TUESDAY!");
                yield 0;
            }
        };
    }

instanceof模式匹配

怎么理解呢?

我們先舉個歷史版本中使用instanceof的例子。

假如我們是動物園的管理員,動物園里面有Girraffe和Hippo兩種動物。

@Data
public class Girraffe {
    private String name;
}
@Data
public class Hippo {
    private String name;
}

為了簡單起見,上面兩種動物我們都之定義一個name屬性。

接下來我們要對兩種動物進(jìn)行管理,傳入一個動物,判斷一下這個動物是不是上面兩種動物之一,按照傳統(tǒng)的辦法,我們應(yīng)該這樣做:

    public void testZooOld(Object animal){
        if(animal instanceof Girraffe){
            Girraffe girraffe = (Girraffe) animal;
            log.info("girraffe name is {}",girraffe.getName());
        }else if(animal instanceof Hippo){
            Hippo hippo = (Hippo) animal;
            log.info("hippo name is {}",hippo.getName());
        }
        throw new IllegalArgumentException("對不起,該動物不是地球上的生物!");
    }

上面的代碼中, 如果instanceof確認(rèn)成功,我們還需要將對象進(jìn)行轉(zhuǎn)換,才能調(diào)用相應(yīng)對象中的方法。

有了JDK 14,一切都變得容易了,我們看下最新的JDK 14的模式匹配怎么做:

    public void testZooNew(Object animal){
        if(animal instanceof Girraffe girraffe){
            log.info("name is {}",girraffe.getName());
        }else if(animal instanceof Hippo hippo){
            log.info("name is {}",hippo.getName());
        }
        throw new IllegalArgumentException("對不起,該動物不是地球上的生物!");
    }

注意instanceof的用法,通過instanceof的模式匹配,就不需要二次轉(zhuǎn)換了。直接使用就可以了。并且模式匹配的對象還被限定了作用域范圍,會更加安全。

Sealed Classes and Interfaces

在Java中,類層次結(jié)構(gòu)通過繼承實現(xiàn)代碼的重用,父類的方法可以被許多子類繼承。

但是,類層次結(jié)構(gòu)的目的并不總是重用代碼。有時,其目的是對域中存在的各種可能性進(jìn)行建模,例如圖形庫支持的形狀類型或金融應(yīng)用程序支持的貸款類型。

當(dāng)以這種方式使用類層次結(jié)構(gòu)時,我們可能需要限制子類集從而來簡化建模。

因為我們引入了sealed class或interfaces,這些class或者interfaces只允許被指定的類或者interface進(jìn)行擴展和實現(xiàn)。

舉個例子:

package com.example.geometry;
public abstract sealed class Shape
    permits Circle, Rectangle, Square {...}

上面的例子中,我們指定了Shape只允許被Circle, Rectangle, Square來繼承。

上面的例子中并沒有指定類的包名,我們可以這樣寫:

package com.example.geometry;
public abstract sealed class Shape 
    permits com.example.polar.Circle,
            com.example.quad.Rectangle,
            com.example.quad.simple.Square {...}

遷移到Jakarta EE

除了下面一些spring依賴包的更新之外:

Spring Framework 6.0.
Spring AMQP 3.0.
Spring Batch 5.0.
Spring Data 2022.0.
Spring GraphQL 1.1.
Spring HATEOAS 2.0.
Spring Integration 6.0.
Spring Kafka 3.0.
Spring LDAP 3.0.
Spring REST Docs 3.0.
Spring Retry 2.0.
Spring Security 6.0 
Spring Session 3.0
Spring WS 4.0.

spring boot3最大的變化就是把Java EE 遷移到了Jakarta EE,也就是說我們需要把 javax.* 替換成為 jakarta.*。

舉個例子HttpServletRequest需要從:

import javax.servlet.http.HttpServletRequest;

替換成為:

import jakarta.servlet.http.HttpServletRequest;

GraalVM Native Image Support

Spring Boot3的一個非常大的功能點就是可以利用Spring的AOT技術(shù),將spring boot的應(yīng)用編譯成為native的image,從而大大提升系統(tǒng)的運行效率。

比如,我們可以這樣添加一個native的build profile:

<profiles>
    <profile>
        <id>native</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.graalvm.buildtools</groupId>
                    <artifactId>native-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>build-native</id>
                            <goals>
                                <goal>compile-no-fork</goal>
                            </goals>
                            <phase>package</phase>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

然后運行下面的命令就可以把spring boot項目打包成native項目了:

mvn clean package -Pnative

對Micrometer的支持

在spring boot3中默認(rèn)提供了對Micrometer 1.10的支持,spring boot會自動幫你配置一個ObservationRegistry的實例。

Micrometer可以用來收集應(yīng)用程序各項指標(biāo)數(shù)據(jù),從而實現(xiàn)對應(yīng)用程序的各種監(jiān)控。

其他的一些改動

當(dāng)然,除了上面的主要的變化之外,Spring boot3還提供了其他的一些小的調(diào)整,大家感興趣的話可以親自升級到spring boot3嘗試一下。

以上就是Spring Boot 3.0升級指南的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot 3.0升級的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在Java編程中使用正則表達(dá)式的基本方法

    在Java編程中使用正則表達(dá)式的基本方法

    這篇文章主要介紹了在Java編程中使用正則表達(dá)式的基本方法,是Java入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-11-11
  • java?ResourceBundle讀取properties文件方式

    java?ResourceBundle讀取properties文件方式

    這篇文章主要介紹了java?ResourceBundle讀取properties文件方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • mybatis執(zhí)行update批量更新時報錯的解決方案

    mybatis執(zhí)行update批量更新時報錯的解決方案

    這篇文章主要介紹了mybatis執(zhí)行update批量更新時報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • idea常用的18個設(shè)置(程序員必不可少)

    idea常用的18個設(shè)置(程序員必不可少)

    這篇文章主要給大家介紹了關(guān)于idea常用的18個設(shè)置,這些對程序員們來說必不可少,idea開發(fā)常用基本且非常實用的配置,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • Java中的重要核心知識點之繼承詳解

    Java中的重要核心知識點之繼承詳解

    繼承是java面向?qū)ο缶幊碳夹g(shù)的一塊基石,因為它允許創(chuàng)建分等級層次的類。繼承就是子類繼承父類的特征和行為,使得子類對象(實例)具有父類的實例域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為
    2021-10-10
  • Java編程思想中關(guān)于并發(fā)的總結(jié)

    Java編程思想中關(guān)于并發(fā)的總結(jié)

    在本文中小編給大家整理的是關(guān)于Java編程思想中關(guān)于并發(fā)的總結(jié)以及相關(guān)實例內(nèi)容,需要的朋友們參考下。
    2019-09-09
  • 淺談一個基礎(chǔ)的SpringBoot項目該包含哪些

    淺談一個基礎(chǔ)的SpringBoot項目該包含哪些

    這篇文章主要介紹了淺談一個基礎(chǔ)的SpringBoot項目該包含哪些,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 使用Java反射獲取方法的全路徑名稱的步驟

    使用Java反射獲取方法的全路徑名稱的步驟

    Java反射是一個強大的特性,它允許程序在運行時查詢和修改類的行為,反射可以用于實現(xiàn)很多高級功能,比如動態(tài)代理、依賴注入等,本文將介紹如何使用Java反射來實現(xiàn)這一功能,需要的朋友可以參考下
    2024-07-07
  • Java中有什么工具可以進(jìn)行代碼反編譯詳解

    Java中有什么工具可以進(jìn)行代碼反編譯詳解

    這篇文章主要介紹了Java中有什么工具可以進(jìn)行代碼反編譯的相關(guān)資,料,包括JD-GUI、CFR、Procyon、Fernflower、Javap、BytecodeViewer、Krakatau和JAD,每種工具都有其特點和適用場景,需要的朋友可以參考下
    2025-03-03
  • Java中鎖的實現(xiàn)和內(nèi)存語義淺析

    Java中鎖的實現(xiàn)和內(nèi)存語義淺析

    這篇文章主要給大家介紹了關(guān)于Java中鎖的實現(xiàn)和內(nèi)存語義的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11

最新評論

双桥区| 广宗县| 武鸣县| 万盛区| 隆昌县| 上栗县| 策勒县| 玛多县| 青州市| 青州市| 新泰市| 改则县| 富宁县| 章丘市| 黎平县| 称多县| 汶川县| 页游| 宁津县| 香格里拉县| 米泉市| 阳山县| 上饶县| 湖南省| 凤阳县| 阆中市| 河间市| 江都市| 镶黄旗| 筠连县| 淮阳县| 措美县| 吴桥县| 唐河县| 榆社县| 海伦市| 修水县| 白银市| 伊春市| 博爱县| 南汇区|