【问题标题】:Webflux nested router on root always returns 404根上的 Webflux 嵌套路由器始终返回 404
【发布时间】:2019-07-03 11:11:40
【问题描述】:

我有一个RouterFunction,里面有嵌套的路由,除了一条路由之外的所有东西都在做我认为他们应该做的事情。
但是,当我尝试在嵌套路由中调用其中一个根路由时,我总是得到 404。这只发生在该特定路由上,当我将它从根更改为“/foo”时,它开始工作。

代码:

    public RouterFunction<ServerResponse> productRouter(final ProductHandler handler) {
        return nest(path(apiPath + BASE_PATH),
                route(POST("/").and(contentType(MediaType.APPLICATION_JSON)), handler::handleCreateProduct)
                        .andRoute(GET("/{id}"), handler::handleGetProductById)
                        .andRoute(PUT("/").and(contentType(MediaType.APPLICATION_JSON)), handler::handleUpdateProduct)
                        .andRoute(GET("/"), handler::handleGetAllProducts)
                        .andNest(path("/category"),
                                route(POST("/").and(contentType(MediaType.APPLICATION_JSON)), handler::handleCreateProductCategory)
                                        .andRoute(GET("/{id}"), handler::handleGetProductCategoryById)
                                        .andRoute(GET("/"), handler::handleGetAllProductCategories)
                                        .andRoute(GET("/search/{name}"), handler::handleGetProductCategoriesByName)
                        ))
                .andNest(path("/brand"),
                        route(POST("/").and(contentType(MediaType.APPLICATION_JSON)), handler::handleCreateProductBrand)
                                .andRoute(GET("/"), handler::handleGetAllProductBrands)
                                .andRoute(GET("/{id}"), handler::handleGetProductBrandById));
    }

不正确的路线如下:

.andRoute(GET("/"), handler::handleGetAllProductCategories)

奇怪的是在根路径和品牌路径下我做完全相同的事情并且这些路径有效。

感谢您的帮助

【问题讨论】:

  • 您能提供更多信息吗? apiPathBASE_PATH 的值是什么?
  • apiPath = "/api/v1" 和 BASE_PATH = "/products"
  • 所以我发现“/api/v1/products/category/”返回 404,但是当我使用“/api/v1/products/category//”时它返回列表我我期待,我已经看到这是 github 上某个地方的错误,但似乎无法再次找到它,我正在使用 spring-boot 2.1.2 和 webflux 5.1.4

标签: spring spring-boot spring-webflux


【解决方案1】:

我没有设法在 Spring Boot 2.1.2.RELEASE 上重现此问题,使用以下内容:

@Configuration
public class RouterConfig {

    @Bean
    public RouterFunction<ServerResponse> productRouter() {
        return nest(path("/test"),
                route(GET("/"), serverRequest -> ServerResponse.ok().syncBody("TEST"))
                        .andNest(path("/other"),
                                route(GET("/{id}"), serverRequest -> ServerResponse.ok().syncBody("ID"))
                                .andRoute(GET("/"), serverRequest -> ServerResponse.ok().syncBody("OTHER"))));
    }
}

我得到了结果:

➜  ~ http :8080/test
HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/plain;charset=UTF-8

TEST

➜  ~ http :8080/test/
HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/plain;charset=UTF-8

TEST

➜  ~ http :8080/test/other
HTTP/1.1 200 OK
Content-Length: 5
Content-Type: text/plain;charset=UTF-8

OTHER

➜  ~ http :8080/test/other/
HTTP/1.1 200 OK
Content-Length: 5
Content-Type: text/plain;charset=UTF-8

OTHER

➜  ~ http :8080/test/other/something
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: text/plain;charset=UTF-8

ID

如果您设法在示例应用程序中重现此问题,请在Spring Framework issue tracker 上创建一个问题,因为我没有找到现有的问题。请在那里提供一个示例项目,我们可以克隆并运行它以重现问题。

【讨论】:

  • 我找到了问题所在,这是因为“/test”路径上有一个 pathVariable(在您的示例中),而 webflux 正在考虑“其他”路径作为路径变量,我'将在 Spring 问题跟踪器中创建一个问题,但感谢帮助我调查它!
  • 那么这可能不是问题 - 请记住,路由器功能是关于第一个匹配的路由。因此,与注释模型不同,排序很重要。如果您创建问题,请提供我们可以运行的简化示例。谢谢!
  • 感谢 Brian 的帮助,在你的帮助下我已经解决了
【解决方案2】:

现在 Weblux 中有一个关于映射根元素的开放错误:https://github.com/spring-projects/spring-boot/issues/9785

您应该使用重定向或不使用“/”映射。

【讨论】:

  • 这是一个不同的问题;您指出的问题是关于支持 Spring Boot 中的欢迎页面支持。在这种情况下,OP 正在尝试匹配嵌套路径下的路由。
  • 是的,你是对的。我最近遇到它,我认为它也适用于基础根映射
【解决方案3】:

感谢 Brian Clozel 的评论,我才弄明白了

keep in mind that router functions are about the first route that matches.

因此,考虑到这一点,我按以下方式重组了我的 RouterFunction:

public RouterFunction<ServerResponse> productRouter(final ProductHandler handler) {

        return nest(path(apiPath + BASE_PATH),
                route(method(HttpMethod.POST).and(accept(MediaType.MULTIPART_FORM_DATA)), handler::handleCreateProduct)
                        .andNest(path("/category"),
                                route(GET("/{id}"), handler::handleGetProductCategoryById)
                                        .andRoute(method(HttpMethod.POST).and(contentType(MediaType.APPLICATION_JSON)), handler::handleCreateProductCategory)
                                        .andRoute(GET("/search/{name}"), handler::handleGetProductCategoriesByName)
                                        .andRoute(method(HttpMethod.GET), handler::handleGetAllProductCategories))
                        .andNest(path("/brand"),
                                route(method(HttpMethod.POST).and(contentType(MediaType.APPLICATION_JSON)), handler::handleCreateProductBrand)
                                        .andRoute(GET("/{id}"), handler::handleGetProductBrandById)
                                        .andRoute(method(HttpMethod.GET), handler::handleGetAllProductBrands))
                        .andRoute(GET("/{id}/pdf"), handler::handlaProductDetailsPdf)
                        .andRoute(GET("/{id}"), handler::handleGetProductById)
                        .andRoute(method(HttpMethod.PUT).and(contentType(MediaType.APPLICATION_JSON)), handler::handleUpdateProduct)
                        .andRoute(method(HttpMethod.GET), handler::handleGetAllProducts));
}

我已将 /category 和 /brand 路径在链中移动到高于根路径的位置,并且它按预期工作。

再次感谢 Brian 的帮助!

【讨论】:

    猜你喜欢
    • 2015-08-24
    • 2019-07-20
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多