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

简介: 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

目录
相关文章
|
4月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
278 1
|
4月前
|
存储 Oracle Java
java零基础学习者入门课程
本课程为Java零基础入门教程,涵盖环境搭建、变量、运算符、条件循环、数组及面向对象基础,每讲配示例代码与实践建议,助你循序渐进掌握核心知识,轻松迈入Java编程世界。
394 0
|
5月前
|
Java API 容器
Java基础学习day08-2
本节讲解Java方法引用与常用API,包括静态、实例、特定类型方法及构造器引用的格式与使用场景,并结合代码示例深入解析。同时介绍String和ArrayList的核心方法及其实际应用。
175 1
|
5月前
|
JavaScript Java 大数据
基于JavaWeb的销售管理系统设计系统
本系统基于Java、MySQL、Spring Boot与Vue.js技术,构建高效、可扩展的销售管理平台,实现客户、订单、数据可视化等全流程自动化管理,提升企业运营效率与决策能力。
|
4月前
|
负载均衡 Java API
grpc-java 架构学习指南
本指南系统解析 grpc-java 架构,涵盖分层设计、核心流程与源码结构,结合实战路径与调试技巧,助你从入门到精通,掌握高性能 RPC 开发精髓。
451 7
|
5月前
|
Java
Java基础学习day08-作业
本作业涵盖Java中Lambda表达式的应用,包括Runnable与Comparator接口的简化实现、自定义函数式接口NumberProcessor进行加减乘及最大值操作,以及通过IntProcessor处理整数数组,实现遍历、平方和奇偶判断等功能,强化函数式编程实践。
94 5
|
5月前
|
Java 程序员
Java基础学习day08
本节讲解Java中的代码块(静态与实例)及其作用,深入介绍内部类(成员、静态、局部及匿名)的定义与使用,并引入函数式编程思想,重点阐述Lambda表达式及其在简化匿名内部类中的应用。
172 5
|
5月前
|
Java
Java基础学习day07-作业
本作业包含六个Java编程案例:1)动物类继承与多态;2)加油卡支付系统;3)员工管理类设计;4)学生信息统计接口;5)USB设备控制;6)家电智能控制。综合运用抽象类、接口、继承、多态等面向对象技术,强化Java基础编程能力。
214 3
|
5月前
|
Java
Java基础学习day06-作业
本内容为Java基础学习作业,涵盖两个案例:一是通过Card类及其子类GoldenCard、SilverCard实现加油卡系统,体现封装与继承;二是通过Shape类及子类Circle、Rectangle演示多态与方法重写,强化面向对象编程理解。
110 1
|
5月前
|
设计模式 存储 Java
Java基础学习day07
本节讲解Java中的final关键字、单例设计模式、枚举类、抽象类与接口。涵盖常量定义、单例写法(饿汉式/懒汉式)、枚举特点及应用场景,以及抽象类与接口的使用与区别,助力掌握核心面向对象编程思想。
169 1