Servlet压缩

public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.声明被压缩的数据
        String str = "Hello你好";
        //2.获取准备压缩的数据的字节码
        byte[] src = str.getBytes("UTF-8");
        //3.在内存中声明一个容器
        ByteArrayOutputStream destByte = new ByteArrayOutputStream();
        //4.声明压缩的工具流,并设置压缩的目的地为destByte
        GZIPOutputStream zip = new GZIPOutputStream(destByte);
        //5.写入数据
        zip.write(src);
        //6.关闭压缩工具流
        zip.close();
        System.out.println("压缩之前的字节码大小:"+src.length);
        //7.获取压缩以后数据
        byte[] dest = destByte.toByteArray();
        System.out.println("压缩以后的字节码大小:"+dest.length);
        //8.必须要输出压缩以后字节数组
        response.setContentType("text/html;charset=UTF-8");
        //9.必须要使用字节流来输出信息
        OutputStream out = response.getOutputStream();
        //10.通知浏览器,这是压缩的数据,要求浏览器解压
        response.setHeader("Content-encoding", "gzip");
        //11.通过浏览器压缩数据的长度
        response.setContentLength(dest.length);
        //10.输出
        out.write(dest);
    }

数据必须较大才会显示出效果

全站压缩:

如果要对整个网站进行压缩,那么最好的办法就是在过滤器中写压缩的代码;全站压缩实现步骤如下

1.先简单写一个Servlet类,正常输出信息

public class OneServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");

PrintWriter out = response.getWriter();

out.println("Hello你好大家同学");

}

}

2.写一个过滤器对这个Servlet类进行拦截,在拦截过程中包装response

实现抽像类:HttpServletResponseWrapper

public class GzipFilter implements Filter {

public void init(FilterConfig filterConfig) throws ServletException {

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

//下面 这一段实现将数据写到a.txt中去。

//声明MyResponse包装类

MyResponse resp = new MyResponse((HttpServletResponse) response);

//放行时,必须要传递自己包装过的类

chain.doFilter(request, resp);

//下面这一段是读取a.txt中的数据。

//目标类调用完成了,返回 以后读取a.txt

File file = new File("d:/a/a.txt");

//声明一个缓存的字符串对象

StringBuilder sb = new StringBuilder();

//读取文件

InputStream in = new FileInputStream(file);

byte[] b = new byte[1024];

int len = 0;

while((len=in.read(b))!=-1){

sb.append(new String(b,0,len,"UTF-8"));

}

in.close();

//下面这段 压缩数据。

//转成字节开始压缩

byte[] src = sb.toString().getBytes("UTF-8");

//声明缓存容器

ByteArrayOutputStream destBytes = new ByteArrayOutputStream();

//声明压缩流

GZIPOutputStream gzip = new GZIPOutputStream(destBytes);

//压缩数据

gzip.write(src);

gzip.close();

//获取压缩以后数据

byte[] dest = destBytes.toByteArray();

System.err.println("压缩之前:"+src.length);

System.err.println("压缩以后:"+dest.length);

//下面这段输出压缩以后数据

//输出

//必须要使用原生 的response

HttpServletResponse res = (HttpServletResponse) response;

res.setContentType("text/html;charset=UTf-8");

OutputStream out = res.getOutputStream();

res.setHeader("Content-encoding", "gzip");//必须

res.setContentLength(dest.length);

out.write(dest);

}

public void destroy() {

}

}

//声明包装类

//实现对HttpSerlvetResponse的包装

class MyResponse extends HttpServletResponseWrapper{

public MyResponse(HttpServletResponse response) {

super(response);

}

//重写getWriter方法。

@Override

public PrintWriter getWriter() throws IOException {

System.err.println("有人想获取输出流");

PrintWriter out = new PrintWriter (//由于PrintWriter是GBK所以要使用转换流。

new OutputStreamWriter(

new FileOutputStream("d:/a/a.txt"),"UTF-8"));

return out;

}

}


4.上面的代码是存在问题的,有待完善。我们不能将每次输出都往文件里面存,IO消耗太大,正确的做法是修改包装类,让输出数据放到一个内存缓存区中

public class GzipFilter2 implements Filter {

public void init(FilterConfig filterConfig) throws ServletException {

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletResponse resp= (HttpServletResponse) response;

//声明包装类对象

MyResponse2 myresp = new MyResponse2(resp);

//放行,调用oneServlet.doGet

chain.doFilter(request, myresp);

//第二步:从myresp2中读取原生的数据

byte[] src = myresp.getSrc();//获取原生的数据。

//第三步:开始压缩

ByteArrayOutputStream destBytes = new ByteArrayOutputStream();

GZIPOutputStream zip = new GZIPOutputStream(destBytes);

zip.write(src);

zip.close();

//第三步:输出-使用原生的response

resp.setContentType("text/html;charset=UTF-8");

//获压缩以后数据

byte[] dest = destBytes.toByteArray();

System.err.println("压缩之前:"+src.length);

System.err.println("压缩以后:"+dest.length);

//设置头

resp.setContentLength(dest.length);

resp.setHeader("Content-Encoding","gzip");

//输出

OutputStream out = resp.getOutputStream();

out.write(dest);

}

public void destroy() {

}

}

//第一步:声明response的包装类

class MyResponse2 extends HttpServletResponseWrapper{

//将这个容器/a.txt,声明成员变量

private ByteArrayOutputStream srcByte;

public MyResponse2(HttpServletResponse response) {

super(response);

}

//修改增强getWtier方法

@Override

public PrintWriter getWriter() throws IOException {

srcByte = new ByteArrayOutputStream();

PrintWriter out =

new PrintWriter(

new OutputStreamWriter(srcByte, "UTF-8"));

return out;

}

//提供一个方法获取原生 的数据

public byte[] getSrc(){

return srcByte.toByteArray();

}

}


5.全部的jsp都要经过压缩

只要是通过包装rersponse,且修改了getWriter方法,返回一个自己的printwiter对象。声明一个放原数据的容器对象。就可以实现数据压缩。

public class GzipFilter2 implements Filter {

public void init(FilterConfig filterConfig) throws ServletException {

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletResponse resp= (HttpServletResponse) response;

//声明包装类对象

MyResponse2 myresp = new MyResponse2(resp);

//放行,调用oneServlet.doGet

chain.doFilter(request, myresp);

//第二步:从myresp2中读取原生的数据

byte[] src = myresp.getSrc();

//第三步:开始压缩

ByteArrayOutputStream destBytes = new ByteArrayOutputStream();

GZIPOutputStream zip = new GZIPOutputStream(destBytes);

zip.write(src);

zip.close();

//第三步:输出-使用原生的response

resp.setContentType("text/html;charset=UTF-8");

//获压缩以后数据

byte[] dest = destBytes.toByteArray();

System.err.println("压缩之前:"+src.length);

System.err.println("压缩以后:"+dest.length);

//设置头

resp.setContentLength(dest.length);

resp.setHeader("Content-Encoding","gzip");

//输出

OutputStream out = resp.getOutputStream();

out.write(dest);

}

public void destroy() {

}

}

//第一步:声明response的包装类

class MyResponse2 extends HttpServletResponseWrapper{

//将这个容器/a.txt,声明成员变量

private ByteArrayOutputStream srcByte;

private PrintWriter out;//为了可以关闭,所以将这个对象,声明成成员变量 。

public MyResponse2(HttpServletResponse response) {

super(response);

}

//修改增强getWtier方法

@Override

public PrintWriter getWriter() throws IOException {

srcByte = new ByteArrayOutputStream();

out =

new PrintWriter(

new OutputStreamWriter(srcByte, "UTF-8"));

return out;

}

//提供一个方法获取原生 的数据

public byte[] getSrc(){

if(out!=null){

out.close();//如果tomcat没有关,我们自己关闭。

}

return srcByte.toByteArray();

}

}


且它的配置如下:

zip2

cn.itcast.filter.GzipFilter2

zip2

*.jsp//对所有jsp都压缩。


 

6.同时实现对getoutputstream和getWtier压缩

思想:

在myrespons2这个类中,对getoutputstream也要覆盖。

返回一个ServletOutputSteam的匿名对象。

实现witer(int b)方法,将数据写到bytearrayoyutpoutstream.

@Override

public ServletOutputStream getOutputStream() throws IOException {

srcByte = new ByteArrayOutputStream();

ServletOutputStream out = new ServletOutputStream() {

//所有IO最终都是一个个字节写出信息

@Override

public void write(int b) throws IOException {

System.err.println(">>>:"+b);

srcByte.write(b);//写到自己的缓存中去-相当于StringBuffer.append(""+b);

}

};

return out;

}

你可能感兴趣的:(java)