【问题标题】:How to do custom action composition to log request and response in Play 2.3?如何在 Play 2.3 中进行自定义操作组合以记录请求和响应?
【发布时间】:2014-12-09 23:03:10
【问题描述】:

我正在开发 Play 2.3 (Java) 应用程序,我需要一个自定义操作组合来记录请求和响应。到目前为止,我可以得到请求的正文,但不能得到响应:

import play.libs.F;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;

public class LogAction extends Action.Simple {

    public F.Promise<Result> call(Http.Context ctx) throws Throwable {
        //Request body
        String requestBody = ctx.request().body().asText();
        //Need to get response body here
        //String responseBody = ???
        return delegate.call(ctx);
    }

}

如何在这种情况下获取响应正文?如果在java中很难做到,也可以在scala中,但是它必须使用java控制器方法@With注解。

【问题讨论】:

    标签: java playframework-2.3


    【解决方案1】:
        @Override
        public F.Promise<Result> call(Http.Context ctx) throws Throwable {
            Promise<Result> call = delegate.call(ctx);
            return call.map((r) -> {
                byte[] body = JavaResultExtractor.getBody(r, 0l);
                Logger.info(new String(body));
                return r;
            });
        }
    

    您可以使用play.core.j.JavaResultExtractor 从响应中提取正文。请记住,getBody(..) 会阻塞直到响应准备好,因此请考虑调用 onRedeem 而不是 map

    【讨论】:

    • JavaResultExtractor.getBody(result, 0L) 即使我将其从 0 更改为 100k 也会超时。
    【解决方案2】:

    你有没有尝试过这样的事情:

    public class VerboseAction extends play.mvc.Action.Simple {
    
        public F.Promise<Result> call(Http.Context ctx) throws Throwable {
            Logger.info("Calling action for " + ctx);
            F.Promise<Result> resultPromise = delegate.call(ctx);
            resultPromise.map(result -> {
                Logger.info(result.toScala().header().status());
                Logger.info(result.toScala().body().toString());
                return result;
            });
            return resultPromise;
        }
    }
    

    正文将作为play.api.libs.iteratee.Enumerator 返回。现在困难的部分是处理这个问题。首先您需要了解Iteratee 的概念以及Enumerator 在其中扮演的角色。提示:将Enumerator 视为数据的生产者,并将Iteratee 视为此数据的消费者

    现在在这个Enumerator 上,您可以运行一个Iteratee,它将数据块转换为您想要的类型。

    坏消息是您需要实现 play.api.libs.iteratee.Iteratee 特征。如您所见,它位于 api 子包中,这意味着它是 Play 中 Scala 世界的一部分。也许在这种情况下,使用 Scala 来完成这部分任务会容易得多。不幸的是,我无法为您提供一些示例实现,但我希望这不会那么难。我认为这是 Play 的 Java 方面真正缺少的东西。

    【讨论】:

    • 感谢您的回答,尽管它似乎是在正确的方向,我得到这个记录 - play.api.libs.iteratee.Enumerator$$anon$18@2ae9a7b2 而不是出于某种原因的响应正文。
    猜你喜欢
    • 2017-07-28
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多