Можно и написать. Где-то давно уже стащил, вроде бы из какой-то книги, так и пользуюсь.
| Код | package com.domain.filters;
import java.io.IOException;
import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
public class GZIPFilter implements Filter { protected static final Log logger = LogFactory.getLog(GZIPFilter.class);
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { if (req instanceof HttpServletRequest) { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String ae = request.getHeader("accept-encoding"); if (ae != null && ae.indexOf("gzip") != -1) { logger.debug("GZIP supported, compressing."); GZIPResponseWrapper wrappedResponse = new GZIPResponseWrapper(response); chain.doFilter(req, wrappedResponse); wrappedResponse.finishResponse(); return; } chain.doFilter(req, res); } }
public void init(FilterConfig filterConfig) { // noop }
public void destroy() { // noop }
}
|
| Код | package com.domain.filters;
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse;
public class GZIPResponseStream extends ServletOutputStream {
// abstraction of the output stream used for compression protected OutputStream bufferedOutput = null;
// state keeping variable for if close() has been called protected boolean closed = false;
// reference to original response protected HttpServletResponse response = null;
// reference to the output stream to the client's browser protected ServletOutputStream output = null;
// default size of the in-memory buffer private int bufferSize = 50000;
public GZIPResponseStream(HttpServletResponse response) throws IOException { super(); closed = false; this.response = response; this.output = response.getOutputStream(); bufferedOutput = new ByteArrayOutputStream(); }
public void close() throws IOException { // This hack shouldn't be needed, but it seems to make JBoss and Struts // like the code more without hurting anything. /* * // verify the stream is yet to be closed if (closed) { throw new * IOException("This output stream has already been closed"); } */ // if we buffered everything in memory, gzip it if (bufferedOutput instanceof ByteArrayOutputStream) { // get the content ByteArrayOutputStream baos = (ByteArrayOutputStream) bufferedOutput; // prepare a gzip stream ByteArrayOutputStream compressedContent = new ByteArrayOutputStream(); GZIPOutputStream gzipstream = new GZIPOutputStream( compressedContent); byte[] bytes = baos.toByteArray(); gzipstream.write(bytes); gzipstream.finish(); // get the compressed content byte[] compressedBytes = compressedContent.toByteArray(); // set appropriate HTTP headers response.setContentLength(compressedBytes.length); response.addHeader("Content-Encoding", "gzip"); output.write(compressedBytes); output.flush(); output.close(); closed = true; } // if things were not buffered in memory, finish the GZIP stream and // response else if (bufferedOutput instanceof GZIPOutputStream) { // cast to appropriate type GZIPOutputStream gzipstream = (GZIPOutputStream) bufferedOutput; // finish the compression gzipstream.finish(); // finish the response output.flush(); output.close(); closed = true; } }
public void flush() throws IOException { if (closed) { throw new IOException("Cannot flush a closed output stream"); } bufferedOutput.flush(); }
public void write(int b) throws IOException { if (closed) { throw new IOException("Cannot write to a closed output stream"); } // make sure we aren't over the buffer's limit checkBufferSize(1); // write the byte to the temporary output bufferedOutput.write((byte) b); }
private void checkBufferSize(int length) throws IOException { // check if we are buffering too large of a file if (bufferedOutput instanceof ByteArrayOutputStream) { ByteArrayOutputStream baos = (ByteArrayOutputStream) bufferedOutput; if (baos.size() + length > bufferSize) { // files too large to keep in memory are sent to the client // without Content-Length specified response.addHeader("Content-Encoding", "gzip"); // get existing bytes byte[] bytes = baos.toByteArray(); // make new gzip stream using the response output stream GZIPOutputStream gzipstream = new GZIPOutputStream(output); gzipstream.write(bytes); // we are no longer buffering, send content via gzipstream bufferedOutput = gzipstream; } } }
public void write(byte b[]) throws IOException { write(b, 0, b.length); }
public void write(byte b[], int off, int len) throws IOException { if (closed) { throw new IOException("Cannot write to a closed output stream"); } // make sure we aren't over the buffer's limit checkBufferSize(len); // write the content to the buffer bufferedOutput.write(b, off, len); }
public boolean closed() { return (this.closed); }
public void reset() { // noop }
}
|
| Код | package com.domain.filters;
import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter;
import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper;
public class GZIPResponseWrapper extends HttpServletResponseWrapper {
protected HttpServletResponse origResponse = null;
protected ServletOutputStream stream = null;
protected PrintWriter writer = null;
public GZIPResponseWrapper(HttpServletResponse response) { super(response); origResponse = response; }
public ServletOutputStream createOutputStream() throws IOException { return (new GZIPResponseStream(origResponse)); }
public void finishResponse() { try { if (writer != null) { writer.close(); } else { if (stream != null) { stream.close(); } } } catch (IOException e) { } }
public void flushBuffer() throws IOException { stream.flush(); }
public ServletOutputStream getOutputStream() throws IOException { if (writer != null) { throw new IllegalStateException( "getWriter() has already been called!"); }
if (stream == null) stream = createOutputStream(); return (stream); }
public PrintWriter getWriter() throws IOException { if (writer != null) { return (writer); }
if (stream != null) { throw new IllegalStateException( "getOutputStream() has already been called!"); }
stream = createOutputStream(); // BUG FIX 2003-12-01 Reuse content's encoding, don't assume UTF-8 writer = new PrintWriter(new OutputStreamWriter(stream, origResponse .getCharacterEncoding())); return (writer); }
public void setContentLength(int length) { }
}
|
В web.xml
| Код | <filter> <filter-name>GZIPFilter</filter-name> <filter-class>com.domain.filters.GZIPFilter</filter-class> </filter> <filter-mapping> <filter-name>GZIPFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
Теоретически должно работать на любом сервере. У меня работает и на Tomcat 5.5 и на Resin 3.0 |