在 Play!Framework 中批量 HTTP 请求 [英] Batch HTTP requests in Play!Framework

查看:26
本文介绍了在 Play!Framework 中批量 HTTP 请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.~~~~~删除/api/:version/:entity my.controllers.~~~~~POST/api/:version/search/:entity my.controllers.~~~~~

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

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

身体应该是这样的:

<预><代码>[{"方法": "POST","call": "/api/1/customer",身体": {"name": "安东尼奥",电子邮件":tonysmallhands@gmail.com"}},{"方法": "POST","呼叫": "/api/1/customer/2",身体": {姓名":马里奥"}},{"方法": "获取","call": "/api/1/company"},{"方法": "删除",呼叫":/api/1/company/22"}]

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

@Test公共无效badRoute(){结果 result = play.test.Helpers.routeAndCall(fakeRequest(GET, "/xx/Kiki"));assertThat(result).isNull();}

进入routeAndCall()的源代码,你会发现这样的事情:

/*** 使用路由器确定调用此请求的操作并执行它.* @已弃用* @see #route 代替*/@SuppressWarnings(value = "unchecked")公共静态结果 routeAndCall(FakeRequest fakeRequest) {尝试 {return routeAndCall((Class)FakeRequest.class.getClassLoader().loadClass("Routes"), fakeRequest);} catch(RuntimeException e) {扔e;} 捕捉(可扔的 t){抛出新的运行时异常(t);}}/*** 使用路由器确定调用此请求的操作并执行它.* @已弃用* @see #route 代替*/public static 结果 routeAndCall(Class router, FakeRequest fakeRequest) {尝试 {play.core.Router.Routes routes = (play.core.Router.Routes)router.getClassLoader().loadClass(router.getName() + "$").getDeclaredField("MODULE$").get(null);if(routes.routes().isDefinedAt(fakeRequest.getWrappedRequest())) {返回 invokeHandler(routes.routes().apply(fakeRequest.getWrappedRequest()), fakeRequest);} 别的 {返回空;}} catch(RuntimeException e) {扔e;} 捕捉(可扔的 t){抛出新的运行时异常(t);}}

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

解决方案

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

I have the current set of of routes implemented (for example):

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.~~~~~

And they work beautifully. Now let's say I want to implement a "batch endpoint" for the same API. It should look something like this:

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

and the body should look like this:

[
    {
        "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"
    }
]

To do that I would like to know how I can call the play framework router to pass those requests? I was planning to use something similar as what is advised for unit tests:

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

by going into the source code of routeAndCall(), you find something like this:

 /**
 * 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);
    }
}

So my question is: Is there a less "hacky" way to do this with Play (I am not against mixing Scala and Java to get to it) than to copy the above code? I would have also like to give the option of executing the batched calls in parallel or in sequence ... I guess instantiating only one Routes using the class loader would be problematic then?

解决方案

You can use the following method call to route your fake requests: Play.current.global.onRouteRequest. Please see this post for a full example: http://yefremov.net/blog/play-batch-api/

这篇关于在 Play!Framework 中批量 HTTP 请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆