Gzip 服务端压缩数据,提高传输速率。
首先写一个过滤器
public class GzipValidator implements Filter{
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) arg0 ;
HttpServletResponse response = (HttpServletResponse) arg1;
CachedResponseWrapper responseWrapper = null ;
responseWrapper = new CachedResponseWrapper(response);
filterChain.doFilter(request, responseWrapper);
byte[] responseData = responseWrapper.getResponseData();
System.out.println(responseData.length);
//压缩数据
responseData=compress(request, responseWrapper, responseData);
System.out.println(responseData.length);
//发送数据
response.setContentLength(responseData.length);
response.setHeader("Content-Encoding", "gzip");
ServletOutputStream output = response.getOutputStream();
//因为是包装过后的所以要重新输出
output.write(responseData);
output.flush();
output.close();
}
public byte[] compress(HttpServletRequest request,
HttpServletResponse response, byte[] responseData){
String acceptEncoding = request.getHeader("Accept-Encoding");
if ( acceptEncoding == null
||!acceptEncoding.contains("gzip")) {
return responseData;
}
response.setHeader("Content-Encoding", "gzip");
return GzipUtil.gzip(responseData);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
GzipUtil 类
public class GzipUtil {
public static byte[] gzip(byte[] data){
ByteArrayOutputStream byteOutput=new ByteArrayOutputStream(10240);
GZIPOutputStream output =null;
try {
output = new GZIPOutputStream(byteOutput);
output.write(data);
} catch (IOException e) {
throw new RuntimeException("Gzip failed.", e);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
}
}
}
return byteOutput.toByteArray();//将字节流转换为byte数组
}
}
CachedResponseWrapper类
public class CachedResponseWrapper extends HttpServletResponseWrapper{
/**
* Indicate that getOutputStream() or getWriter() is not called yet.
*/
public static final int OUTPUT_NONE = 0;
/**
* Indicate that getWriter() is already called.
*/
public static final int OUTPUT_WRITER = 1;
/**
* Indicate that getOutputStream() is already called.
*/
public static final int OUTPUT_STREAM = 2;
private int outputType = OUTPUT_NONE;
private int status = SC_OK;
private ServletOutputStream output = null;
private PrintWriter writer = null;
private ByteArrayOutputStream buffer = null;
public CachedResponseWrapper(HttpServletResponse resp) throws IOException {
super(resp);
buffer = new ByteArrayOutputStream();
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public void setStatus(int status, String string) {
super.setStatus(status, string);
this.status = status;
}
public void sendError(int status, String string) throws IOException {
super.sendError(status, string);
this.status = status;
}
public void sendError(int status) throws IOException {
super.sendError(status);
this.status = status;
}
public void sendRedirect(String location) throws IOException {
super.sendRedirect(location);
this.status = SC_MOVED_TEMPORARILY;
}
public PrintWriter getWriter() throws IOException {
if (outputType == OUTPUT_STREAM)
throw new IllegalStateException();
else if (outputType == OUTPUT_WRITER)
return writer;
else {
outputType = OUTPUT_WRITER;
writer = new PrintWriter(new OutputStreamWriter(buffer,
getCharacterEncoding()));
return writer;
}
}
public ServletOutputStream getOutputStream() throws IOException {
if (outputType == OUTPUT_WRITER)
throw new IllegalStateException();
else if (outputType == OUTPUT_STREAM)
return output;
else {
outputType = OUTPUT_STREAM;
output = new WrappedOutputStream(buffer);
return output;
}
}
public void flushBuffer() throws IOException {
if (outputType == OUTPUT_WRITER)
writer.flush();
if (outputType == OUTPUT_STREAM)
output.flush();
}
public void reset() {
outputType = OUTPUT_NONE;
buffer.reset();
}
/**
* Call this method to get cached response data.
*
* @return byte array buffer.
* @throws IOException
*/
public byte[] getResponseData() throws IOException {
flushBuffer();
return buffer.toByteArray();
}
/**
* This class is used to wrap a ServletOutputStream and store output stream
* in byte[] buffer.
*/
class WrappedOutputStream extends ServletOutputStream {
private ByteArrayOutputStream buffer;
public WrappedOutputStream(ByteArrayOutputStream buffer) {
this.buffer = buffer;
}
public void write(int b) throws IOException {
buffer.write(b);
}
public byte[] toByteArray() {
return buffer.toByteArray();
}
}
}
遇到的问题:发送数据的时候先设置相应数据的长度再获得包装之后的输出流。