1. 压缩 Filter
// GZIPFilter.java
package org.demo.filter;
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;
/**
* Filter that compress output with gzip.
* Code from http://www.onjava.com/pub/a/onjava/2003/11/19/filters.html
* @author dycc
*
*/
public class GZIPFilter implements Filter{
@Override
public void init(FilterConfig arg0) throws ServletException {
// No operation.
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
if (req instanceof HttpServletRequest){
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
// check for gzip capability
String ac = request.getHeader("accept-encoding");
if (ac == null || ac.indexOf("gzip") == -1){
// not support gzip.
chain.doFilter(request, response);
} else {
// support gzip.
GZIPResponseWrapper wrappedResp = new GZIPResponseWrapper(response);
chain.doFilter(request, wrappedResp);
wrappedResp.finish();
}
}
}
@Override
public void destroy() {
// No operation.
}
}
// GZIPResponseWrapper.java
package org.demo.filter;
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;
/**
* Wrap for GZIPFilter
* @author dycc
*
*/
public class GZIPResponseWrapper extends HttpServletResponseWrapper{
protected HttpServletResponse original_resp = null;
protected ServletOutputStream stream = null;
protected PrintWriter writer = null;
public GZIPResponseWrapper(HttpServletResponse response) {
super(response);
this.original_resp = response;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null){
throw new IllegalStateException("getWriter() has already been called.");
}
if (stream == null){
stream = new GZIPResponseStream(original_resp);
}
return stream;
}
@Override
public PrintWriter getWriter() throws IOException {
if (stream != null){
throw new IllegalStateException("getOutputStream() has already been called.");
}
if (writer == null){
writer = new PrintWriter(
new OutputStreamWriter(
new GZIPResponseStream(original_resp),"UTF-8"));
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (stream != null){
stream.flush();
} else if (writer != null){
writer.flush();
}
}
public void finish(){
try {
if (stream != null){
stream.close();
} else if (writer != null){
writer.close();
}
} catch (IOException e){
// Ignore.
}
}
}
// GZIPResponseStream.java
package org.demo.filter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
/**
* Wrap response stream for GZIPFilter
* @author dycc
*
*/
public class GZIPResponseStream extends ServletOutputStream{
protected HttpServletResponse response = null;
protected ServletOutputStream out = null;
protected ByteArrayOutputStream baos = null;
protected GZIPOutputStream gzipos = null;
protected boolean closed = false;
public GZIPResponseStream(HttpServletResponse response)throws IOException{
super();
this.response = response;
this.out = response.getOutputStream();
this.baos = new ByteArrayOutputStream();
this.gzipos = new GZIPOutputStream(this.baos);
this.closed = false;
}
@Override
public void write(int b) throws IOException {
if (closed){
throw new IOException("Cannot write to a closed output stream.");
}
gzipos.write(b);
}
@Override
public void write(byte[] b) throws IOException {
write(b,0,b.length);
}
@Override
public void write(byte[] buf, int off, int len) throws IOException {
if (closed){
throw new IOException("Cannot write to a closed output stream.");
}
gzipos.write(buf, off, len);
}
@Override
public void flush() throws IOException {
if (closed){
throw new IOException("Cannot flush a closed output stream.");
}
gzipos.flush();
}
@Override
public void close() throws IOException {
if (closed){
return;
}
gzipos.finish();
byte[] buf = this.baos.toByteArray();
response.addHeader("Content-Length", Integer.toString(buf.length));
response.addHeader("Content-Encoding", "gzip");
out.write(buf);
out.flush();
out.close();
closed = true;
}
}
2. END