本文参考自:
【尚硅谷SpringBoot零基础教程,面试&加薪必会springboot3】 https://www.bilibili.com/video/BV1Es4y1q7Bf/?p=88&share_source=copy_web&vd_source=d45508e20b7e3eae6233a57ab7104d22
1.前置要求
1.环境要求
环境&工具 | 版本(or later) |
---|---|
SpringBoot | 3.0.5+ |
IDEA | 2021.2.1+ |
Java | 17+ |
Maven | 3.5+ |
Tomcat | 10.0+ |
Servlet | 5.0+ |
GraalVM Community | 22.3+ |
Native Build Tools | 0.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.自动配置包位置变化
-
SpringBoot2.X
META-INF/spring.factories
-
SpringBoot3.X
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
2.jakata api迁移
1.SpringBoot2.X
2.SpringBoot3.X
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规范方式返回错误数据
原理
-
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(); } }
-
处理以下异常。如果系统出现以下异常,会被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访问
原因:主要是因为该请求异常被 HttpRequestMethodNotSupportedException拦截了
4.新特性–函数式接口
SpringMVC 5.2 以后 允许我们使用函数式的方式,定义Web的请求处理流程。
函数式接口
Web请求处理的方式:
- @Controller + @RequestMapping:耦合式 (路由、业务耦合)
- 函数式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 即使编译:程序边 编译,边运行
JIT AOT 优点 1.具备实时调整能力
2.生成最优机器指令
3.根据代码运行情况优化内存占用1.速度快,优化了运行时编译时间和内存消耗
2.程序初期就能达最高性能
3.加快程序启动速度缺点 1.运行期边编译速度慢
2.初始编译不能达到最高性能1.运行期边编译速度慢
2.初始编译不能达到最高性能语言
-
编译型语言:需要编译器 C C++
-
解释型语言:需要解释器 Python、js、PHP
-
半编译半解释型语言:既有编译器有有解释器 JAVA
GraalVM
GraalVM是一个高性能的JDK,旨在加速用Java和其他JVM语言编写的应用程序的执行,同时还提供JavaScript、Python和许多其他流行语言的运行时。
GraalVM提供了两种运行Java应用程序的方式:
-
- 在HotSpot JVM上使用Graal即时(JIT)编译器
-
- 作为预先编译(AOT)的本机可执行文件运行(本地镜像)。
GraalVM的多语言能力使得在单个应用程序中混合多种编程语言成为可能,同时消除了外部语言调用的成本。
具体示例:7、AOT (yuque.com)
-
-
-
-
还没有评论,来说两句吧...