在HttpHandler.handle()被调用之前, Filter.doFilter()只被调用一次 。
这意味着在处理程序运行后,您无法修改 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())
一个技巧:您的包装器必须确保在调用HttpExchange.sendResponseHeaders()之前它不会向原始OutputStream写入任何内容。这意味着您必须确保您的包装器构造函数(上面示例中的MyInterceptedOutputStream(OutputStream os))不写任何东西,这与GZIPOutputStream()不同!
奖励:压缩流的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();
}
}