思路:

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>

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

浏览器输出(显示响应报文)

response压缩响应的更多相关文章

  1. response (响应对象)

    一.response响应过程 在去发送一个请求时, 会找到tomcat引擎 引擎会找到对应的web应用,并且会创建request对象和response对象 找到应用后, 会执行应用的web.xml再去 ...

  2. http response压缩

    http response压缩 一.Spring boot启用Gzip压缩 application.xml新增配置: 未启用压缩时试验接口传输大小不变为61.88M,耗时1分多钟 启动压缩时试验接口传 ...

  3. JSP Filter,GZIP压缩响应流

    url:http://hi.baidu.com/xhftx/blog/item/fbc11d3012648711ebc4af59.html 关键词:JSP,Filter,Servlet,GZIP 现在 ...

  4. thttpd增加gzip压缩响应报文体功能,以减少传输数据量

    thttpd thttpd是一个非常小巧的轻量级web server,它非常非常简单,仅仅提供了HTTP/1.1和简单的CGI支持,在其官方网站上有一个与其他web server(如Apache, Z ...

  5. 通过response设置响应体

    (1)响应体设置文本 PrintWriter getWriter() 获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将res ...

  6. Filter 起航 编程式配置 压缩响应 日志过滤器

    [编程式配置]可以用web.xml配置替换 @WebListenerpublic class FilterListenerConfigurator implements ServletContextL ...

  7. Response Assertion(响应断言)

    响应断言可以让你添加匹配字符串来匹配请求和响应的各个字符串. 匹配字符串可以是1.Contains和Matches正则表达式:2.Equals和SubString文本类型,大小写敏感. Apply t ...

  8. Servlet学习(五)——通过response设置响应体及中文乱码问题

    1.响应体设置文本 PrintWriter writer=response.getWriter(); 获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲 ...

  9. response对响应的设置

    1.response对象设置响应行状态码: protected void doGet(HttpServletRequest request, HttpServletResponse response) ...

随机推荐

  1. Android闹钟设置的解决方案

    Android设置闹钟并不像IOS那样这么简单,做过Android设置闹钟的开发者都知道里面的坑有多深.下面记录一下,我解决Android闹钟设置的解决方案. 主要问题 API19开始AlarmMan ...

  2. Sql server使用Merge关键字做插入或更新操作

    Merge是关于对于两个表之间的数据进行操作的. 要使用Merge的场景比如: 数据同步 数据转换 基于源表对目标表做Insert,Update,Delete操作 MERGE语句的基本语法: MERG ...

  3. MVC-通过对象获取整个表单内容

    -------- 在MVC的Controller(控制器)里面定义相同的方法时,我们需要解决重载问题: 解决方案一:在参数中定义一个FormCollection类型,解决问题 [HttpSet] pu ...

  4. C++ redirect input

    #include<iostream> #include<string> #include<fstream> using namespace std; int mai ...

  5. android 使用多个接口

    今天,好久没有这么用过都忘记可以这样用了.来记录下: 一个类想要使用多个接口可以implements 接口1 , 接口2,...

  6. 最棒的10款MySQL GUI工具

    绝大多数的关系数据库都明显不同于MS Access,它们都有两个截然不同的部分:后端作为数据仓库,前端作为用于数据组件通信的用户界面.这种设计非常巧妙,它并行处理两层编程模型,将数据 层从用户界面中分 ...

  7. ContentObserver监听数据库·变化

    //短信Uri Uri smsUri = Uri.parse("content://sms"); //使用ContentReslover注册·监听器 getContentResol ...

  8. Swift微博项目--Swift中通过类名字符串创建类以及动态加载控制器的实现

    Swift中用类名字符串创建类(用到了命名空间) OC中可以直接通过类名的字符串转换成对应的类来操作,但是Swift中必须用到命名空间,也就是说Swift中通过字符串获取类的方式为NSClassFro ...

  9. 系统间通信(9)——通信管理与RMI 下篇

    接上文<架构设计:系统间通信(8)--通信管理与RMI 上篇>.之前说过,JDK中的RMI框架在JDK1.1.JDK1.2.JDK1.5.JDK1.6+几个版本中做了较大的调整.以下我们讨 ...

  10. js 时间与时间戳的转换

      一:时间转时间戳:javascript获得时间戳的方法有四种,都是通过实例化时间对象 new Date() 来进一步获取当前的时间戳 1.var timestamp1 = Date.parse(n ...