一文弄懂 SpringBoot3 新特性

一文弄懂 SpringBoot3 新特性

码农世界 2024-05-27 后端 65 次浏览 0个评论

本文参考自:

【尚硅谷SpringBoot零基础教程,面试&加薪必会springboot3】 https://www.bilibili.com/video/BV1Es4y1q7Bf/?p=88&share_source=copy_web&vd_source=d45508e20b7e3eae6233a57ab7104d22

1.前置要求

1.环境要求

环境&工具版本(or later)
SpringBoot3.0.5+
IDEA2021.2.1+
Java17+
Maven3.5+
Tomcat10.0+
Servlet5.0+
GraalVM Community22.3+
Native Build Tools0.9.19+

2.SpringBoot是什么

SpringBoot 帮我们简单、快速地创建一个独立的、生产级别的 Spring 应用(说明:SpringBoot底层是Spring)

大多数 SpringBoot 应用只需要编写少量配置即可快速整合 Spring 平台以及第三方技术

特性

  • 快速创建独立Spring应用,无需像SSM一样,导一堆的包,写一堆配置
  • 直接嵌入Servlet容器,如Tomcat、Jetty等,无需部署 war 包,直接打包成jar包,java -jar执行
  • 重点: 提供了可选的场景启动器starter,简化应用整合,Spring Boot会自动管理这些依赖项的版本,确保它们之间的兼容性。
  • 重点: 按需自动配置Spring以及第三方库,约定大于配置,每个场景都有默认配置,需要自定义只需要在配置文件修改即可。
  • 提供生产级特性,如监控指标、健康检查、外部化配置等

    总结:简化开发,简化配置,简化整合,简化部署,简化监控,简化运维。

    2.改变&新特性

    1.自动配置包位置变化

    1. SpringBoot2.X

      META-INF/spring.factories

      一文弄懂 SpringBoot3 新特性

    2. SpringBoot3.X

      META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

      一文弄懂 SpringBoot3 新特性

    2.jakata api迁移

    1.SpringBoot2.X

    一文弄懂 SpringBoot3 新特性

    2.SpringBoot3.X

    一文弄懂 SpringBoot3 新特性

    3.SpringBoot3使用druid有问题,因为它引用的是旧的包

    该问题已经得到官方解决:

    解决SpringBoot3整合Druid的兼容性问题_druid-spring-boot-3-starter-CSDN博客

    方法:将依赖有原先的依赖

    
       com.alibaba
       druid-spring-boot-starter
       1.2.18
    
    

    改为

    
        com.alibaba
        druid-spring-boot-3-starter
        1.2.20
    
    

    3.新特性–Problemdetails

    SpringBoot3提供的一个新规范,当发生某些异常时,以RFC 7807规范方式返回错误数据

    原理

    1. ProblemDetailsErrorHandlingConfiguration 是一个 @ControllerAdvice集中处理系统异常

      @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();
          }
      }
      
    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
      		})
      

    效果

    spring.mvc.problemdetails.enabled=true
    

    开启后 会使用新的MediaType

    Content-Type: application/problem+json+ 额外扩展返回
    

    并且返回信息也会变化

    例:写一个GET接口,用POST访问

    一文弄懂 SpringBoot3 新特性

    原因:主要是因为该请求异常被 HttpRequestMethodNotSupportedException拦截了

    4.新特性–函数式接口

    SpringMVC 5.2 以后 允许我们使用函数式的方式,定义Web的请求处理流程。

    函数式接口

    Web请求处理的方式:

    1. @Controller + @RequestMapping:耦合式 (路由、业务耦合)
    2. 函数式Web:分离式(路由、业务分离)

    核心类

    • RouterFunction - 定义路由信息。发什么请求,谁来处理
    • RequestPredicate - 定义请求规则:请求谓语。请求方式(GET、POST)、请求参数
    • ServerRequest - 封装请求完整数据
    • ServerResponse - 封装响应完整数据

      示例

      package com.atguigu.web.config;
      import com.atguigu.web.bean.Person;
      import com.atguigu.web.biz.UserBizHandler;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.http.MediaType;
      import org.springframework.web.servlet.function.RequestPredicates;
      import org.springframework.web.servlet.function.RouterFunction;
      import org.springframework.web.servlet.function.RouterFunctions;
      import org.springframework.web.servlet.function.ServerResponse;
      /**
       * @author lfy
       * @Description
       * @create 2023-04-18 21:46
       */
      /**
       * 场景: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,集中所有路由信息
           * 2、每个业务准备一个自己的Handler
           *
           *
           * 核心四大对象
           * 1、RouterFunction: 定义路由信息。发什么请求,谁来处理
           * 2、RequestPredicate:定义请求规则:请求谓语。请求方式(GET、POST)、请求参数
           * 3、ServerRequest:  封装请求完整数据
           * 4、ServerResponse: 封装响应完整数据
           */
          @Bean
          public RouterFunction 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();
          }
      }
      
      package com.atguigu.web.biz;
      import com.atguigu.web.bean.Person;
      import jakarta.servlet.ServletException;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.stereotype.Component;
      import org.springframework.stereotype.Service;
      import org.springframework.web.servlet.function.ServerRequest;
      import org.springframework.web.servlet.function.ServerResponse;
      import java.io.IOException;
      import java.util.Arrays;
      import java.util.List;
      /**
       * @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 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();
          }
      }
      

      5.支持GraalVM与AOT

      • AOT 提前编译:程序执行前,全部先编译成机器码

      • JIT 即使编译:程序边 编译,边运行

        JITAOT
        优点1.具备实时调整能力
        2.生成最优机器指令
        3.根据代码运行情况优化内存占用
        1.速度快,优化了运行时编译时间和内存消耗
        2.程序初期就能达最高性能
        3.加快程序启动速度
        缺点1.运行期边编译速度慢
        2.初始编译不能达到最高性能
        1.运行期边编译速度慢
        2.初始编译不能达到最高性能

        语言

        • 编译型语言:需要编译器 C C++

        • 解释型语言:需要解释器 Python、js、PHP

        • 半编译半解释型语言:既有编译器有有解释器 JAVA

          一文弄懂 SpringBoot3 新特性

          GraalVM

          GraalVM是一个高性能的JDK,旨在加速用Java和其他JVM语言编写的应用程序的执行,同时还提供JavaScript、Python和许多其他流行语言的运行时。

          GraalVM提供了两种运行Java应用程序的方式:

            1. 在HotSpot JVM上使用Graal即时(JIT)编译器
            1. 作为预先编译(AOT)的本机可执行文件运行(本地镜像)。

            GraalVM的多语言能力使得在单个应用程序中混合多种编程语言成为可能,同时消除了外部语言调用的成本。

          具体示例:7、AOT (yuque.com)

转载请注明来自码农世界,本文标题:《一文弄懂 SpringBoot3 新特性》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,65人围观)参与讨论

还没有评论,来说两句吧...

Top