Filter.doFilter() 在调用之前只调用一次 HttpHandler.handle()。
这意味着您无法在处理程序运行后修改 HTTP 响应的内容。所以,它更自然地是一个前置过滤器。
然而,在你的 doFilter() 实现中,你可以用你自己的 FilterOutputStream 包装响应的 OutputStream,这样你就可以拦截对 HttpExchange.getResponseBody().write(...) 的调用。
class MyFilter extends Filter {
@Override
public void doFilter(HttpExchange exch, Chain chain) throws IOException {
exch.setStreams(null, new MyInterceptedOutputStream(exch.getResponseBody()));
chain.doFilter(exch);
}
...
}
这个 MyInterceptedOutputStream 类需要扩展 OutputStream 并实现其常用方法(write() 和 close() em>)
一个技巧:您的包装器必须确保在调用 HttpExchange.sendResponseHeaders() 之前它不会向原始 OutputStream 写入任何内容。这意味着您必须确保您的包装器构造函数(上述示例中的 MyInterceptedOutputStream(OutputStream os) )不写入任何内容,这与 GZIPOutputStream() 不同!
Bonus:OutputStream 包装器的示例,用于压缩流...并在 HttpFilter.doFilter()
中工作
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
public class GZIPDelayedOutputStream extends OutputStream {
GZIPOutputStream gzipStream;
OutputStream originalStream;
public GZIPDelayedOutputStream(OutputStream os) {
super();
originalStream = os;
}
private void createGzipStreamIfNecessary() throws IOException {
if (gzipStream == null) {
gzipStream = new GZIPOutputStream(originalStream);
}
}
@Override
public void write(int b) throws IOException {
createGzipStreamIfNecessary();
gzipStream.write(b);
}
@Override
public void write(byte buf[]) throws IOException {
createGzipStreamIfNecessary();
gzipStream.write(buf);
}
@Override
public void write(byte[] buf, int off, int len) throws IOException {
createGzipStreamIfNecessary();
gzipStream.write(buf, off, len);
}
@Override
public void close() throws IOException {
createGzipStreamIfNecessary();
gzipStream.close();
}
}