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();
}
}
且它的配置如下:
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;
}