GzipOutputStream - > > ByteArrayOutputStream
压缩工具-->>压缩结果容器
1:以下是在某个servlet中对指定的数据进行压缩:
public class Gzip extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 声明准备被压缩的数据
String str = "Hello你好Hello你好在内存中声明一Hello你好在"
+ "内存中声明一个Hello你好在内存中声明一个Hello你"
+ "好在内存中声明一个<br/>容器声明准备被压缩获取准备被压缩"
+ "的数据的字节码的数据容器声明准备被压缩获取准备被压缩的数"
+ "据的字节码的数据容器声明准备被压缩获取准备被压缩的数据的"
+ "字节码的数据个容器声明准备被压缩获取准备被压缩的数据的字节码的"
+ "数据在内存中声明一个容器声明准备被压缩获取准备被压缩的数据" + "的字节码的数据";
// 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.err.println("压缩之前字节码大小:" + src.length);
// 7:获取压缩以后数据
byte[] dest = destbyte.toByteArray();
System.err.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);
}
}
压缩之前字节码大小:570
压缩以后的字节码大小:140
2:所有页面*。jsp全部压缩
只要是输出信息,只有两种方式:
Respoonse.getWriter()..输出信息 - 字符流。所有的jsp页面,编译后,都是通过JspWriter方式输出的信息。
但所有jsp页面都是JspWriter,而jspwriter是对PrintWriter的包装。
Response.getOutputStream() – ―― 字节流。
分析:如果要实现全站的压缩,请先实现对所有servlet中的resp.getWriter输出的数据都压缩
先实现对一个进行压缩。
第一步:书写一个类Servlet类。正常输出信息
: resp.,getWriter().print(…..);
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你好大家同学");
}
}
第二步:对这上面的这个类进行拦截-Filter,在拦截过程中包装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 {
//声明MyResponse包装类
MyResponse resp = new MyResponse((HttpServletResponse) response);
//放行时,必须要传递自己包装过的类
chain.doFilter(request, resp);
}
public void destroy() {
}
}
//实现对HttpSerlvetResponse的包装
class MyResponse extends HttpServletResponseWrapper{
public MyResponse(HttpServletResponse response) {
super(response);
}
}
第三步:为了可以压缩数据,我们必须要拦截getwriter方法
返回的不是apache的Wrtiter对象。
public class GzipFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//声明MyResponse包装类
MyResponse resp = new MyResponse((HttpServletResponse) response);
//放行时,必须要传递自己包装过的类
chain.doFilter(request, resp);
//目标类调用完成了,返回 以后读取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);
}
@Override
public PrintWriter getWriter() throws IOException {
System.err.println("有人想获取输出流");
PrintWriter out = new PrintWriter(
new OutputStreamWriter(
new FileOutputStream("d:/a/a.txt"),"UTF-8"));
return out;
}
}
第四步:修改包装类Myresponse2,让输出数据放到一个内存缓存区中
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();
}
}
第五步:全部的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();
}
return srcByte.toByteArray();
}
}
且它的配置如下:
<filter>
<filter-name>zip2</filter-name>
<filter-class>cn.itcast.filter.GzipFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>zip2</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>zip2</filter-name>
<filter-class>cn.itcast.filter.GzipFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>zip2</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
同时实现对getoutputstream和getWtier压缩
思想:
在myrespons2这个类中,对getoutputstream也要覆盖。
返回一个ServletOutputSteam的匿名对象。
实现witer(int b)方法,将数据写到bytearrayoyutpoutstream.
在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;
}