装饰者模式之servlet过滤器(Filter)网页压缩

1.装饰者模式定义

动态地给一个对象添加一些额外的职责。就增加功能来说, 装饰模式相比生成子类更为灵活。
                                                                    ------《设计模式之禅》

2.通用类图:

装饰者模式之servlet过滤器(Filter)网页压缩_第1张图片

类图说明:

● Component抽象构件
Component是一个接口或者是抽象类, 就是定义我们最核心的对象, 也就是最原始的对象。

注意: 在装饰模式中, 必然有一个最基本、 最核心、 最原始的接口或抽象类充当Component抽象构件。 

● ConcreteComponent 具体构件
ConcreteComponent是最核心、 最原始、 最基本的接口或抽象类的实现, 你要装饰的就是它。  

● Decorator装饰角色
一般是一个抽象类, 做什么用呢? 实现接口或者抽象方法, 它里面可不一定有抽象的方法呀, 
在它的属性里必然有一个private变量指向Component抽象构件。 

● 具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,
 你要把你最核心的、 最原始的、 最基本的东西装饰成其他东西。

                                                                    ------《设计模式之禅》  

3.类图代码:

public abstract class Component {
//抽象的方法
    public abstract void operate();
}

public class ConcreteComponent extends Component {
//具体实现
@Override
    public void operate() {
        System.out.println("do Something");
    }
}

public abstract class Decorator extends Component {
    private Component component = null;
    //通过构造函数传递被修饰者
        public Decorator(Component _component){
        this.component = _component;
    }
    //委托给被修饰者执行
    @Override
    public void operate() {
        this.component.operate();
    }
}

public class ConcreteDecorator1 extends Decorator {
//定义被修饰者
    public ConcreteDecorator1(Component _component){
        super(_component);
}
    //定义自己的修饰方法
    private void method1(){
        System.out.println("method1 修饰");
    }
    //重写父类的Operation方法
    public void operate(){
        this.method1();
        super.operate();
    }
}

servlet过滤器之网页压缩

应用: 如今租赁的服务器有的是按照流量来节省流量,所以网页压缩技术有助于节省流量,
     并且可以提高用户的网的响应速度,大大提高了用户体验。
  • 所用技术:

    • java 的GZIPOutputStream类进行gzip压缩。
    • 通过javaweb的过滤器,对服务端发响应的数据进行压缩。
    • 装饰者模式,对已经存在的方法进行重写。
  • 分析:

    • 运用过滤器,对服务器每一次的响应的数据进行gzip压缩。
    • 在servlet中的response.getwriter().writer()向客户端发送数据,可是中间的数据无法再过滤器中截取。
    • 以上,所以需要重写response中的PrintWriter方法,将响应数据在发送到客户端之前先保存到ServletResponse的成员缓冲区中。
    • 随后在过滤器中将响应内容进行压缩,再发送给客户端。

过滤器代码

public class GIZPFilter implements Filter {

    public GIZPFilter() {

    }
    public void destroy() {

    }
    public void init(FilterConfig fConfig) throws ServletException {

    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
     throws IOException, ServletException {
        //对响应中的数据先进行编码
        req.setCharacterEncoding("utf-8");
        //对response进行装饰
        HttpServletResponse response = (HttpServletResponse) res;
        //进行包装
        MyHttpResponse myResponse = new MyHttpResponse(response);
        //放行,在servlet向缓冲区中写数据
        chain.doFilter(req, myResponse);
        //获取缓冲区中的内容
        char[] content = myResponse.getBuf().toCharArray();
        //创建缓冲区
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //进行压缩
        GZIPOutputStream gzip = new GZIPOutputStream(bos);
        //向bos2缓冲区中写入数据
        gzip.write(new String(content).getBytes());
        //刷新缓冲区
        gzip.finish();
        System.out.println("压缩后的数据大小:" + new String(bos.toByteArray()).length());
        System.out.println(new String(content));
        //设置响应体中的字体
        myResponse.setContentType("text/html;charset=utf-8");
        //设置浏览器解析格式
        myResponse.setHeader("content-encoding", "gzip");
        //向浏览器写数据
        myResponse.getOutputStream().write(bos.toByteArray());
    }
}

//重写的类
class MyHttpResponse extends HttpServletResponseWrapper {
    private HttpServletResponse response = null;
    //定义缓冲区
    private CharArrayWriter buf = new CharArrayWriter();

    public CharArrayWriter getBuf() {
        return buf;
    }

    public MyHttpResponse(HttpServletResponse response) {
        super(response);
        this.response = response;
    }
    @Override
    public PrintWriter getWriter() throws IOException {
        //创建带缓冲区的PrintWriter对象(API中可查)
        return new PrintWriter(buf);
    }
}

服务器代码:

public void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws  ServletException, IOException {
        //准备数据
        StringBuffer sb = new StringBuffer();
        for(int i=1;i<=3000;i++){
            sb.append("abcd你好");
        }
        System.out.println("压缩前的数据大小: "+sb.toString().getBytes().length);
        //这里的response已经是过滤器中定义的MyHttpResponse 类
        PrintWriter out = response.getWriter();
        out.write(sb.toString());
        //关闭并刷新缓冲区
        out.close();
    }

你可能感兴趣的:(java)