【问题标题】:Access Play Framework route parameters during action composition在动作组合期间访问 Play Framework 路由参数
【发布时间】:2017-09-19 20:16:05
【问题描述】:

我想在我的 Play 应用程序中应用多个路由的操作。这些路由对一个产品执行操作,一个产品可以有不同的版本。我希望我的 API 能够正常工作,以便用户可以明确指定一个版本(通过查询参数),如果他们没有指定一个版本,我们将从数据库中为他们查找最新版本并对其进行操作。所以这个动作需要能够查找到一个产品的最新版本,但是我们需要知道是哪个产品被请求。在路由的控制器中,这是显而易见的。 Play 以路由参数作为参数调用路由控制器:

@RequireProductVersion()
public CompletionStage<Result> getProduct(String productId) {
    ...
}

但在我们的操作中,我们只有这个 Play 内部 Context 对象可以使用。我的操作如下所示:

public class RequireProductVersion extends Action<RequireProductVersion> {
    @Override
    public CompletionStage<Result> call(Http.Context ctx) {
        final String version = ctx.request().getQueryString("version");
        // if an explicit "version" parameter was specified, verify it and use it
        if (version != null) {
            ...
        } else {
            // look up the latest version for this product
            final String productId = ctx.request.????getParameter("productId");
            return lookupLatestProductVersion(productId).thenCompose( ... );
        }
    }
}

虽然我在该操作中有一些额外的有效性检查。有时我会立即从那里返回一个错误。因此,我们可以通过将查询字符串参数“version”添加到所有路由并在我的每个路由控制器中添加六行代码来替换此操作组合解决方案:

@RequireProductVersion()
public CompletionStage<Result> getProduct(String productId, @Nullable String productVersion) {
    final int productVersion;
    try {
        productVersion = Utils.getProductVersion(productId, productVersion);
    } catch (ProductVersionException e) {
        return CompletableFuture.completedFuture(e.getAppropriateResult());
    }
    ...
}

但我认为,这个用例正是动作组合的用途。似乎缺少路由参数。实际上,在 Action call() 方法中公开的 Context 对象中有很多东西。标题在那里,查询参数在那里,甚至被命中的确切路径也在那里!即使不是这样,框架已经解析了路由并确定了路由参数的值。这一定是真的,因为如果不是,那么它怎么知道要调用哪个动作?但是,我们似乎完全无法使用这些解析的参数。我们可以自己从路径中再次解析它们。但是我们为什么要这样做呢?我们将解析路径两次。为什么框架不公开这些值?

我发现一篇有趣的文章,为了解决类似的问题,提出了一种将 url 参数放入查询字符串参数映射的 hack。 https://alots.wordpress.com/2014/05/01/accessing-url-parameters-as-get-parameters-in-play/ 但是在我看来,这种方法基本上也是对路径的双重解析,尽管我可能会误解它,因为我对 Scala 不是很熟悉。如果是这样,我还不如破解逻辑来重新解析我的 Action 中的路径。

【问题讨论】:

    标签: java playframework


    【解决方案1】:

    好的,所以这个问题在 Scala 中是可以解决的。由于 Play Java 如何使用注释进行动作组合(以及对于正文解析器,这是我遇到完全相同问题的另一个地方),因此目前似乎没有任何方法可以在 Java 中解决它。您将不得不自己再次解析路径。但是,看起来在 Scala 中很容易实现。这两个我都没有测试过,我对 Scala 也不是很熟悉,但看起来对于 Play in Scala,动作组合的工作方式不同。

    这个要点有一个例子,说明 Play Scala 动作组合应该如何支持这一点: https://gist.github.com/wolfendale/75e8b5e9a7ace95aa7e6d123e6c6dacd

    jroper 在这个问题线程中的帖子也展示了在我看来是相同的解决方案: https://github.com/playframework/playframework/issues/3378#issuecomment-54925034

    如果这些方法有效,那么如果您使用的是 Scala,article I linked in the original post 中演示的技术对于解决此问题完全没有必要。然而,因为它只需要在 Scala 中编写一些代码(而对于 wolfendale 和 jroper 演示的技术,您也需要在 Scala 中编写控制器),它可能是解决这个问题的有用方法,并且仍然编写您的大部分Java 中的应用程序。我不确定。我还没有测试过,我对那种 hack 不感兴趣。

    【讨论】:

      【解决方案2】:

      你不能,至少,不能开箱即用。 Play 不提供在动作组合中获取请求参数的方法。

      基本上:你必须自己解析。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-11
        • 1970-01-01
        • 2014-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-18
        • 1970-01-01
        相关资源
        最近更新 更多