You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring函数式端点返回404问题排查求助

Spring函数式端点返回404问题排查

问题场景

开发同时包含常规端点和函数式端点的Spring应用,常规端点可正常返回结果,但所有函数式端点均返回404。已按照Handler+Router模式实现,相关代码及日志如下:

Handler代码

@Service
public class LorcCardHandler {
    private final LorcCardReactiveRepository lorcCardReactiveRepository;

    @Autowired
    public LorcCardHandler(LorcCardReactiveRepository lorcCardReactiveRepository) {
        this.lorcCardReactiveRepository = lorcCardReactiveRepository;
    }

    public Mono<ServerResponse> getCardProjectionList(ServerRequest request) {
        return ServerResponse.ok().body(lorcCardReactiveRepository.getAllCardsProjection(), CardProjection.class);
    }
}

Router代码

@Configuration
public class LorcRouter {
    private final LorcCardHandler handler;

    public LorcRouter(LorcCardHandler handler) {
        this.handler = handler;
    }

    @Bean
    public RouterFunction<ServerResponse> getCardListByRoute() {
       return route().path("/lorc", builder -> builder.GET(handler::getCardProjectionList)).build();
    }
}

关键日志信息

Bean初始化日志

o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from beaame 'reactiveMongoTemplate' via factory method to beaamed 'mappingMongoConverter'
o.s.d.r.c.s.RepositoryFactorySuppo: Initializing repository instance for com.luizgomendes.lorc.rest.repository.LorcCardReactiveRepository…
o.s.d.r.c.s.RepositoryFactorySuppo: Finished creation of repository instance for com.luizgomendes.lorc.rest.repository.LorcCardReactiveRepository.
o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from beaame 'lorcReactiveService' via constructor to beaamed 'lorcCardReactiveRepository'
o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from beaame 'lorcReactiveController' via constructor to beaamed 'lorcReactiveService'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'lorcRouter'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'lorcCardHandler'
o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from beaame 'lorcCardHandler' via constructor to beaamed 'lorcCardReactiveRepository'
o.s.b.f.s.DefaultListableBeanFactory : Autowiring by type from beaame 'lorcRouter' via constructor to beaamed 'lorcCardHandler'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'globalExceptionHandler'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'getCardListByRoute'

服务调用日志

[Lorcana Rest Services] [nio-8080-exec-1] o.s.web.servlet.DispatcherServle : GET "/lorc", parameters={}
[Lorcana Rest Services] [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
[Lorcana Rest Services] [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandl: Resourcot found
[Lorcana Rest Services] [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.servlet.resource.NoResourceFoundException: No static resource lorc.]
[Lorcana Rest Services] [nio-8080-exec-1] o.s.web.servlet.DispatcherServle : Completed 404 NOT_FOUND

问题分析

从服务调用日志可见,请求被映射到静态资源处理器,而非函数式路由。核心原因:

  • 日志中出现o.s.web.servlet.DispatcherServle(Servlet栈的DispatcherServlet),而非WebFlux的org.springframework.web.reactive.DispatcherHandler,说明当前应用运行在Servlet栈环境中,WebFlux的RouterFunction不会被Servlet容器处理。
  • 通常是因为项目同时引入了spring-boot-starter-web(Spring MVC)和spring-boot-starter-webflux依赖,Spring Boot默认优先启用Servlet栈,导致WebFlux路由失效。

解决方案

  1. 清理依赖
    检查项目的pom.xml(Maven)或build.gradle(Gradle),移除spring-boot-starter-web依赖,仅保留spring-boot-starter-webflux。

    Maven示例:

    <!-- 移除该依赖 -->
    <!-- <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency> -->
    
    <!-- 保留WebFlux依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
  2. 验证RouterFunction定义
    确保路由路径配置正确,可调整Router代码写法,显式指定路径匹配规则:

    @Bean
    public RouterFunction<ServerResponse> getCardListByRoute() {
        // 直接匹配GET /lorc
        return route(GET("/lorc"), handler::getCardProjectionList);
    }
    

    或使用path分组的写法(需明确子路径):

    @Bean
    public RouterFunction<ServerResponse> getCardListByRoute() {
        return route().path("/lorc", builder -> 
            builder.GET("", handler::getCardProjectionList) // 子路径为空,对应/lorc
        ).build();
    }
    
  3. 重启应用验证
    调整依赖和代码后,重启应用,再次请求/lorc,检查日志是否出现DispatcherHandler相关的路由匹配日志,确认请求是否正确映射到函数式端点。

内容的提问来源于stack exchange,提问作者Luiz Gustavo Mendes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:42:33