您的位置:首页 > 其它

response压缩响应

2016-01-05 14:30 309 查看
思路:1、通过filter向目标页面传递一个自定义的response对象

2.、在这个response对象中通过重写getOutputStream方法和getWriter方法使目标资源调用

该方法输出页面内容时,获得我们自定义的ServletOutputStream对象

3、在我们自己定义的ServletOutputStream中,重写writer 方法,使资源写到buffer中。

4、当页面完成输出后,在filter中就可以得到页面写出的数据,从而我们可以调用GZIPOutputStream

对数据进行压缩后再传递给浏览器,完成响应文件的压缩功能

目的:减少浏览器的响应时间以及节省带宽

1、showServlet类:

public class ShowServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获得response的输出流
ServletOutputStream sout=response.getOutputStream();
//字符串转化为字节输出
sout.write("AAAAAAAfwef fds asdfsdaf sdfa sdfasd sadf AAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes());
}
}


2、MyResponse类:

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

/*HttpServletResponseWrapper
是一个Decoretor设计模式的默认实现类
不需要像实现request接口中的所有方法
以下为装饰类的做法
*/
public class MyResponse extends HttpServletResponseWrapper {
private HttpServletResponse response;
private ByteArrayOutputStream bout=new ByteArrayOutputStream();

public MyResponse(HttpServletResponse response) {
super(response);
this.response=response;
}

/*综合考虑下还是重写getOutStream
但是需求是要输出到缓存,此方法不适合,于是写一个拓展类类来迎合需求*/
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyServletOutputStream(bout);
}

//将数据封装成一个数组然后发送到缓存
class MyServletOutputStream extends ServletOutputStream{
private ByteArrayOutputStream bout;
public MyServletOutputStream(ByteArrayOutputStream bout){
this.bout=bout;

}

/*此处应该要将数据包装成一个数组但是
此处不符合需求,于是重载*/
@Override
public void write(int b) throws IOException {

}
public void write(byte[] bytes) throws IOException {
bout.write(bytes);
bout.flush();
bout.close();
}

}
public byte[] getBuffer() {
return bout.toByteArray();
}
}


3、GZIPFilter过滤类:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

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;

public class GZIPFilter implements Filter {
@Override
public void destroy() {
}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
//转化为子类才能处理,此处用了强制类型转换
HttpServletRequest request=(HttpServletRequest) req;
HttpServletResponse response=(HttpServletResponse) res;

//创建MyResponse
MyResponse myResponse=new MyResponse(response);

//此处放行的response是处理过的response
chain.doFilter(request, myResponse);

//在输出到浏览器之前将输过来的buffer进行压缩
//增加getBuffer方法
byte[] bytes=myResponse.getBuffer();
//输出压缩前的长度以作对比
System.out.println("压缩前"+bytes.length);

//用GZIPOutputStream压缩
ByteArrayOutputStream bout=new ByteArrayOutputStream();
GZIPOutputStream gzip=new GZIPOutputStream(bout);

gzip.write(bytes);

//一般输出都要flush
gzip.flush();
gzip.close();
bytes=bout.toByteArray();
//压缩后
System.out.println("压缩后"+bytes.length);

//注明压缩类型
response.setHeader("content-encoding", "gzip");
response.setHeader("content-length",bytes.length+"");
//写到浏览器,浏览器会自动解压,只要注明了类型
response.getOutputStream().write(bytes);

}

@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

}


其中在xml配置文件中应该添加以下代码

<filter>
<filter-name>GZIPFilter</filter-name>
<filter-class>a2.GZIPFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>GZIPFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


控制台输出(显示压缩的效果)

浏览器输出(显示响应报文)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: