`
wangtong40
  • 浏览: 249703 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用Filter实现正文压缩

阅读更多
public class CompressionResponseStream extends ServletOutputStream {

    protected int compressionThreshold = 0;// 是否启用压缩的临界值
    protected byte[] buffer = null;// 临时容纳写入的数据的缓冲区
    protected int bufferCount = 0; // 缓冲区实际写入的数据量
    protected GZIPOutputStream gzipstream = null;
    protected boolean closed = false;// 对当前流对象是否处于关闭状态
    protected int length = -1;
    protected HttpServletResponse response = null;
    protected ServletOutputStream output = null;

    public CompressionResponseStream(HttpServletResponse response)
            throws IOException {
        super();
        closed = false;
        this.response = response;
        this.output = response.getOutputStream();
    }

    protected void setBuffer(int threshold) {
        compressionThreshold = threshold;
        buffer = new byte[compressionThreshold];
    }

    public void close() throws IOException {
        if (closed) {
            throw new IOException("This output stream has already been closed");
        }
        /*
         * 根据gzipstream是否为null,就可以判断写入的内容是否达到
         * 启用压缩的临界值,因为到达临界值时,write方法会自动创建gzipstream对象
         */
        if (gzipstream != null) {
            flushToGZip();
            gzipstream.close();
            gzipstream = null;
        } else {
            if (bufferCount > 0) {
                output.write(buffer, 0, bufferCount);
                bufferCount = 0;
            }
        }

        output.close();
        closed = true;
    }

    public void flush() throws IOException {
        if (closed) {
            throw new IOException("Can't flush a closed output stream");
        }
        if (gzipstream != null) {
            gzipstream.flush();
        }
    }

    /**
     * 将buffer缓冲区中的数据写入到gzipstream中
     *
     * @throws IOException
     */
    public void flushToGZip() throws IOException {
        if (bufferCount > 0) {
            writeToGZip(buffer, 0, bufferCount);
            bufferCount = 0;
        }
    }

    @Override
    public void write(int b) throws IOException {
        if (closed) {
            throw new IOException("Can't write to a closed output stream");
        }

        /*
         * 当写入的数据达到启用压缩的临界值时, 则先将buffer缓冲区的数据写入到gzipstream对象中
         */
        if (bufferCount >= buffer.length) {
            flushToGZip();
        }
        buffer[bufferCount++] = (byte) b;
    }

    public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }

    public void write(byte[] b, int off, int len) throws IOException {
        if (closed) {
            throw new IOException("Can't write to a closed output stream");
        }
        if (len == 0) {
            return;
        }
        /*
         * 如果buffer缓冲区中剩余的空间能够容纳要写入的数据, 则先将这些数据写入到buffer缓冲区中
         */
        if (len <= (buffer.length - bufferCount)) {
            System.arraycopy(b, off, buffer, bufferCount, len);
            bufferCount += len;
            return;
        }
        /*
         * 如果buffer缓冲区剩余的空间不能容纳要写入的数据, 则先将buffer缓冲区的原有数据写入到gzipstream对象中
         */
        flushToGZip();

        /*
         * 腾空buffer缓冲区数据后,判断整个buffer缓冲区是否能够容纳要写入的数据, 如果能将这些数据写入到buffer缓冲区中
         */
        if (len <= (buffer.length - bufferCount)) {
            System.arraycopy(b, off, buffer, bufferCount, len);
            bufferCount += len;
            return;
        }
        /*
         * 如果整个buffer缓冲区的空间都不能容纳要写入的数据, 则直接将这些数据写入gzipstream中
         */
        writeToGZip(b, off, len);
    }

    /**
     * 将gzipstream对象中写入数据,如果第一次写入 则还需创建gzips实体对象
     *
     * @param b
     * @param off
     * @param len
     * @throws IOException
     */
    public void writeToGZip(byte b[], int off, int len) throws IOException {
        if (gzipstream == null) {
            response.addHeader("Content-Encoding", "gzip");
            gzipstream = new GZIPOutputStream(output);
        }
        gzipstream.write(b, off, len);
    }
}

 

public class CompressionServletResponseWrapper extends
		HttpServletResponseWrapper {

	protected HttpServletResponse origResponse = null;
	protected static final String info = "CompressionServletResponseWrapper";
	protected ServletOutputStream stream = null;
	protected PrintWriter writer = null;
	protected int threshold = 0;
	protected String contentType = null;

	public CompressionServletResponseWrapper(HttpServletResponse response) {
		super(response);
		origResponse = response;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
		origResponse.setContentType(contentType);
	}

	public void setCompressionThreshold(int threshold) {
		this.threshold = threshold;
	}

	/**
	 * 创建自定义response对象包括输出流对象
	 * 
	 * @return
	 * @throws IOException
	 */
	public ServletOutputStream createOutputStream() throws IOException {
		CompressionResponseStream stream = new CompressionResponseStream(
				origResponse);
		stream.setBuffer(threshold);
		return stream;
	}

	/**
	 * 为了防止目标Servlet没有关闭输出流对象,Filter调用该方法 以便自动关闭输出流对象
	 */
	public void finishResponse() {
		try {
			if (writer != null) {
				writer.close();
			} else {
				if (stream != null) {
					stream.close();
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	/**
	 * 覆盖flushBuffer方法
	 */
	public void flushBuffer() throws IOException {
		((CompressionResponseStream) stream).flush();
	}

	/**
	 * 覆盖getOutputStream方法
	 */
	public ServletOutputStream getOutputStream() throws IOException {
		if (writer != null) {
			throw new IllegalStateException(
					"getWriter() has already been called for this resposne");
		}
		if (stream == null) {
			stream = createOutputStream();
		}
		return stream;
	}

	public PrintWriter getWriter() throws IOException {
		if (writer != null) {
			return writer;
		}
		if (stream != null) {
			throw new IllegalStateException(
					"getOutputStream() has already been called for this resposne");
		}
		stream = createOutputStream();

		String charEnc = origResponse.getCharacterEncoding();
		if (charEnc != null) {
			writer = new PrintWriter(new OutputStreamWriter(stream, charEnc));
		} else {
			writer = new PrintWriter(stream);
		}
		return writer;
	}

}
 
public class CompressionFilter implements Filter {
	private FilterConfig config = null;
	private int minThreshold = 128;
	protected int compressionThreshold;

	public void init(FilterConfig filterConfig) throws ServletException {
		this.config = filterConfig;
		if (filterConfig != null) {
			String str = filterConfig.getInitParameter("compressionThreshold");
			if (compressionThreshold != 0 & compressionThreshold < minThreshold) {
				compressionThreshold = minThreshold;
			} else {
				// 不对响应信息的实体内容进行压缩
				compressionThreshold = 0;
			}
		} else {
			compressionThreshold = 0;
		}

	}

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		/*
		 * 不对响应信息的实体内容进行压缩
		 */
		if (compressionThreshold == 0) {
			chain.doFilter(request, response);
		}
		/*
		 * 检测客户端浏览器是否支持gzip数据压缩格式
		 */
		boolean supportCompression = false;
		if (request instanceof HttpServletRequest) {
			Enumeration<String> e = ((HttpServletRequest) request)
					.getHeaders("Accept-Encoding");
			while (e.hasMoreElements()) {
				String name = e.nextElement();
				if (name.indexOf("gzip") != -1) {
					supportCompression = true;
				}
			}
		}
		if (!supportCompression) {
			chain.doFilter(request, response);
			return;
		} else {
			if (response instanceof HttpServletResponse) {
				/*
				 * 创建自定义的Response对象
				 */
				CompressionServletResponseWrapper wrapperResponse = 
                         new CompressionServletResponseWrapper(
						(HttpServletResponse) response);
				wrapperResponse.setCompressionThreshold(compressionThreshold);
				try {
					chain.doFilter(request, wrapperResponse);
				} finally {
					wrapperResponse.finishResponse();
				}
			}
			return;
		}
	}

	public void destroy() {
		this.config = null;
	}

}
分享到:
评论

相关推荐

    通过filter实现对输出内容的压缩处理

    博文链接:https://melin.iteye.com/blog/164113

    Filter(过滤器)简介和工作原理

    * 数据压缩:可以使用 Filter 来实现数据压缩,例如压缩 HTML、CSS 和 JavaScript 文件。 Filter 是 Java EE 中的一种强大且灵活的组件,能够帮助开发人员快速实现各种功能强大且灵活的 Web 应用程序。

    web容器文件压缩 tk-filter tk-filter js,jsp,css,文件压缩包含源代码

    tk-filter js,jsp,css,文件压缩包含源代码,web容器加载filter,能够实现对于js,jsp,css等文件压缩,保证网络传输速率。

    SpringBoot整合XssFilter,Jsoup等实现请求参数的过滤,处理Xss攻击及sql注入.zip

    Springboot中会使用FilterRegistrationBean来注册Filter,Filter是Servlet规范里面的,属于容器范围,Springboot中没有web.xml,那Springboot中,不用管Filter是如何交给Ser...SpringBoot整合XssFilter,Jsoup等实现...

    java-bloomfilter:具有JSON(反)序列化和(zlib)压缩的Java Bloomfilter实现

    具有JSON(反)序列化和(zlib)压缩的Java Bloomfilter实现 您可以在此处找到兼容的PYTHON实现: : 例子: BloomFilter bf1 = new BloomFilter(1000000, 0.001); bf1.add("Alabama"); bf1.add("Illinois"); bf1...

    python-bloomfilter:带有JSON(反)序列化和(zlib)压缩的纯python bloomfilter实现

    带有JSON(反)序列化和(zlib)压缩的纯python bloomfilter实现 您可以在此处找到兼容的JAVA实现: : 例子: bf1 = BloomFilter(ideal_num_elements_n=1000000, error_rate_p=0.001) bf1.add("Alabama") bf1....

    JavaWeb Servlet中Filter过滤器的详解

     Filter过滤器,对web服务器所有web资源进行过滤,从而实现一些特殊的功能(权限访问控制、过滤敏感词汇、压缩响应信息)。Filter能够对Servlet容器的请求和响应进行检查和修改,其本身不能生成请求request和响应...

    iOS实现压缩图片上传功能

    本文实例为大家分享了iOS实现压缩图片上传功能,供大家参考,具体内容如下 #pragma mark - 打开相机 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:...

    一种面向深度包检测的DFA压缩算法

    DFA(确定性有限自动机)对于实现深度包检测(deep packet inspection,DPI)技术具有重要作用。随着深度包检测规则的不断...实验结果表明,该算法在L7-filter和Snort规则集上具有较稳定的压缩率,压缩率都在5%以下。

    论文研究-一种用于深度报文检测的DFA状态表压缩方法.pdf

    基于正则表达式进行深度报文检测...将DFA状态转换表拆分成3个表,使用run-length编码进行压缩,并对压缩方法进行了优化。采用l7-filter中几个常用应用程序的正则表达式进行测试,结果表明该方法压缩效果一般在90%以上。

    Filter.docx

    1.Filter概述 Filter也称为过滤器,可以实现对资源访问的拦截,如实现权限控制,敏感词汇过滤,压缩响应等 2.Filter原理

    C#实现页面GZip或Deflate压缩的方法

    本文实例讲述了C#实现页面GZip或Deflate压缩的方法。分享给大家供大家参考。具体分析如下: .NET Framework里 System.IO.Compression下有两个可用于页面压缩的类,GZipStream和 DeflateStream. 在页面被传输之前,...

    dshow视频捕获压缩到avi

    该代码是在pudn里下载 原代码不能捕获视频.经过改动可以实现视频捕获压缩。内带两种filter的连接方式

    SpringBoot一步配置Filter

    愈知愈知不知:你知道的越多,你不知道的越多。 引言 关于如何搭建SpringBoot工程...在使用servlet的时候,我们实现过滤器Filter可能需要三步: 1.声明一个类实现javax.servlet.Filter接口。 2.重写doFilter()方法。

    matched_filter.rar_matched_matched filter

    实现快速关机处理。输入:未压缩脉冲的宽度,散射体距离向量等。

    ehcache用法

    EHCache使用SimplePageCachingFilter类实现Filter缓存。该类继承自CachingFilter,有默认产生cache key的calculateKey()方法,该方法使用HTTP请求的URI和查询条件来组成key。也可以自己实现一个Filter,同样继承...

    图片压缩函数支持jd-aliyun-tencent-qiniu

    图片压缩函数,支持jd、aliyun、tencent、qiniu,其中实现了vue filter和指令,也可以作为纯函数使用,支持vue,react,Vanilla JS,配置可扩展,支持webp转换,图片质量、尺寸

    深入了解Java中的Filter过滤器

    Filter也称之为过滤器,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。下面我们来简单学习一下吧

Global site tag (gtag.js) - Google Analytics