JavaWeb-过滤器Filter学习(五)全站压缩

全站压缩,最大的好久就是帮客户端节省流量。
数据压缩,我们需要用到二个Java类,也就是java.util.zip 中的
类 GZIPOutputStream
此类为使用 GZIP 文件格式写入压缩数据实现流过滤器。

java.io
类 ByteArrayOutputStream
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。

我们利用GZIPOutputStream(OutputStream out) 使用默认缓冲区大小创建新的输出流。
再用write(byte[] b)将 b.length 个字节写入此输出流。
也就是把数据压缩后写入ByteArrayOutputStream。

然后通过内存流输出到客户端。

简单演示:

也就是在一个servlet这样写:

public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

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

        String str = "网页压缩数据hncuhdncu网页压缩数据hncuh数据hncuhdncu网页压缩数据hncuh数据hncuhdncu网页压缩数据hncuhdncu网页压缩数据hncuhdncu";

        System.out.println("原大小:" + str.getBytes("utf-8").length);

        // 压缩输出--把源数据压缩输出到baout内存流中
        ByteArrayOutputStream baout = new ByteArrayOutputStream();

        GZIPOutputStream gout = new GZIPOutputStream(baout);
        gout.write(str.getBytes("utf-8"));
        gout.close();

        // 从baout内存流中把压缩后的数据取出来,输出到客户端
        byte dest[] = baout.toByteArray();
        System.out.println("压缩后的大小:" + dest.length);

        //输出之前告诉客户端:我们的数据是gzip格式,然后输出
        response.setHeader("Content-Encoding", "gzip");
        response.setContentLength(dest.length);
        OutputStream out = response.getOutputStream();
        out.write(dest);
        out.close();
    }

这样可以实现压缩,但是每次我们有一个servlet就要写一大长串的代码,很臃肿,也很麻烦,毕竟代码是一样的。而且还无法压缩jsp和html字符文件。

这个时候,我们就需要用到过滤器了。只要拦截所有的servlet和jsp/html就ok。只要写一次!很方便。

全站压缩实例:

index.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>过滤器应用示例---全站压缩</title>
  </head>

  <body>
    <h2>过滤器应用示例---全站压缩</h2>
    <a href="<c:url value='/servlet/SecondServlet'/>">请求第二个servlet--用过滤器压缩输出字节流数据</a><br/><br/>
    <a href="<c:url value='/servlet/ThirdServlet'/>">请求第三个servlet--用过滤器压缩输出字符流数据</a><br/><br/>
  </body>
</html>

SecondServlet.java

package cn.hncu.servlets;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SecondServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=utf-8");
        String str = "网页压缩数据hncuhdncu网页压缩数据hncuh数据hncuhdncu网页压缩数据hncuh数据hncuhdncu网页压缩数据hncuhdncu网页压缩数据hncuhdncu";
        System.out.println("原大小:" + str.getBytes("utf-8").length);

        OutputStream out = response.getOutputStream();
        out.write(str.getBytes("utf-8"));
        //注意,虽然MyEclipse环境设置的是utf-8编码,但本句“str.getBytes()”却是以gbk方式编码---应该是Tomcat中的JVM采用的方式
    }
}

ThirdServlet.java

package cn.hncu.servlets;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ThirdServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=utf-8");
        String str="网页压缩数据hncuhdncu网页压缩数据hncuh数据hncuhdncu网页压缩数据hncuh数据hncuhdncu网页压缩数据hncuhdncu网页压缩数据hncuhdncu";
        System.out.println("原大小:"+ str.getBytes("utf-8").length);

        PrintWriter out = response.getWriter();
        //out.write(str);
        out.println(str);
        out.close();
    }

}

GzipFilter.java

package cn.hncu.filter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class GzipFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        MyResponse resp = new MyResponse((HttpServletResponse) response);
        // 用增强版的resp放行到servlet中去用(让后台把数据 写到 baout中 )

        chain.doFilter(request, resp);// 放行--让后台去写

        // 从增强版的resp的baout中(存放的是源字节数据),把数据取出来进行压缩,
        // 然后再压缩后的数据用原生的response输出到客户端
        ByteArrayOutputStream baout = resp.getBaout();
        byte bs[] = baout.toByteArray();// 源字节数据
        System.out.println("压缩前大小:" + bs.length);

        ByteArrayOutputStream baout2 = new ByteArrayOutputStream();
        GZIPOutputStream gout = new GZIPOutputStream(baout2);
        gout.write(bs);// 把数据压缩到baout中
        gout.close();

        bs = baout2.toByteArray();
        System.out.println("压缩后大小:" + bs.length);
        // 输出之前告诉客户端:我们的数据是gzip格式,然后输出
        HttpServletResponse httpResp = (HttpServletResponse) response;
        httpResp.setHeader("Content-Encoding", "gzip");
        httpResp.setContentLength(bs.length);
        OutputStream out = httpResp.getOutputStream();
        out.write(bs);

    }

    @Override
    public void destroy() {
    }

}

class MyResponse extends HttpServletResponseWrapper {
    private ByteArrayOutputStream baout = new ByteArrayOutputStream();

    public MyResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return new MyOutputStream(baout);
    }

    public ByteArrayOutputStream getBaout() {
        if(pw!=null){
            pw.flush();
            //这里很重要,如果不flush或close,不把字符流刷出去,baout中是不会有数据的.
        }
        return baout;
    }

    private PrintWriter pw;
    @Override
    public PrintWriter getWriter() throws IOException {
        pw = new PrintWriter(new OutputStreamWriter(baout, "utf-8"),true);
        return pw;
    }

}

class MyOutputStream extends ServletOutputStream {
    private ByteArrayOutputStream baout = null;

    public MyOutputStream(ByteArrayOutputStream baout) {
        this.baout = baout;
    }

    @Override
    public void write(int b) throws IOException {
        baout.write(b);
    }
}

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>

  <filter>
    <filter-name>gzip</filter-name>
    <filter-class>cn.hncu.filter.GzipFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>gzip</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <servlet>
    <servlet-name>FirstGzipServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.FirstGzipServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>SecondServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.SecondServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ThirdServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.ThirdServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>FirstGzipServlet</servlet-name>
    <url-pattern>/FirstGzipServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>SecondServlet</servlet-name>
    <url-pattern>/servlet/SecondServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ThirdServlet</servlet-name>
    <url-pattern>/servlet/ThirdServlet</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

用过滤器来做全站压缩,无论你怎么增加servlet,jsp,html,还是照原来的写,不用你增加代码,我们只要在过滤器中对你的数据进行压缩发送到前台去就可以了!!!

注意,过滤器中用了装饰模式。

完整项目源码:

https://github.com/chenhaoxiang/Java/tree/master/myGzipWeb

myGzipWeb.zip

转载请附上原文博客链接:

http://blog.csdn.net/qq_26525215

时间: 2024-09-29 08:24:07

JavaWeb-过滤器Filter学习(五)全站压缩的相关文章

JavaWeb 后端 &lt;十二&gt; 之 过滤器 filter 乱码、不缓存、脏话、标记、自动登录、全站压缩过滤器

一.过滤器是什么?有什么? 1.过滤器属于Servlet规范,从2.3版本就开始有了. 2.过滤器就是对访问的内容进行筛选(拦截).利用过滤器对请求和响应进行过滤 二.编写步骤和执行过程 1.编码步骤: a.编写一个类:实现javax.servlet.Filter接口 public class FilterDemo1 implements Filter {           public FilterDemo1(){         System.out.println("调用了默认的构造方法

⑧javaWeb之在例子中学习(过滤器Filter) 前言

Fitler(过滤器) 过滤器filter是拦截请求,并对传给请求资源的ServletRequest 或 ServletResponse 进行处理的一个对象.可以用于登录,加密和解密,会话检查,图片转换等等   过滤器执行机制图: Filter API : http://docs.oracle.com/javase/6/docs/api/ Filter详解 Filter接口的构成:       所有的Filter类都必须实现javax.servlet.Filter接口.这个接口含有3个过滤器类必

JavaWeb过滤器的运行机制理解及过滤器.监听器.拦截器-原理&amp;区别

过滤器Filter 一.过滤器的概念. Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等一些高级功能. 二.过滤器的运行机制.   没有加Filter的web项目运行机制如下:   加上Filter的web运行机制: 由此可见:Filter的作用

servlet和JSP过滤器Filter

js|servlet 或许,servlet API的2.3版本中最重要的一个新功能就是能够为servlet和JSP页面定义过滤器.过滤器提供了某些早期服务器所支持的非标准"servlet链接"的一种功能强大且标准的替代品.过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上.过滤器可附加到一个或多个servlet或JSP页面上,并且可以检查进入这些资源的请求信息.在这之后,过滤器可以作如下的选择:l 以常规的方式调用资源(即,调用servlet或JSP页面).l

AngularJS过滤器filter用法总结_AngularJS

本文实例总结了AngularJS过滤器filter用法.分享给大家供大家参考,具体如下: 引言 filter过滤器对于我们来说并不陌生,他和我们现实生活中的过滤器的意思差不多,它的作用就是接收一个输入的值,然后按照某个规则进行处理然后输出最后的结果,例如我们输入一个数字,然后我们需要得到货币形式的数据,这样我们就可以利用过滤器来实现,AngularJS中的过滤器是非常简单的,分为内置和自定义两种,下面小编就简单的给大家介绍一些. 内置过滤器 ng内置了一些过滤器,它们是:currency(货币)

JavaWeb-过滤器Filter学习(一)Filter知识点

Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息.自动登录等一些高级功能. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter.

更好的用户体验:过滤器(Filter)的搜索

最简单的搜索引擎不过是一个输入框,用户输入关键字.有的搜索引擎(例如谷歌)支持使用一些语法来控制搜索参数,例如逻辑控制:和.或.非等. 后来采用了过滤器(Filter)的搜索,给用户带来的更好的体验.用户甚至什么关键字也不输入,也可以找到需要的结果. 例如淘宝的搜索过滤器: AJAX技术的引入,给搜索过滤器带来了更好的体验.集合了AJAX技术后,用户无论是更改关键字还是过滤条件,搜索结果都根据用户输入实时变更. 应用过滤器可以不用跳转页面,节省了用户的时间,同时,可以很好地允许用户随时修正过滤条

教你如何学习五笔

五笔不一定是最好的输入法,也不一定是最快的输入法,但我肯定,五笔有着拼音无可比拟的优势,不是难学这个借口就值得放弃的.你想试试每分钟80字的感觉吗?你想知道什么是真正的盲打吗?加入我们五笔吧. 本方法一年前已经在我朋友身上试了,现在把方法写出来大家分享,也好让五笔输入法发扬光大. 首先说明的三点: 第一.这不是什么奇法,所以你还是要努力,我只是改了人们学五笔传统的错误学习方法. 第二.如果你说两天三小时换来只是学会五笔,每分钟打不到10字,每个句子有一半要问人怎样打,这样太无聊的话你也不要看下去

后台-Javaweb应用图片上传,压缩的问题

问题描述 Javaweb应用图片上传,压缩的问题 本人新手.想问问高人.我目前在做一个图片上传的功能.过程是用户上传图片,后台压缩,存储.我的问题是完成功能的思路是什么.是弄成二进制流上传到后台?传到后台怎么处理,处理好了之后是存数据库,还是存在服务器硬盘上?思路点拨一下,小弟感激不尽 解决方案 上传不用考虑,浏览器自动实现.服务器获取了文件流可以写文件也可以写数据库,建议写文件. 解决方案二: 放服务器硬盘上好像,存数据库浪费