SpringBoot3新特性

本篇文章参考尚硅谷springboot3课程: https://www.bilibili.com/video/BV1Es4y1q7Bf?p=94&vd_source=d6deb2b69988de2ae72087817e5143d7
原版笔记:
https://www.yuque.com/leifengyang/springboot3/xy9gqc2ezocvz4wn

1.自动配置包位置变化

现在指定自动配置类放在了下面这个AutoConfiguration.imports文件里面:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
springboot2是放在:
META-INF/spring.factories

2.Java EE API 迁移到 Jakarta EE变体

Spring Boot 3已经将所有Java EE API迁移到其等效的Jakarta EE变体,对于大多数用户来说,这意味着需要将任何javax导入替换为jakarta。例如:javax.servlet.Filter 将被替换为 jakarta.servlet.Filter.

3.新特性 - ProblemDetails、 函数式Web

ProblemDetails: 定义新的错误信息返回格式
遵循RFC 7807: https://www.rfc-editor.org/rfc/rfc7807

problemdetails默认是关闭的,可以在application.properties里面打开:
spring.mvc.problemdetails.enabled=true

原理:
WebMvcAutoConfiguration 里面定义了–> ProblemDetailsErrorHandlingConfiguration里面又返回了 --> ProblemDetailsExceptionHandler

@Configuration(proxyBeanMethods = false)
//配置过一个属性 spring.mvc.problemdetails.enabled=true, 才生效
@ConditionalOnProperty(prefix = "spring.mvc.problemdetails", name = "enabled", havingValue = "true")
static class ProblemDetailsErrorHandlingConfiguration {

    @Bean
    @ConditionalOnMissingBean(ResponseEntityExceptionHandler.class)
    ProblemDetailsExceptionHandler problemDetailsExceptionHandler() {
        return new ProblemDetailsExceptionHandler();
    }

}

1)ProblemDetailsExceptionHandler 是一个 @ControllerAdvice集中处理系统异常
2)它会处理以下异常。如果系统出现以下异常,会被SpringBoot支持以 RFC 7807规范方式返回错误数据

@ExceptionHandler({
        HttpRequestMethodNotSupportedException.class, //请求方式不支持
        HttpMediaTypeNotSupportedException.class,
        HttpMediaTypeNotAcceptableException.class,
        MissingPathVariableException.class,
        MissingServletRequestParameterException.class,
        MissingServletRequestPartException.class,
        ServletRequestBindingException.class,
        MethodArgumentNotValidException.class,
        NoHandlerFoundException.class,
        AsyncRequestTimeoutException.class,
        ErrorResponseException.class,
        ConversionNotSupportedException.class,
        TypeMismatchException.class,
        HttpMessageNotReadableException.class,
        HttpMessageNotWritableException.class,
        BindException.class
    })

例子: 出现Method Not Allowed 异常:
1)不开启Problemdetails的时候,默认响应错误的json。状态码 405

{
    "timestamp": "2023-04-18T11:13:05.515+00:00",
    "status": 405,
    "error": "Method Not Allowed",
    "trace": "org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' is not supported\r\n\tat org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:265)\r\n\tat org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:441)\r\n\tat org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:382)\r\n\tat org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:126)\r\n\tat org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:68)\r\n\tat org.springframework.web.servlet.handler.",
    "message": "Method 'POST' is not supported.",
    "path": "/list"
}

2)开启ProblemDetails返回, 使用新的MediaType
返回的Content-Type是application/problem+json,而且可以自己扩展返回的数据

{
    "type": "about:blank",
    "title": "Method Not Allowed",
    "status": 405,
    "detail": "Method 'POST' is not supported.",
    "instance": "/list"
}

函数式Web:
SpringMVC 5.2 以后 允许我们使用函数式的方式,定义Web的请求处理流程。
Web请求处理的方式:
1.以前使用@Controller + @RequestMapping:耦合式 (路由、业务耦合)
2.现在可以使用函数式Web:分离式(路由、业务分离)

使用函数式Web的步骤:
1.实现配置类给容器中放RouterFunctions bean
2.每个业务准备一个自己的Handler


/**
 * 场景:User RESTful - CRUD
 * ● GET /user/1  获取1号用户
 * ● GET /users   获取所有用户
 * ● POST /user  请求体携带JSON,新增一个用户
 * ● PUT /user/1 请求体携带JSON,修改1号用户
 * ● DELETE /user/1 删除1号用户
 */
@Configuration
public class WebFunctionConfig {

    /**
     * 函数式Web步骤:
     * 1、给容器中放一个Bean:类型是 RouterFunction<ServerResponse>,集中所有路由信息
     * 2、每个业务准备一个自己的Handler
     *
     *
     * 核心四大对象
     * 1、RouterFunction: 定义路由信息。发什么请求,谁来处理
     * 2、RequestPredicate:定义请求规则:请求谓语。请求方式(GET、POST)、请求参数
     * 3、ServerRequest:  封装请求完整数据
     * 4、ServerResponse: 封装响应完整数据
     */
    @Bean
    public RouterFunction<ServerResponse> userRoute(UserBizHandler userBizHandler/*这个会被自动注入进来*/){

        return RouterFunctions.route() //开始定义路由信息
                .GET("/user/{id}", RequestPredicates.accept(MediaType.ALL), userBizHandler::getUser)
                .GET("/users", userBizHandler::getUsers)
                .POST("/user", RequestPredicates.accept(MediaType.APPLICATION_JSON), userBizHandler::saveUser)
                .PUT("/user/{id}", RequestPredicates.accept(MediaType.APPLICATION_JSON), userBizHandler::updateUser)
                .DELETE("/user/{id}", userBizHandler::deleteUser)
                .build();
    }

实现Handler:

/**
 * @author lfy
 * @Description 专门处理User有关的业务
 * @create 2023-04-18 21:55
 */
@Slf4j
@Service
public class UserBizHandler {

    /**
     * 查询指定id的用户
     * @param request
     * @return
     */
    public ServerResponse getUser(ServerRequest request) throws Exception{
        String id = request.pathVariable("id");
        log.info("查询 【{}】 用户信息,数据库正在检索",id);
        //业务处理
        Person person = new Person(1L,"哈哈","aa@qq.com",18,"admin");
        //构造响应
        return ServerResponse
                .ok()
                .body(person);
    }

    /**
     * 获取所有用户
     * @param request
     * @return
     * @throws Exception
     */
    public ServerResponse getUsers(ServerRequest request) throws Exception{
        log.info("查询所有用户信息完成");
        //业务处理
        List<Person> list = Arrays.asList(new Person(1L, "哈哈", "aa@qq.com", 18, "admin"),
                new Person(2L, "哈哈2", "aa2@qq.com", 12, "admin2"));

        //构造响应
        return ServerResponse
                .ok()
                .body(list); //凡是body中的对象,就是以前@ResponseBody原理。利用HttpMessageConverter 写出为json
    }


    /**
     * 保存用户
     * @param request
     * @return
     */
    public ServerResponse saveUser(ServerRequest request) throws ServletException, IOException {
        //提取请求体
        Person body = request.body(Person.class);
        log.info("保存用户信息:{}",body);
        return ServerResponse.ok().build();
    }

    /**
     * 更新用户
     * @param request
     * @return
     */
    public ServerResponse updateUser(ServerRequest request) throws ServletException, IOException {
        Person body = request.body(Person.class);
        log.info("保存用户信息更新: {}",body);
        return ServerResponse.ok().build();
    }

    /**
     * 删除用户
     * @param request
     * @return
     */
    public ServerResponse deleteUser(ServerRequest request) {
        String id = request.pathVariable("id");
        log.info("删除【{}】用户信息",id);
        return ServerResponse.ok().build();
    }
}

4. GraalVM 与 AOT - 将应用编译成可执行文件,飞速运行

====
Complier 与 Interpreter对比
AOT 与 JIT 对比

====
jvm执行java代码流程: jvm里面会判断一段代码是解释执行还是编译执行,如果是编译执行,就编译成机器码并且放到缓存里面,下次用到的时候,直接取;如果是解释执行,就直接解释执行,并且统计解释执行的次数,当次数达到某个阈值的时候,就触发编译,将机器猫放在缓存中
在这里插入图片描述
更详细的图:
方法执行的时候,判断是否已经有了编译好的机器码,如果是,直接从缓存中取出来执行;如果不是,进行热点探测,统计热点代码执行次数,是否超过阈值(这个阈值可以通过compileThreshold设置),
没有超过就解释执行,超过了就进行编译,编译的时候可以设置是否同步编译,如果是同步编译就是先编译好了再执行,非同步编译就是先解释执行完这块代码,然后提交一个编译请求,最后将编译好的机器码放在缓存中
在这里插入图片描述

====
(了解)JVM编译器: C1和C2

(了解)分层编译: Java 7开始引入了分层编译(Tiered Compiler)的概念
总的来说,C1的编译速度更快,C2的编译质量更高,分层编译的不同编译路径,也就是JVM根据当前服务的运行情况来寻找当前服务的最佳平衡点的一个过程。从JDK 8开始,JVM默认开启分层编译。

====
存在的问题:
1.java应用如果用jar,解释执行,热点代码才编译成机器码;初始启动速度慢,初始处理请求数量少。
2.大型云平台,要求每一种应用都必须秒级启动。每个应用都要求效率高。
希望的效果:
1.java应用也能提前被编译成机器码,随时急速启动,一启动就急速运行,最高性能
2.编译成机器码的好处:
1)另外的服务器还需要安装Java环境
2)编译成机器码的,可以在这个平台 Windows X64 直接运行。

====
原生镜像概念:native-image(就是编译成机器码、本地镜像)
1.最终的目标: 把应用打包成能适配本机平台的可执行文件(机器码、本地镜像)

GraalVM
https://www.graalvm.org/
GraalVM是一个高性能的JDK,旨在加速用Java和其他JVM语言编写的应用程序的执行,同时还提供JavaScript、Python和许多其他流行语言的运行时
GraalVM提供了两种运行Java应用程序的方式:
1.在HotSpot JVM上使用Graal即时(JIT)编译器 --> 和C2编译器类似,具有C2编译器的功能,常用于代替C2,一般不用,常见的jvm实现里面的C2已经很好了
2.作为预先编译(AOT)的本机可执行文件运行(本地镜像)。 --> 将程序编译成本机可执行文件
GraalVM的多语言能力使得在单个应用程序中混合多种编程语言成为可能,同时消除了外部语言调用的成本。

GraalVM基于HotSpot,替换了里面的编译器,不仅支持java系列的语言,还想要支持其它的语言,比如js,python等
在这里插入图片描述

====
跨平台提供原生镜像原理
GraalVM提供native-image工具,native-image工具使用不同平台上的编译工具,将你的应用编译成可执行文件(比如windows的.exe),然后这些可执行文件就能够在相同平台的不同机器上跑了
在这里插入图片描述
详细步骤参考雷老师的笔记

native-image可以本地安装然后编译jar包到可执行文件,springBoot也集成了,既然本地能够将应用编译成可执行文件了,为什么springBoot还要额外支持呢?
1.动态能力损失: 运行时才能确定的代码
并不是所有的Java代码都能支持本地打包,例如反射的代码(反射动态获取构造器,反射创建对象,反射调用一些方法),需要做一些额外处理,告诉graalvm反射会用到哪些方法、构造器
SpringBoot做了这部分: 它提供了一些注解:提前告知 graalvm 反射会用到哪些方法、构造器
2.配置文件损失 --> 配置文件时放在jar包内的,在编译成可执行文件的时候,配置文件不能被编译放在最后的可执行文件中
SpringBoot做了这部分: 额外处理(配置中心):提前告知 graalvm 配置文件怎么处理

不是所有的代码都能打包编译: 二进制里面不能包含的,不能动态的都得提前处理 --> SpringBoot都做好了

/**
 * 打包成本地镜像:
 *
 * 1、打成jar包:  注意修改 jar包内的 MANIFEST.MF 文件,指定Main-Class的全类名
 *        - java -jar xxx.jar 就可以执行。
 *        - 切换机器,安装java环境。默认解释执行,启动速度慢,运行速度慢
 * 2、打成本地镜像(可执行文件):
 *        - native-image -cp  你的jar包/路径  你的主类  -o 输出的文件名
 *        - native-image -cp boot3-15-aot-common-1.0-SNAPSHOT.jar com.atguigu.MainApplication -o Demo
 *
 * 并不是所有的Java代码都能支持本地打包;
 * SpringBoot保证Spring应用的所有程序都能在AOT的时候提前告知graalvm怎么处理?
 *
 *   - 动态能力损失:反射的代码:(动态获取构造器,反射创建对象,反射调用一些方法);
 *     解决方案:额外处理(SpringBoot 提供了一些注解):提前告知 graalvm 反射会用到哪些方法、构造器
 *   - 配置文件损失:
 *     解决方案:额外处理(配置中心):提前告知 graalvm 配置文件怎么处理
 *   - 【好消息:新版GraalVM可以自动进行预处理,不用我们手动进行补偿性的额外处理。】
 *   二进制里面不能包含的,不能动态的都得提前处理;
 *
 *   不是所有框架都适配了 AOT特性;Spring全系列栈适配OK
 *
 *  application.properties
 *  a(){
 *      //ssjsj  bcde();
 *      //提前处理
 *  }
 */

详细步骤参考雷老师的笔记

两条命令:
1、运行aot提前处理命令:mvn springboot:process-aot --> IDEA meavn插件里面也有
2、运行native打包:mvn -Pnative native:build --> IDEA meavn插件里面也有

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/149826.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity中Shader矩阵的乘法

文章目录 前言一、矩阵乘以标量二、矩阵和矩阵相乘1、第一个矩阵的列数必须 与 第二个矩阵的行数相等&#xff0c;否则无法相乘&#xff01;2、相乘的结果矩阵&#xff0c;行数由第一个矩阵的行数决定&#xff0c;列数由第二个矩阵的列数决定&#xff01; 三、单位矩阵四、矩阵…

计算机毕业设计 基于Vue的米家商城系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

身份认证系统迁移至浪潮信息KOS5.8过程记录

身份认证系统迁移至浪潮信息KOS5.8过程记录 目录 身份认证系统迁移至浪潮信息KOS5.8过程记录项目背景简介环境介绍 实施01.迁移前准备02.迁移登录浪潮信息KeyarchOS迁移平台 03.操作总结本次操作过程使用X2Keyarch时发现的技术亮点&#xff1a; 项目背景 CentOS 停更危机 2020 …

SQLite3 数据库学习(三):SQLite C API 接口详解

参考引用 SQLite 权威指南&#xff08;第二版&#xff09;SQLite3 入门 1. 接口基本使用 SQLite C API 接口在线文档 1.1 打开数据库文件 返回值 成功返回 0 &#xff08;SQLITE_OK&#xff09;&#xff0c;失败返回 1 &#xff08;SQLITE_ERROR&#xff09; 参数 const cha…

前端js,reduce归并操作图解

// 数组reduce方法// arr.reduce(function(上一次值, 当前值){}, 初始值)const arr [1, 5, 8]// 1. 没有初始值 // const total arr.reduce(function (prev, current) {// return prev current// })// console.log(total)// 2. 有初始值// const total arr.reduce(functi…

15:00进去,15:08就出来了,问的问题太变态了。

前不久刚从一家小自研出来&#xff0c;祸不单行&#xff0c;没想到的是在另一家公司也凉了。 到这家公司上班&#xff0c;每天加班是常态&#xff0c;但看在钱的面子上倒是还能忍受&#xff0c;毕竟给加班费&#xff0c;没想到前段时间突然出了通知&#xff0c;不仅加班费没了…

JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)

目录 1.自定义类加载器2.线程上下文类加载器3.OSGi模块化4.JDK9之后的类加载器5.类加载器总结 1.自定义类加载器 ⚫ 一个Tomcat程序中是可以运行多个Web应用的&#xff0c;如果这两个应用中出现了相同限定名的类&#xff0c;比如Servlet类&#xff0c;Tomcat要保证这两个类都能…

msvcp120.dll下载_msvcp120.dll文件丢失解决[dll系统文件修复]

msvcp120.dll是Microsoft Visual C库中的一个重要组件&#xff0c;属于Microsoft Visual C 2005 Redistributable Package。它提供了许多用于执行C程序所需的函数。Visual C是一款流行的集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛应用于游戏、视频和图形处理等领…

【计算机组成原理】绘制出纯整数(1字节)和纯小数的数轴

绘制出用原码、反码、补码表示纯整数(字节) 的数轴&#xff1a; 对于一字节的大小&#xff0c;原码和反码都只能表示255个数字&#xff0c;因为0占了2个符号数。而补码能表示256个数字&#xff0c;因为0和-0的补码是一样的。所以多出来一个符号数1000 0000能够表示-128所以&…

Android 摇一摇功能实现,重力加速度大于15

最近接到需求实现摇一摇需求&#xff0c;不过这个法律限制的很严格&#xff0c;属于敏感地带&#xff0c;实现后又被叫停了。 法律要求&#xff1a; 如果按照规定&#xff0c;操作时间不少于3s就基本没什么跳转了。 实现的话&#xff0c;只考虑了第一条&#xff0c;即&#…

JCJC错别字检测系统安装部署手册

本手册是针对 Ubuntu 服务器环境的安装使用说明。CentOS安装手册&#xff0c;请参考连接&#xff1a; JCJC错别字系统部署-腾讯云开发者社区-腾讯云 。 安装步骤&#xff1a; 第一步&#xff1a;安装 docker 离线方式在Ubuntu 18.04 上安装Docker &#xff0c;参考连接&am…

UniApp中的数据存储与获取指南

目录 介绍 数据存储方案 1. 本地存储 2. 数据库存储 3. 网络存储 实战演练 1. 本地存储实例 2. 数据库存储实例 3. 网络存储实例 注意事项与最佳实践 结语 介绍 在移动应用开发中&#xff0c;数据的存储和获取是至关重要的一部分。UniApp作为一款跨平台应用开发框架…

delete 与 truncate 命令的区别

直接去看原文 原文链接:【SQL】delete 与 truncate 命令的区别_truncate和delete的区别-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- 1. 相同点 二者都能删除表中的数据…

计算属性与watch的区别,fetch与axios在vue中的异步请求,单文本组件使用,使用vite创建vue项目,组件的使用方法

7.计算属性 7-1计算属性-有缓存 模板中的表达式虽然很方便,但是只能做简单的逻辑操作,如果在模版中写太多的js逻辑,会使得模板过于臃肿,不利于维护,因此我们推荐使用计算属性来解决复杂的逻辑 <!DOCTYPE html> <html lang"en"> <head><meta …

炫酷爱心表白

一、代码 <!DOCTYPE html> <!-- saved from url(0051)https://httishere.gitee.io/notion/v4/love-name.html --> <html><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><title>&#x1f4…

11_聚类算法

文章目录 1 聚类1.1 什么是聚类1.2 相似度/距离公式1.3 聚类的思想 2 K-means算法2.1 K-means算法步骤2.2 K-means算法思考2.3 K-means算法优缺点 3 解决K-Means算法对初始簇心比较敏感的问题3.1 二分K-Means算法3.2 K-Means算法3.3 K-Means||算法3.4 Canopy算法3.4.1 Canopy算…

gradle PKIX path building failed

最近编译gradle项目的时候突然出错了,说是could not resolve org.springframework.boot.spring-boot-gradle-plugin:xxx 最后的错误是PKIX path building failed 这个错初一看是https的证书校验错误&#xff0c;然后网上搜了很多解决方案都不行&#xff0c;最后摸索出来是grad…

LTV预测算法从开发到上线,浅谈基于奇点云DataSimba的MLOps实践

今年8月&#xff0c;StartDT旗下GrowingIO分析云产品客户数据平台&#xff08;CDP&#xff09;正式上线了LTV预测标签。通过开箱即用的标签功能&#xff0c;分析师就能一键生成用户价值的预测结果&#xff0c;用于用户运营和价值分析。 LTV预测标签背后是怎样的算法&#xff1…

url找不到404的问题,url被拼接

今天遇到一个测试feign调用的功能&#xff0c;如图所示 先说结论 Controller换成RestController 将日志设置为debug模式 被DispatcherServlet FORWARD了 找到路径 对属性设置断点&#xff0c;看下是哪注进来的 我们再去找encodedPath 此处是undertow的源码&#xff0c;但是und…

systemverilog:interface中的modport用法

使用modport可以将interface中的信号分组并指定方向&#xff0c;方向是从modport连接的模块看过来的。简单示例如下&#xff1a; interface cnt_if (input bit clk);logic rstn;logic load_en;logic [3:0] load;logic [7:0] count;modport TEST (input clk, count,output rst…