【问题标题】:Batch HTTP requests in Play!FrameworkPlay!Framework 中的批处理 HTTP 请求
【发布时间】:2014-03-25 04:36:16
【问题描述】:

我已经实现了当前的一组路由(例如):

GET     /api/:version/:entity               my.controllers.~~~~~
GET     /api/:version/:entity/:id           my.controllers.~~~~~
POST    /api/:version/:entity               my.controllers.~~~~~
POST    /api/:version/:entity/:id           my.controllers.~~~~~
DELETE  /api/:version/:entity               my.controllers.~~~~~

POST    /api/:version/search/:entity        my.controllers.~~~~~

而且它们工作得很好。现在假设我想为同一个 API 实现一个“批处理端点”。它应该看起来像这样:

POST    /api/:version/batch                 my.controllers.~~~~~

身体应该是这样的:

[
    {
        "method": "POST",
        "call": "/api/1/customer",
        "body": {
            "name": "antonio",
            "email": "tonysmallhands@gmail.com"
        }
    },
    {
        "method": "POST",
        "call": "/api/1/customer/2",
        "body": {
            "name": "mario"
        }
    },
    {
        "method": "GET",
        "call": "/api/1/company"
    },
    {
        "method": "DELETE",
        "call": "/api/1/company/22"
    }
]

为此,我想知道如何调用播放框架路由器来传递这些请求?我打算使用与单元测试建议类似的东西:

@Test
public void badRoute() {
  Result result = play.test.Helpers.routeAndCall(fakeRequest(GET, "/xx/Kiki"));
  assertThat(result).isNull();
} 

通过查看routeAndCall()的源代码,你会发现这样的内容:

 /**
 * Use the Router to determine the Action to call for this request and executes it.
 * @deprecated
 * @see #route instead
 */
@SuppressWarnings(value = "unchecked")
public static Result routeAndCall(FakeRequest fakeRequest) {
    try {
        return routeAndCall((Class<? extends play.core.Router.Routes>)FakeRequest.class.getClassLoader().loadClass("Routes"), fakeRequest);
    } catch(RuntimeException e) {
        throw e;
    } catch(Throwable t) {
        throw new RuntimeException(t);
    }
}

/**
 * Use the Router to determine the Action to call for this request and executes it.
 * @deprecated
 * @see #route instead
 */
public static Result routeAndCall(Class<? extends play.core.Router.Routes> router, FakeRequest fakeRequest) {
    try {
        play.core.Router.Routes routes = (play.core.Router.Routes)router.getClassLoader().loadClass(router.getName() + "$").getDeclaredField("MODULE$").get(null);
        if(routes.routes().isDefinedAt(fakeRequest.getWrappedRequest())) {
            return invokeHandler(routes.routes().apply(fakeRequest.getWrappedRequest()), fakeRequest);
        } else {
            return null;
        }
    } catch(RuntimeException e) {
        throw e;
    } catch(Throwable t) {
        throw new RuntimeException(t);
    }
}

所以我的问题是:有没有比复制上面的代码更“hacky”的方式来使用 Play(我不反对混合 Scala 和 Java 来实现它)?我还想提供并行或顺序执行批处理调用的选项...我猜使用类加载器仅实例化一个Routes 会有问题吗?

【问题讨论】:

    标签: java scala playframework playframework-2.2


    【解决方案1】:

    您可以使用以下方法调用来路由您的虚假请求: Play.current.global.onRouteRequest。请参阅此帖子以获取完整示例:http://yefremov.net/blog/play-batch-api/

    【讨论】:

      【解决方案2】:

      您可能可以使用WS API,但我个人只是创建一个私有方法来收集数据并从“单一”和“批量”操作中使用它们——它肯定会更快。

      【讨论】:

      • 我确实考虑过这个(绝望地)。我想避免必须向我的服务器发送额外的 HTTP 请求......因为毕竟批处理端点的一大优势是只需一个 HTTP 请求的开销即可执行大量调用。
      • 因此只需采用第二种建议的方法,在您的batch 操作中,您可以先收集即。要获取的 id 列表,然后执行单个查询并构建返回对象
      • 您能说得更具体些吗?我对批处理的一般原则没有任何问题......我唯一的问题是我不知道如何从我的代码中调用播放框架路由。
      猜你喜欢
      • 2017-09-03
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多