我正在使用PlayFramework版本2.0.2,我正在尝试创建一个游戏play.mvc.Action
来为http结果实现后置过滤器。
使用actor进行预处理的示例在play docs。
中进行了解释然而,我想要达到的目标有点不同。我需要:
play.mvc.Result
Result
界面不会公开http正文,甚至假设你有特定的子类(比如SimpleResult
或AsyncResult
)我不是确定如何提取邮件正文。
我的具体用例是GZip结果体并添加正确的“Content-Encoding”标头的过滤器。我希望能够通过添加注释来将此GZip
过滤器应用于任何现有的Controller,类似于在文档中实现身份验证的方式。
下面是我想要做的一个例子
public class Compress {
@With(GZipResult.class)
public @interface GZip {
}
public static class GZipResult extends Action<GZip> {
@Override
public Result call(Http.Context ctx) throws Throwable {
Result result = delegate.call(ctx);
if (requestSupportsGZip(ctx) {
result = extractAndGZipResult(result); //how to extract http body?
}
return result;
}
}
}
可以用作
@Compress.GZip
class MyController extends Controller {
public static Result index() {
return ok(someHtml);
}
}
答案 0 :(得分:4)
我在修改http结果时遇到了类似的情况。我想分享我在Java中处理这个问题的方法。
在检查Play 2.0.3的Scala源代码后,我发现play.core.j.JavaResultExtractor
可以检索Java中Result
类的响应正文,cookie,标题和状态{{1} }可以写出响应体的内容。
尽管如此,我仍然不知道如何以简单的方式用修改后的身体替换当前的反应体。也许用Scala实现处理这个会更容易,但我仍然发现Scala太神秘了: - (
我找到的方法是查看如何实现play.core.j.JavaResults
,它使用play.mvc.Results.Status
来编写内容正文。我提到的课程是play.core.j.JavaResults
,ok()
,notFound()
的核心,以及在Java中forbidden()
类中生成Result
的其他类似方法。这个类的实现如下所示:(重构Scala类以提高可读性)
Controller
如果您希望实现上述代码,还需要实现// scala classes
import play.api.mvc.Codec;
import play.api.mvc.Content;
import play.core.j.JavaResults;
// ...
public static class Status implements Result {
final private play.api.mvc.Result wrappedResult;
// ...
// there are a lot of constructors for this class to reference from
// this particular constructor is the general approach for most cases
public Status(play.api.mvc.Results.Status status, Content content, Codec codec) {
// ...
wrappedResult = status.apply(
content,
JavaResults.writeContent(codec),
JavaResults.contentTypeOf(content.contentType() + "; charset=" + codec.charset())
);
}
}
接口。总而言之,从我说的内容中实现你的代码看起来像这样:
play.api.mvc.Content
通过上面的实现,我可以修改http结果。我希望这可以帮助您完成特定的用例。
干杯!
<强> 强>
上面的代码可以解决修改http结果的大多数用例。你的特殊情况,即gzipping响应,需要一种替代方法,因为gzipped主体位于import play.api.mvc.Codec;
import play.api.mvc.Content;
import play.core.j.JavaResultExtractor;
import play.core.j.JavaResults;
// ...
public static class GZipResult extends Action<GZip> {
@Override
public Result call(Http.Context ctx) throws Throwable {
Result result = delegate.call(ctx);
if (requestSupportsGZip(ctx)) {
// copy parts of current response
final int statusCode = JavaResultExtractor.getStatus(result);
final Map<String,String> headers = JavaResultExtractor.getHeaders(result);
final byte[] body = JavaResultExtractor.getBody(result);
// create a gzip result
result = new GZipResult(statusCode, new String(body), headers.get("Content-Type"));
// add appropriate headers here
// ...
}
return result;
}
}
private static class GZipResult implements Result {
final private play.api.mvc.Result wrappedResult;
public GZipResult(final int StatusCode, final String content, final String contentType) {
if(content == null) throw new NullPointerException("null content");
// i guess this is the good place in transforming the content body
String gzippedContent = someMethodToGzipContent(content);
this.wrappedResult = JavaResults.Status(statusCode).apply(
// implement the play.api.mvc.Content interface
new Content() {
@Override public String body() { return gzippedContent; }
@Override public String contentType() { return contentType; }
},
JavaResults.writeContent(Codec.utf_8),
JavaResults.contentTypeOf(contentType))
);
}
// ...
}
而不是byte[]
。 String
类还提供了处理play.mvc.Results.Status
的方法。实现如下:
byte[]
您可以在我的更新之前根据我的实现了解如何对代码执行此操作。请注意,您不再需要实现// scala classes
import play.core.j.JavaResults;
// ...
public static class Status implements Result {
final private play.api.mvc.Result wrappedResult;
// ...
public Status(play.api.mvc.Results.Status status, byte[] content) {
// ...
wrappedResult = status.apply(
content,
JavaResults.writeBytes(),
JavaResults.contentTypeOfBytes()
);
}
}
,并确保在响应中返回适当的内容类型。
快乐编码: - )
答案 1 :(得分:3)
AFAIK,经过一番挖掘后,您可以使用result.getWrappedResult()
获取回复的正文;它返回一个play.api.mvc.Result
,可以(通常)转换为包含play.api.mvc.SimpleResult
方法的body()
:
play.api.mvc.SimpleResult wrappedResult = (play.api.mvc.SimpleResult) result.getWrappedResult();
Enumerator body = wrappedResult.body();
然后,我建议你阅读Enumerator doc;目前,我还没弄清楚这些事情是如何运作的: - )。
希望这对你有所帮助......