如何在Play 2.3中执行自定义操作合成以记录请求和响应?

时间:2014-10-02 09:12:09

标签: java playframework-2.3

我正在开发Play 2.3(Java)应用程序,我需要一个自定义的Action Composition来记录请求和响应。到目前为止,我已经得到了请求的主体,但没有回复:

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注释。

2 个答案:

答案 0 :(得分:3)

    @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

答案 1 :(得分:1)

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

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方面确实缺少了。