我在修改 http 结果时遇到了类似的情况。我想分享我在 Java 中处理这个问题的方法。
通过查看Play 2.0.3的Scala源代码,我发现可以在Javaplay.core.j.JavaResultExtractor
中检索响应体、cookies、headers和类的状态,并且可以编写响应体的内容。Result
play.core.j.JavaResults
尽管如此,我仍然不知道如何以简单的方式用修改后的主体替换当前的响应主体。也许用 Scala 实现处理这个问题会更容易,但我仍然发现 Scala 太难读了:-(
我找到的方式是看play.mvc.Results.Status
是如何实现的,它使用play.core.j.JavaResults
来编写内容主体。我提到的类是Java中类中生成的ok()
、、、和其他类似方法的核心。此类的实现如下所示:(重构 Scala 类以提高可读性)notFound()
forbidden()
Result
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
接口。总而言之,按照我所说的实现你的代码看起来像这样:
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))
);
}
// ...
}
通过上面的实现,我可以修改 http 结果。我希望这可以为您的特定用例提供帮助。
干杯!
更新
上面的代码可以解决大多数修改 http 结果的用例。您的特殊情况,即 gzipping 响应,需要另一种方法,因为 gzipped 正文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()
);
}
}
您可以在我更新之前根据我的实现找出如何对您的代码执行此操作。请注意,您不再需要实现play.api.mvc.Content
并确保在响应中返回适当的内容类型。
快乐编码:-)