您的位置:首页 > Web前端 > JavaScript

JSP过滤器(Filter)之实现全站数据压缩

2014-07-04 14:05 453 查看
一般用于返回给客户端的的数据都要进行压缩后再返回,以减少数据的传输

可以用下面的过滤器进行实现全站数据压缩

//全站压缩过滤器
/*
将所有的数据进行压缩,然后在输出到浏览器
就是重写response对象,然后让其输入的数据存在一个缓冲流中,然后在此过滤器中取出并压缩,再传给客户端
*/
public class GzipFilter implements Filter {

public void destroy() {

}

public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
//创建一个自己的response,此response对象在原有基础上增加了  以字节数组返回response对象中所有数据的功能
GzipHttpServletResponse gresponse = new GzipHttpServletResponse(response);
//放行
chain.doFilter(request, gresponse);

//到此次已经执行完了servlet

//压缩代码写在此处
//创建一个字节数组缓存输出流,用于存放压缩后的数据
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//创建一个字节压缩输出流,把数据压缩到baos这个字节缓存输出流中
GZIPOutputStream gout = new GZIPOutputStream(baos);

//取出request对象中的所有数据:压缩前的
byte b[] = gresponse.getOldBytes();//原始字节数组
System.out.println("原有数据大小:"+b.length);
//将原始数据存放到压缩字节输出流中,进行压缩,并将压缩完成的数据存放到baos这个字节数组缓存输出流中
gout.write(b);
//刷新
gout.flush();//保证所有的数据都进入 字节数组缓存输出流
//关闭压缩流
gout.close();

//取出压缩后的数据
b = baos.toByteArray();
System.out.println("压缩后的数据大小:"+b.length);

//输出前一定要告知客户端压缩方式(用的是当前的response对象)
response.setHeader("Content-Encoding", "gzip");
response.setContentLength(b.length);//告知客户压缩后的数据的大小
//获取当前response对象的字节输出流对象
ServletOutputStream out = response.getOutputStream();
//将压缩后的数据 读出到 response对象的字节输出流中
out.write(b);
//关闭流
out.close();
}

public void init(FilterConfig filterConfig) throws ServletException {

}

}
//创建一个自己的response,此response对象在原有基础上增加了  以字节数组返回response对象中所有数据的功能,
//此类继承了HttpServletResponseWrapper这个HttpServletResponse类的适配器
class GzipHttpServletResponse extends HttpServletResponseWrapper{
//创建一个字节数组缓存流
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
//定义一个自己的servletOutputStream 字节输出流对象
private MyServletOutputStream myOutputStream = null;

//定义一个字节输出转 字符输出的流
private OutputStreamWriter writer = null;
//创建一个打印字符输出流
private PrintWriter pw = null;
//构造方法
public GzipHttpServletResponse(HttpServletResponse response){
super(response);
}
//把原始数据封装到一个缓冲流中
@Override//从写父类中(response)的getOutputStream方法,从而使response.getOutputStream(),方法获取的是我的字节数组缓存流
public ServletOutputStream getOutputStream() throws IOException {
if(myOutputStream == null){
myOutputStream = new MyServletOutputStream(baos);
}
//返回给调用者
return myOutputStream;
}

//字符流:把原始数据封装到一个缓冲流中
@Override
public PrintWriter getWriter() throws IOException {
if(writer == null){
//将baos字节数组缓冲流转换成 一个字符输出流
writer = new OutputStreamWriter(baos, super.getCharacterEncoding());//字节流转成字符流需给一个编码表
}
//通过这个字符输出流,创建一个字符打印流,通过此打印字符输出流传入的数据,都会被封装到baos这个字节数组缓存流中
pw = new PrintWriter(writer);
//返回给调用者
return pw;
}

//返回baos中的缓存的所有数据:原始
public byte[] getOldBytes(){
try {
if(pw!=null){
pw.close();
}
baos.flush();
} catch (IOException e) {
e.printStackTrace();
}
//以字节数组返回baos字节数组缓存输出流中的所有数据
return baos.toByteArray();
}

}

//创建一个自己的字节缓存流,让写入此流中的数据都写入 到传入的字节数组缓存流中,此类继承了ServletOutputStream适配器
class MyServletOutputStream extends ServletOutputStream{
private ByteArrayOutputStream baos;
public MyServletOutputStream(ByteArrayOutputStream baos){
this.baos = baos;
}
//当读取到数据时,就存入baos这个字节数组缓存流中
@Override
public void write(int b) throws IOException {
baos.write(b);
}
}



在web.xml中配置文件中,注册此过滤器
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>AllStieFilter.GzipFilter</filter-class>
</filter>
<!-- 配置此过滤器的过滤范围,由于此过滤器是全站过滤器,直接配置/* -->
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


通过以上的过滤器,就实现了全站的数据压缩了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: