我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringBoot3.0升级指南

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringBoot3.0升级指南

简介

Spring boot 3.0于2022年11月正式发布了,这次的发布对于我们普通程序员的影响有多少呢?我们是不是需要考虑立马升级到Spring Boot3.0呢?

别急,看完这篇文章再来做决定也不迟。

对JAVA17和JAVA19的支持

相信很多小伙伴到现在还是使用得是JDK8,但是JDK8已经发布很多年了,随着oracle加速JDK版本的发布,现在每半年发布一次,目前最新的JDK版本已经到了19了。其中JDK11和JDK17是LTS版本,也就是说我们常说的稳定版本。

鉴于JDK17带来的很多新特性,Spring boot的最低JDK版本支持已经提升到了JDK17,如果你还在使用JDK8或者JDK11的话,那么首先需要把JDK版本升级到17才能够使用Spring Boot 3.0。

很多小伙伴可能不是很清楚JDK17到底有些什么新的特性或者功能,这里再给大家详细介绍一下。

record

首先是在JDK14的时候引入了record这个关键词,Record是一种轻量级的class,可以看做是数据结构体。和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和普通的类的区别就在于Record多了一个括号括起来的定义的字段。

Record类默认是final的,里面的字段默认是private final的。

要想知道Record到底是怎么工作的,我们可以使用javap来对编译好的class文件反编译,运行javap CustUser,可以得到下面的结果:

警告: 二进制文件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。

并且自动添加了默认带有所有字段的构造函数。各个自动的获取方法,并实现了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) {  }
    public java.lang.String toString() {  }
    public final int hashCode() {  }
    public final boolean equals(java.lang.Object o) {  }
    public java.lang.String firstName() {  }
    public java.lang.String lastName() {  }
    public com.flydean.records.Address address() {  }
    public int age() {  }
}

注意,上面的反编译我们可以看到,record中的所有字段都是final的,只能在初始化的时候设置。并且方法里面也没有提供其他可以改变字段内容的方法。

Text Blocks

Text Blocks是在JDK13中以第一次预览版本引入的。现在在JDK14中是第二次预览版本 JEP 368: Text Blocks。

在我们日常的工作中,有时候需要用到一大段的字符串,这些字符串需要换行,需要排版,需要转义。在一个文本编辑器中,这当然是非常容易的事情。但是在java代码中,就是一个噩梦了。

虽然IDE可以自动帮我们加上换行甚至可以对字符串进行拼接。但在java程序眼中,添加的诸多额外的代码破坏了代码的美感。是任何一个有洁癖的程序员都无法忍受的。

怎么办? Text Blocks就是来解救大家的。

我们先来个直观的例子,然后再分析Text Blocks的特点。

还是举HTML的例子,如果我们想要打印出带缩减,有格式的html,传统方法可以这样做:

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>
              """;

是不是清爽很多,想要立即给文本块点个赞。

别慌点赞,我们还有更多的东西要讨论。

可能有人又有问题了,文本块好用是好用,你这输出结果中,字段前面的空格都去哪了了呀?

这里就要介绍这个概念了:英文名字叫Indentation,中文我把它翻译为编排。

再看一下上面的代码,这一次我们把代码前面的空格以点来表示:

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

Indentation的规则就是以最下面的“”“为界,对每一行都移除相同数量的空格。

上面的代码输出:

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

上面的例子,最下面的”“”刚好在最左边的位置,如果把“”“向右移动4个空格会发生什么呢?

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

输出结果:

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

我们看到输出结果是不变的,这样我们又得到一条结论:如果”“”向右移动,则以text block中最左的那一行记录为准。

如果我们把“”“向左移动四位,就会发现最终的输出结果每行前面都有四个空格。

这个功能是和String添加的新的String::stripIndent()对应的。

Switch Expressions

switch的新特性可是源远流长,早在JDK 12就以预览功能被引入了,最终在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;
        }
    }

上面的例子中,我们想要匹配所有的星期,然后打印出相应的结果。写了很多个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("这天没发见人!");
        }
    }

传统方式我们需要定义一个局部变量,并在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("这天没发见人!");
        };
    }

是不是非常简单。

注意,这里需要一个default操作,否则会报编译错误。因为可能存在未遍历的值。

上面的switch返回值的情况,如果case后面的表达式比较复杂,那么就需要使用大括号来围起来。这种情况我们需要使用到yield来返回要返回的值。

    @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属性。

接下来我们要对两种动物进行管理,传入一个动物,判断一下这个动物是不是上面两种动物之一,按照传统的办法,我们应该这样做:

    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确认成功,我们还需要将对象进行转换,才能调用相应对象中的方法。

有了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的模式匹配,就不需要二次转换了。直接使用就可以了。并且模式匹配的对象还被限定了作用域范围,会更加安全。

Sealed Classes and Interfaces

在Java中,类层次结构通过继承实现代码的重用,父类的方法可以被许多子类继承。

但是,类层次结构的目的并不总是重用代码。有时,其目的是对域中存在的各种可能性进行建模,例如图形库支持的形状类型或金融应用程序支持的贷款类型。

当以这种方式使用类层次结构时,我们可能需要限制子类集从而来简化建模。

因为我们引入了sealed class或interfaces,这些class或者interfaces只允许被指定的类或者interface进行扩展和实现。

举个例子:

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技术,将spring boot的应用编译成为native的image,从而大大提升系统的运行效率。

比如,我们可以这样添加一个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中默认提供了对Micrometer 1.10的支持,spring boot会自动帮你配置一个ObservationRegistry的实例。

Micrometer可以用来收集应用程序各项指标数据,从而实现对应用程序的各种监控。

其他的一些改动

当然,除了上面的主要的变化之外,Spring boot3还提供了其他的一些小的调整,大家感兴趣的话可以亲自升级到spring boot3尝试一下。

以上就是Spring Boot 3.0升级指南的详细内容,更多关于Spring Boot 3.0升级的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringBoot3.0升级指南

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringBoot3.0升级指南

这篇文章主要为大家介绍了SpringBoot3.0升级指南,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-07

PHP5.3服务器升级指南

PHP5.3服务器升级指南随着技术的不断发展,PHP5.3版本已经逐渐过时,而许多网站和应用程序仍在使用这个版本。为了保证网站的安全性和性能,升级到最新的PHP版本是非常重要的。本篇文章将为您提供PHP5.3服务器升级的指南,并提供具体的
PHP5.3服务器升级指南
2024-03-11

Python pip升级指南:从初级到高级

从入门到精通:Python升级pip的完整教程简介:Python是一种广泛使用的编程语言,而pip是Python的包管理工具。随着Python的版本升级,有时我们需要升级pip以保持与最新的包兼容。本文将提供一个完整的教程,引导读者从入门
Python pip升级指南:从初级到高级
2024-01-18

pip升级pip3的快速方法指南

使用python时经常使用到pip命令,可以方便安装python的各种第三方库这篇文章主要给大家介绍了关于pip升级pip3的快速方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2022-12-10

Linux下Ruby开发环境升级指南

在Linux下升级Ruby开发环境,可以遵循以下步骤:首先,确保系统已更新到最新版本。在终端中运行以下命令:sudo apt-get updatesudo apt-get upgrade安装依赖项。在终端中运行以下命令:sudo apt-
Linux下Ruby开发环境升级指南
2024-09-10

升级numpy版本:详细易学的指南

如何升级numpy版本:简单易懂的教程,需要具体代码示例引言:NumPy是一个重要的Python库,用于科学计算。它提供了一个强大的多维数组对象和一系列与之相关的函数,可用于进行高效的数值运算。随着新版本的发布,不断有更新的特性和Bug修
升级numpy版本:详细易学的指南
2024-02-26

腾讯云服务器带宽升级指南

1.了解腾讯云服务器带宽腾讯云服务器带宽是指服务器与互联网之间的网络传输速度。在使用腾讯云服务器时,如果你的网站或应用程序需要更高的网络传输速度,你可以考虑升级服务器的带宽。2.检查当前带宽配置在升级带宽之前,你需要先了解当前服务器的带宽配置。你可以登录腾讯云控制台,在服务器实例的管理页面查看当前带宽配置信息。3.选择适合的带宽升级方案腾讯云提供了多种带宽升级方案,你可以根据自己的需求选择适合的方案。以...
2023-10-27

阿里云服务器版本升级指南

简介:本文将介绍如何在阿里云服务器上进行版本升级,包括备份数据、安装新版本、配置和测试等步骤。详细说明:1.备份数据在进行版本升级之前,我们需要首先备份服务器上的数据。这样可以确保我们的数据不会因为升级过程中出现问题而丢失。1.1使用命令行备份数据我们可以使用命令行工具来备份数据。例如,可以使用tar命令将整个服务器打
阿里云服务器版本升级指南
2023-12-28

Conda使用指南:轻松升级Python版本

Conda使用指南:轻松升级Python版本,需要具体代码示例引言:在Python的开发过程中,我们经常需要升级Python版本来获取新的功能或修复已知的Bug。然而,手动升级Python版本可能会很麻烦,特别是当我们的项目和依赖包相对复
Conda使用指南:轻松升级Python版本
2024-02-22

numpy版本选择指南:为什么要升级?

随着数据科学、机器学习和深度学习等领域的快速发展,Python成为了数据分析和建模的主流语言。在Python中,NumPy(Numerical Python的简称)是一个很重要的库,因为它提供了一组高效的多维数组对象,也是许多其他库如pan
numpy版本选择指南:为什么要升级?
2024-01-19

腾讯云服务器流量包升级指南

1.了解腾讯云服务器流量包腾讯云服务器流量包是一种预付费的网络流量套餐,可以用于腾讯云服务器的出网流量消耗。流量包的购买可以帮助用户降低服务器出网流量的费用,并提供更灵活的流量管理。2.流量包升级的条件在购买腾讯云服务器流量包后,如果你的业务需求发生变化,需要更多的流量,你可以考虑升级流量包。以下是流量包升级的条件:流
腾讯云服务器流量包升级指南
2023-10-28

使用pip升级Python版本的简易指南

一步步教你使用pip升级Python版本,需要具体代码示例导语:Python是一种功能强大的编程语言,常用于开发应用程序和网站。随着Python不断的发展和更新,升级Python版本变得非常重要。本文将教你如何使用pip升级Python版
使用pip升级Python版本的简易指南
2024-02-02

提升开发环境稳定性的pip工具升级指南

pip工具升级攻略,让你的开发环境更稳定,需要具体代码示例在开发中,我们经常使用Python的pip工具来管理各种第三方库和模块。然而,随着时间的推移,pip本身也会有一些更新和改进。为了确保我们的开发环境能够保持稳定并享受最新的功能,定
提升开发环境稳定性的pip工具升级指南
2024-01-16

简便指南:如何升级Python的pip工具

解决常见问题:Python升级pip的实用指南导言:Python是一种流行的高级编程语言,拥有强大的生态系统和广泛的第三方库。而pip是Python的默认包管理工具,用于安装和管理Python包。然而,随着时间的推移,pip的版本可能会变
简便指南:如何升级Python的pip工具
2024-01-18

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录