新版本JDK和SpringBoot特性

本项目采用JDK17SpringBoot3,在进行项目开发之前,先要了解JDK9-JDK17的新特性和SpringBoot3的新特性

JDK9新特性

jshell交互式工具

JDK9中引入了命令行交互工具jshell,直接可以运行对应Java代码

image-20231119233027637

模块化开发

JDK8及以前将package作为顶级组件,JDK9将模块作为顶级组件

image-20231119234445748

不同模块之间的相互引用问题,可以通过Maven加入依赖的方式引用

JDK9之后,可以通过模块化方式引用

  1. 使用module-info.java来申明一个模块,一个模块只能有一个该文件,且该文件在顶层包同目录
  2. 使用exports来申明可以被外部引用的包,可以有多个exports语句
    • 一个module中能够被外部调用的包都需要在module-info.java中用exports语句申明
      • exports 包名
  3. 使用requires来申明依赖的外部模块,可以有多个requires语句
    • 一个module中需要调用外部模块都需要在module-info.java中用requires语句申明
      • requires 模块名

image-20231119235341393

JDK10新特性

var局部变量推导

使用var基本要求

  • 必须能够推导出实际类型
  • 只能用于局部变量

该特性一般不推荐使用

1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) {
Test1 test1 = new Test1();
var test11 = new Test1();
Test2 test2 = new Test2();
}
}

JDK11新特性

单文件程序

以前运行.java文件需要:

  • javac xxx.java编译得到对应的字节码文件xxx.class
  • java xxx.class运行对应java程序

新特性只需:java xxx.java即可运行

1
2
3
4
5
6
7
package com.test2;

public class Test2 {
public static void main(String[] args) {
System.out.println("JDK11 new property,Single File Program");
}
}

image-20231120000851511

shebang脚本

  • #!符号叫做shebang,音译为释伴,即解释伴随行
  • #!/bin/bash,以此开头的文件,在执行时会实际调用/bin/bash程序来执行

编写一个非Java文件,文件首行添加shebang语句,在git bash中可以直接执行

image-20231120001817144

1
2
3
4
5
6
#!D:\ProgramTools\java_tools\JDK17\bin\java --source 11
public class Test2 {
public static void main(String[] args) {
System.out.println("JDK11 new property,Single File Program");
}
}

image-20231120001952472

该功能应用场景:用Java语言编写脚本

JDK14新特性

文本块

多行字符串:比如jsonhtmlsql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Test2 {
public static void main(String[] args) {
String json1="{\n" +
" \"name\":\"张飞\",\n" +
" \"age\":27\n" +
" }";
//JDK14新特性:文本块,使得多行字符串定义更美观和可读性
String json2= """
{
"name":"张飞",
"age":27
}
""";

System.out.println(json1);
System.out.println(json2);
}
}

instanceof增强

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {
public static void main(String[] args) {
Object str1 = "we are";
if(str1 instanceof String){
String str2=(String) str1;
System.out.println(str2);
}
//JDK14 instanceof写法增强,将判断和赋值写在了一条语句
if(str1 instanceof String str2){
System.out.println(str2);
}
}
}

空指针提示

可以提示空指针异常具体产生的位置和原因

下面代码在两个不同JDK版本运行结果

1
2
3
4
5
6
7
8
public class Test {
public static void main(String[] args) {
int a=12;
int b=2;
Integer c = null;
System.out.println(a+b+c);
}
}

JDK8版本

image-20231120003842812

JDK14版本

image-20231120003753190

JDK16新特性

record类

  • record是一个final类,初始化后就不能修改属性值
  • 自动生成toString, hashCode, equals方法
  • 一般应用场景:数据类,比如MVC机构中的DTOVOPO

image-20231120004349675

1
2
3
4
package com.test1;

public record UserDto(String name,int age) {
}

image-20231120004534276

JDK17新特性

sealed类

背景:类的继承很难管理,使用sealed可以显示管理

  • 父类如果是sealed类,则其必须至少有一个子类
  • sealed类的子类,必须是finalsealednon-sealed之一

其实实际上没多大用处,只是在如果一个类需要继承其他类,或者一个类需要被其他子类继承,需要强制申明一些关键字,在一定程度上可以避免继承的泛滥

image-20231120231224546

Switch增强

其实没啥用

下面举个例子简单介绍一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Switch {
public static void main(String[] args) {
Object o = 23F;
if(o instanceof String b){
System.out.println("Sting类型,b="+b);
}else if(o instanceof Integer b){
System.out.println("Integer类型,b="+b);
}else if(o instanceof Float b){
System.out.println("Float类型,b="+b);
}else{
System.out.println("其他类型");
}

//switch增强版写法
switch(o){
case String b -> System.out.println("Sting类型,b="+b);
case Integer b -> System.out.println("Integer类型,b="+b);
case Float b -> System.out.println("Float类型,b="+b);
default -> System.out.println("其他类型");
}

}
}

SpringBoot3新特性

AOT与JIT介绍

JIT(Just-in-Time,实时编译)

AOT(Ahead-of-Time,预编译或提前编译)

AOT的优势

  • 启动和运行速度快
    • 传统SpringBoot空项目启动时间大概是2秒,AOT的启动时间大概是100毫秒
  • 打包体积小

AOT的缺点

  • 编译后的程序不支持跨平台
  • 不支持动态功能,比如AOP

AOP在正常项目一般用不到,其主要特点是可以将项目打包成exe的模式,在单机应用中可以直接运行,而无需另外的JDK环境

JIT在高并发场景中的生产问题

生产问题现象:热点应用重启后,出现业务超时,几分钟后恢复正常,所谓的热点应用只有在并发量超过一定阈值之后才会出现

原因:image-20231120233923088

image-20231120233202709

解决办法

  • 预热:初始让程序自动运行热点代码几百次

  • 流量控制:启动时小流量,运行几分钟后再放到正常流量