大数跨境
0
0

我给Spring提交一个Bug,已在最新版修复!请这样修复!

我给Spring提交一个Bug,已在最新版修复!请这样修复! Spring全家桶实战案例
2024-08-15
0
导读:我给Spring提交一个Bug,已在最新版修复!请这样修复!

环境:Spring6.1.11



1. Bug介绍

这是一个关于Spring 函数式接口的问题。

Spring Web MVC 包含 WebMvc.fn,是一种轻量级的函数式编程模型,其中函数用于路由和处理请求,并且设计了不可变性的契约。它是基于注解(@RequestMapping)的编程模型的替代方案,但在其他方面与 DispatcherServlet 相同。有关函数式接口详细,查看下面的文章:

你以为只有Controller一种接口定义方式?详解Web函数式接口

接下来将详细介绍bug的复现的过程

1.1 路由接口定义

环境采用SpringBoot3.2.8该版本对应的Spring版本是6.1.11。

路由定义

@BeanRouterFunction<ServerResponse> userRouter(UserHandler handler) {  return route()      .path("/routers/users", builder -> builder        .GET("/{id}", accept(MediaType.TEXT_HTML), handler::findById))      .build() ;}

路由处理函数

@Componentpublic class UserHandler {  public ServerResponse findById(ServerRequest request) {    User user = new User(        Long.valueOf(request.pathVariable("id")),         request.param("name").orElse(null)      ) ;    return ServerResponse.ok().body(user) ;  }}

请求测试

没有问题

1.2 bug复现

接下来,我们只需要在配置文件中进行如下的servlet path配置问题就会出现了

spring:  mvc:    servlet:      path: /api

该配置会给DispatcherServlet访问路径添加/api前缀。

如上配置后,当你再次访问上面的/routers/users/*接口时,将会出现如下错误

说明:该错误的出现是只针对的上面那种嵌套路由,其它普通的路由则不会有这样的问题。

2. 给Spring官方提交issue

问题提出后作者给出了回复

意思是确认问题,同时你可以通过下面的配置进行临时代替

server:  servlet:    context-path: /api

通过配置上下文的方式确实可以解决。

最终该问题在spring6.1.12版本中修复,当前我使用的最新springboot3.2.8最高支持的spring是6.1.11。所以我们可以通过如下方式进行替换为最新的Spring版本

<properties>  <spring-framework.version>6.1.12</spring-framework.version></properties>

在maven项目中的pom.xml中配置如上的属性即可替换当前springboot依赖的Spring版本。

错误原因

这种嵌套路由在进行RequestPredicate路径匹配时,构建请求路径时,不知道怎么想的直接抛出异常(整个过程就不细说了,看下最终构建上下文时的代码):

Spring6.1.11版本中(包括之前)

public abstract class ServletRequestPathUtils {  private static final class ServletRequestPath implements RequestPath {    // 这里的contextPath = /routers/users/6666 (这时候并没有包括我们的/api前缀)    public RequestPath modifyContextPath(String contextPath) {      // 毫不犹豫,直接抛出异常      throw new UnsupportedOperationException();    }  }}

Spring6.1.12版本中修复

private static final class ServletRequestPath implements RequestPath {  public RequestPath modifyContextPath(String contextPath) {    // 将当前配置的servletPathPrefix拼接到当前的请求上下文路径    // 也就是将/api拼接到 当前请求的/routers/users/6666中    return new ServletRequestPath(this.pathElements.withContextPath(contextPath));  }}

项目中如果你也遇到这样的问题,你可以按照上面的方式进行修复,要么就是不要使用这种嵌套路由无非就是多写两行代码也没什么关系。

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

放弃ThreadLocal!TTL真香

SpringBoot错误使用拦截器导致系统奔溃,发生OOM错误

别不信@PathVariable你真不会用

SpringBoot请求参数还可以这样玩?很少有人知道

SpringBoot3优雅停止/重启定时任务

强大!SpringBoot结合STOMP简化数据实时通信

总结7种JVM出现OOM时的原因及解决方案

强大!SpringBoot通过这3个注解监测Controller接口

强大!必须掌握!Spring Security这些技巧你知道吗?

SpringBoot这几个工具类太有用了

必须掌握的SpringBoot开发技能

紧急!Spring Boot安全漏洞

玩转Redis!非常强大的Redisson分布式集合,少写60%代码

SpringBoot3.2开始Controller参数验证@Validated新功能

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读368
粉丝0
内容832