【SpringBoot】SpringBoot 3.x与SpringBoot2.x的对比

目录

Java 版本要求

  • Spring Boot 3.x 要求至少使用 Java 17,这是最低版本要求。
  • 同时,Spring Boot 3.x 也已经通过了 Java 19 的测试,确保了更好的兼容性和性能。
  • 这意味着开发者需要使用 Java 17 或更高版本来运行和开发基于 Spring Boot 3.x 的应用程序。

Spring Framework 版本

  • Spring Boot 3.x 基于最新的 Spring Framework 6 构建,提供了更好的性能和功能。
  • 这是对之前 Spring Boot 2.x 使用的 Spring Framework 5.x 的一个重大升级。

GraalVM 支持和原生镜像

Spring Boot 3.x 引入了对 GraalVM 的支持,允许开发者使用 GraalVM 将 Spring 应用程序编译成本地可执行的镜像文件。
这可以显著提升应用程序的启动速度、峰值性能以及减少内存使用
这一特性取代了之前的 Spring Native 项目。

错误信息返回新格式

错误信息返回新格式,使用方式:在配置文件中开启即可

spring:
  mvc:
    problemdetails:
      enabled: true

 
 
  • 1
  • 2
  • 3
  • 4

开启后的区别:对于这些异常

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

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • springboot2.x版本会返回这样的数据

    {
        "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.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:505)\r\n\tat org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1275)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)\r\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974)\r\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011)\r\n\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:563)\r\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\r\n\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:631)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\r\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)\r\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)\r\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166)\r\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)\r\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)\r\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)\r\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)\r\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)\r\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)\r\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)\r\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)\r\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)\r\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\r\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.base/java.lang.Thread.run(Thread.java:833)\r\n",
        "message": "Method 'POST' is not supported.",
        "path": "/list"
    }
    
       
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • springboot3.x开启后返回这样的数据

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

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

函数式编程

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

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

案例:

  • GET /user/1 :获取1号用户
  • GET /users :获取所有用户
  • POST /user :请求体携带JSON,新增一个用户
  • PUT /user/1 :请求体携带JSON,修改1号用户
  • DELETE /user/1 :删除1号用户

自定义配置类

@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {
    private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);
    @Bean
    public RouterFunction<ServerResponse> routerFunction(MyUserHandler userHandler) {
        return route()
                .GET("/{user}", ACCEPT_JSON, userHandler::getUser)
                .GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers)
                .DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser)
                .build();
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

自定义Handler类,函数式编程

@Component
public class MyUserHandler {
<span class="token keyword">public</span> <span class="token class-name">ServerResponse</span> <span class="token function">getUser</span><span class="token punctuation">(</span><span class="token class-name">ServerRequest</span> request<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token keyword">return</span> <span class="token class-name">ServerResponse</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token class-name">ServerResponse</span> <span class="token function">getUserCustomers</span><span class="token punctuation">(</span><span class="token class-name">ServerRequest</span> request<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token keyword">return</span> <span class="token class-name">ServerResponse</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token class-name">ServerResponse</span> <span class="token function">deleteUser</span><span class="token punctuation">(</span><span class="token class-name">ServerRequest</span> request<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token keyword">return</span> <span class="token class-name">ServerResponse</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

响应式编程

案例:响应式编程实现远程调用(RPC)。两种实现方式

  • 第一种webclient。
  • 第二种HTTP Interface,Spring 允许我们通过定义接口的方式,给任意位置发送 http 请求,实现远程调用,可以用来简化 HTTP 远程访问。需要webflux场景才可以

依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

 
 
  • 1
  • 2
  • 3
  • 4

接口

public interface UserService {
    @GetExchange(url = "/user/list")//这里设置需要给哪个地址发送http请求
    String search(@RequestParam("keyword ") String keyword , @RequestHeader("auth") String headerStr);//把keywaord的值当作发http请求的参数q的值
}

 
 
  • 1
  • 2
  • 3
  • 4

测试

    @Test
    void contextLoads() throws InterruptedException {
        //1、创建客户端
        WebClient client = WebClient.builder()
                .baseUrl("http://localhost:9090")
                .codecs(clientCodecConfigurer -> {
                    clientCodecConfigurer
                            .defaultCodecs()
                            .maxInMemorySize(256*1024*1024);
                            //响应数据量太大有可能会超出BufferSize,所以这里设置的大一点
                })
                .build();
        //2、创建工厂
        HttpServiceProxyFactory factory = HttpServiceProxyFactory
                .builder(WebClientAdapter.forClient(client)).build();
        //3、获取代理对象
        UserService userService = factory.createClient(UserService.class);
    <span class="token comment">//4、测试调用</span>
    <span class="token class-name">Mono</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> search <span class="token operator">=</span> userService<span class="token punctuation">.</span><span class="token function">search</span><span class="token punctuation">(</span><span class="token string">"email"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"=========="</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    search<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>str <span class="token operator">-&gt;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">100000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

自动配置包位置变化

SpringBoot3:现在在这里了: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

jakata api迁移

比如servlet的包,在boot3.0引用的是jakata.servlet-api,在之前的比如druid是javax.servlet-api

配置属性兼容性

  • 在 Spring Boot 3.x 中,一些配置属性被重新命名或删除,开发人员需要更新 application.properties 或 application.yml 配置文件。
  • 为了帮助开发者进行升级,Spring Boot 提供了 spring-boot-properties-migrator 模块,该模块可以在启动时分析应用程序的环境并打印诊断结果,同时在运行时为开发者临时迁移属性
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-properties-migrator</artifactId>
            <scope>runtime</scope>
        </dependency>

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

Apache HttpClient 4 的依赖管理

  • Spring Framework 6 中删除了RestTemplate对Apache HttpClient 4 的支持,取而代之的是 Apache HttpClient 5。
  • Spring Boot 3.0 包括 HttpClient 4 和 5 的依赖管理。继续使用 HttpClient 4

HttpClient 5 的依赖

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient5</artifactId>
        <version>5.1</version>
    </dependency>

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
//创建 HttpClient 实例
HttpClient httpClient = HttpClientBuilder.create().build();

//创建 HttpGet 请求
HttpGet httpGet = new HttpGet(“https://www.example.com/”);

//发送请求并获取响应
HttpResponse response = httpClient.execute(httpGet)

//处理响应
//其中,response.getStatusLine().getStatusCode() 可以获取响应状态码,
//EntityUtils.toString(response.getEntity()) 可以获取响应正文。
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity());

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

完整代码

作者:哪吒编程
链接:https://www.zhihu.com/question/575241602/answer/3220075536
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

public class HttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient httpClient = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet(“https://www.example.com/”);
HttpResponse response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("Status code: " + statusCode);
System.out.println("Response body: " + responseBody);
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Servlet 和过滤器注册

  • ServletRegistrationBean如果注册失败,和类FilterRegistrationBean现在将失败,IllegalStateException而不是记录警告。
  • 如果需要旧的行为,应该调用setIgnoreRegistrationFailure(true)你的注册 bean。

Git 提交 ID Maven 插件版本属性

  • 用于覆盖 的版本的属性io.github.git-commit-id:git-commit-id-maven-plugin已更新以与其工件名称保持一致。
  • 为了适应这种变化,请git-commit-id-plugin.version在git-commit-id-maven-plugin.version你的pom.xml。

增强服务连接

  • 引入了新的服务连接概念。此类连接在应用程序中由 bean 表示ConnectionDetails。
  • 这些 bean 提供了必要的细节来建立与删除服务的连接,并且 Spring Boot 的自动配置已更新为使用ConnectionDetailsbean。
  • 当此类 beans 可用时,它们将优先于任何与连接相关的配置属性。与连接本身无关的配置属性,
  • 例如控制连接池大小和行为的属性,仍将被使用。
  • 此低级功能旨在作为其他高级功能的构建块,这些功能通过定义ConnectionDetailsbean 自动配置服务连接。
  • 在没有在其他地方定义适当的 bean 的情况下…ConnectionDetails,Spring Boot 的自动配置已更新为定义自己的基础,由相关配置属性支持。
  • 这允许…ConnectionDetails注入而不必处理没有这样的 bean 可用并且需要回退到基于属性的配置的情况。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值