`
wangtong40
  • 浏览: 254071 次
  • 性别: 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

    使用ant实现zip压缩和解压缩 一

    本篇文章将深入探讨如何使用Ant实现ZIP文件的压缩和解压缩。 首先,Ant是基于XML的,因此我们需要在项目中创建一个名为`build.xml`的配置文件,这个文件包含了所有构建任务的定义。对于ZIP压缩,我们可以使用`&lt;zip&gt;...

    Javascript开发之js压缩篇.pdf

    作者提供了一个使用gzip servlet filter的示例代码,展示了如何使用gzip压缩来减少文件体积。 作者的解决方法可以分为两步:首先使用yui-compressor对js文件进行压缩混淆,然后使用gzip压缩来减少文件体积。这种...

    网络应用开发 之使用Filter实现用户自动登录功能

    Filter可以用于执行各种任务,如身份验证、日志记录、内容压缩等。在这个实验中,Filter将用于检查用户的Cookie,如果找到有效的登录信息,就自动为用户登录。 Cookie是一种小型文本文件,由服务器发送到用户的...

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

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

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

    `tk-filter` 的工作原理是通过读取请求的资源,然后使用特定的压缩算法(如GZIP或DEFLATE)对这些资源进行压缩。在Web应用的部署描述符(如web.xml)中,我们需要配置`tk-filter`,将它添加到过滤链中,设定适当的...

    java 中如何使用filter过滤器

    本文将详细介绍如何在Java中使用Filter过滤器,以及如何配置相关的配置文件,让你一目了然。 ### 1. Filter接口与生命周期 Filter是Servlet API中的一个接口,位于`javax.servlet`包下。它定义了三个关键方法: -...

    实现图片上传且具有压缩功能

    总结,本项目实现了使用JSP和Struts框架实现图片上传并压缩的功能。通过前端页面提交图片,后端Action接收并处理文件,再使用Java的图像处理API进行压缩,从而达到节省存储空间和网络资源的目的。同时,安全性的强化...

    matched_filter_脉冲压缩_matched_快速卷积_cityfce_雷达_

    同时,通过在接收端使用匹配滤波器,可以在时间上对信号进行压缩,使得在保持相同距离分辨力的前提下,可以显著提高频率分辨率,从而获取更精确的目标信息。 匹配滤波器,也称为最佳滤波器,它的传输函数与输入信号...

    matlab开发-数字脉冲压缩MATLAB的实现

    3. **滤波操作**:使用MATLAB的滤波器函数(如`filter`或`freqz`)进行滤波操作,对输入的宽带脉冲信号进行处理。 4. **脉冲压缩**:经过滤波后的信号进行积分或者累积,完成脉冲压缩。 5. **结果评估**:通过比较...

    简单使用Filter模拟Servlet中的过滤器

    这里的`myFilter`是过滤器的名称,`com.example.MyFilter`是Filter实现类的全限定名,`/somePath/*`表示所有以`/somePath/`开头的URL都将被这个过滤器拦截。 Filter的执行顺序是由它们在web.xml中的顺序决定的。...

    Web后端开发-使用Filter过滤器技术,实现访问量统计

    总结,使用Filter过滤器技术实现访问量统计,结合注解的方式,可以极大地提高开发效率和代码可读性。通过灵活地配置和扩展Filter,我们可以解决许多Web后端开发中的常见问题,提高应用程序的功能和性能。

    servlet之Filter使用范例--登陆验证

    Servlet是Java提供的一个用于扩展服务器功能的接口,而Filter则是一种动态web资源过滤机制,它允许我们在数据处理流程中进行预处理和后处理,比如登录验证、日志记录、GZIP压缩等。本篇文章将深入探讨如何使用Filter...

    Bayer格式图像压缩方法及FPGA实现

    3. **并行处理与流水线设计**:利用FPGA的多核处理能力,实现压缩算法的并行执行,以及输入/输出数据的高效管理,提高整体系统的吞吐量和响应速度。 通过上述方案,Bayer图像压缩的性能得到了显著提升,不仅压缩...

    Asp.net2.0实现压缩/解压示例源码

    `HttpResponse.Filter`可以被设置为一个压缩流,例如`GZipStream`或`DeflateStream`,这样,服务器发送到客户端的所有内容都会经过这个压缩流,实现数据的压缩。 3. **压缩文件和目录**:在服务器端实现文件和目录...

    Filter

    标题中的"Filter"一词在IT领域...如果博客中有更具体的讨论,例如Filter的高级特性、自定义Filter实现或是与其他技术的结合,那么这些都需要通过原文链接进行深入学习。如果你需要更详细的信息,建议直接访问博文链接。

    matlab图像;51 DPCM编码实现编码压缩.zip

    本压缩包文件“51 DPCM编码实现编码压缩.zip”显然是一个关于使用MATLAB实现DPCM(差分脉冲编码调制)编码的教程或实例。 DPCM编码是一种常见的数字信号压缩技术,它基于信号的连续性,通过预测当前采样值并只传输...

    matlab图像专题:52 KLT编码实现编码压缩.zip

    在MATLAB中,你可以编写函数来实现上述步骤,或者直接调用内置的`vision.KalmanFilter`或者`vision.KLTFeatureTracker`类来追踪特征点。同时,MATLAB的矩阵运算能力使得计算光流和优化过程更为高效。 4. **效率与优...

    基于Matlab实现雷达系统脉冲压缩.zip

    3. **matched_filter.m**:匹配滤波器是脉冲压缩的核心部分,该文件很可能包含了匹配滤波器的实现代码。匹配滤波器的作用是在接收端与回波信号进行卷积,达到最佳检测效果,同时压缩信号。 4. **fig5_14.m**、**fig...

Global site tag (gtag.js) - Google Analytics