【问题标题】:Is it possible to extract duplicate code in bean into single method?是否可以将 bean 中的重复代码提取到单个方法中?
【发布时间】:2021-02-21 17:32:55
【问题描述】:

我有这个云网关配置,我想提取和清理所有重复的代码。

    @Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
    return builder.routes()
                  .route("post_route", r -> r.path("/api/wallet/**")
                                             .and().method("POST")
                                             .and().readBody(BankRequestData.class, requestBody -> findWalletInstance(requestBody.externalReference()).equals("localhost:3000")).uri("http://localhost:3000"))
                  .route("post_route", r -> r.path("/api/wallet/**")
                                             .and().method("POST")
                                             .and().readBody(BankRequestData.class, requestBody -> findWalletInstance(requestBody.externalReference()).equals("localhost:3001")).uri("http://localhost:3001"))

                  .build();
}

这有可能吗?我不确定是否可以做到。非常感谢任何建议或建议。提前谢谢!

【问题讨论】:

    标签: java spring kotlin java-8 functional-programming


    【解决方案1】:

    route() 获取 Function<PredicateSpec,Route.AsyncBuilder>,所以你需要一个返回它的方法。

    由于路由是相同的,除了host和post,你需要把它传递给方法。

    private Function<PredicateSpec,Route.AsyncBuilder> walletRoute(String server) {
        return r -> r.path("/api/wallet/**")
                     .and().method("POST")
                     .and().readBody(BankRequestData.class, requestBody ->
                             findWalletInstance(requestBody.externalReference()).equals(server))
                     .uri("http://" + server));
    
    @Bean
    public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
                      .route("post_route", walletRoute("localhost:3000"))
                      .route("post_route", walletRoute("localhost:3001"))
                      .build();
    }
    

    【讨论】:

    • 替代方案可能是将该函数定义为gatewayRoutes() 中的局部函数,或初始化为匿名函数或lambda 的局部变量。那些甚至可以避免在类中添加私有成员,但会使gatewayRoutes() 本身更复杂一些。 (都同样有效;更多的是个人品味。)
    【解决方案2】:

    作为 Andreas 答案的变体,在 Kotlin 中,您还可以将函数定义为 gatewayRoutes() 中的本地函数:

    @Bean
    fun RouteLocator gatewayRoutes(builder: RouteLocatorBuilder): routeLocator {
    
        fun walletRoute(server: String) = { r: PredicateSpec ->
            r.path("/api/wallet/**")
             .and().method("POST")
             .and().readBody(BankRequestData::class.java,
                             { findWalletInstance(it.externalReference()) == server } )
             .uri("http://$server")
        }
    
        return builder.routes()
                      .route("post_route", walletRoute("localhost:3000"))
                      .route("post_route", walletRoute("localhost:3001"))
                      .build()
    }
    

    或者作为初始化为匿名函数的局部变量:

    @Bean
    fun RouteLocator gatewayRoutes(builder: RouteLocatorBuilder): routeLocator {
    
        val walletRoute = fun (server: String) = { r: PredicateSpec ->
            r.path("/api/wallet/**")
             .and().method("POST")
             .and().readBody(BankRequestData::class.java,
                             { findWalletInstance(it.externalReference()) == server } )
             .uri("http://$server")
        }
    
        return builder.routes()
                      .route("post_route", walletRoute("localhost:3000"))
                      .route("post_route", walletRoute("localhost:3001"))
                      .build()
    }
    

    或者到一个 lambda:

    @Bean
    fun RouteLocator gatewayRoutes(builder: RouteLocatorBuilder): routeLocator {
    
        val walletRoute = { server: String -> { r: PredicateSpec ->
                r.path("/api/wallet/**")
                 .and().method("POST")
                 .and().readBody(BankRequestData::class.java,
                                 { findWalletInstance(it.externalReference()) == server } )
                 .uri("http://$server")
            }
        }
    
        return builder.routes()
                      .route("post_route", walletRoute("localhost:3000"))
                      .route("post_route", walletRoute("localhost:3001"))
                      .build()
    }
    

    所有这些选项都可以避免将成员添加到包含类中,您可能会认为它更整洁——尽管这是否证明更复杂的函数体的合理性可能是个人喜好问题!

    (注意:所有这些都未经测试,因为我没有相关的库,所以它可能有错误。请让我知道任何更正。希望它无论如何都能说明这些选项。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 2022-06-14
      • 2020-10-30
      • 2017-07-21
      • 1970-01-01
      • 2023-02-25
      相关资源
      最近更新 更多