JSP Filter,GZIP压缩响应流
url:http://hi.baidu.com/xhftx/blog/item/fbc11d3012648711ebc4af59.html
关键词:JSP,Filter,Servlet,GZIP
现在主流浏览器都是支持gzip的。服务器压缩网页后进行传输,可减少传输数据的大小使用户感觉访问速度更快。当然,压缩也会消耗一部分服务器处理时间。
用Filter实现对返回信息的压缩,代码参考Tomcat examples里面的compressionFilters:
GZipStream.java
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.zip.GZIPOutputStream;
- import javax.servlet.ServletOutputStream;
- public class GZipStream extends ServletOutputStream {
- private GZIPOutputStream zipStream;
- public GZipStream(OutputStream out) throws IOException {
- zipStream = new GZIPOutputStream(out);
- }
- @Override
- public void flush() throws IOException {
- zipStream.flush();
- }
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- zipStream.write(b, off, len);
- }
- @Override
- public void write(byte[] b) throws IOException {
- zipStream.write(b);
- }
- @Override
- public void write(int arg0) throws IOException {
- zipStream.write(arg0);
- }
- public void finish() throws IOException {
- zipStream.finish();
- }
- public void close() throws IOException {
- zipStream.close();
- }
- }
GZipResponse.java
- import java.io.IOException;
- import java.io.OutputStreamWriter;
- import java.io.PrintWriter;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpServletResponseWrapper;
- public class GZipResponse extends HttpServletResponseWrapper {
- private GZipStream stream;
- private PrintWriter writer;
- public GZipResponse(HttpServletResponse response) throws IOException{
- super(response);
- stream=new GZipStream(response.getOutputStream());
- }
- @Override
- public ServletOutputStream getOutputStream() throws IOException {
- return stream;
- }
- @Override
- public PrintWriter getWriter() throws IOException {
- if (writer == null) {
- writer = new PrintWriter(new OutputStreamWriter(
- getOutputStream(), getCharacterEncoding()));
- }
- return writer;
- }
- public void flush() throws IOException {
- if (writer != null) {
- writer.flush();
- }
- stream.finish();
- }
- }
GZipFilter.java
- import java.io.IOException;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class GZipFilter implements Filter {
- public void destroy() {
- }
- public void init(FilterConfig fConfig) throws ServletException {
- }
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
- HttpServletRequest req=(HttpServletRequest)request;
- HttpServletResponse res=(HttpServletResponse)response;
- if(isGZipEncoding(req)){
- GZipResponse zipResponse=new GZipResponse(res);
- res.setHeader("Content-Encoding", "gzip");
- chain.doFilter(request, zipResponse);
- zipResponse.flush();
- } else {
- chain.doFilter(request, response);
- }
- }
- /**
- * 判断浏览器是否支持GZIP
- * @param request
- * @return
- */
- private static boolean isGZipEncoding(HttpServletRequest request){
- boolean flag=false;
- String encoding=request.getHeader("Accept-Encoding");
- ){
- flag=true;
- }
- return flag;
- }
- }
web.xml配置
- <filter>
- <description>
- </description>
- <display-name>GZipFilter</display-name>
- <filter-name>GZipFilter</filter-name>
- <filter-class>GZipFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>GZipFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
这个配置是对所有的资源都进行压缩传输,对于图片,flash等本身已经压缩过的文件就没有必要再进行压缩了,可以根据自己的需要更改<url-pattern>已提高WEB访问速度。
tomcat自带源码剖析:
url:http://hi.baidu.com/springfieldx/blog/item/9faa88dfd5760414495403b6.html
在响应请求的时候对response进行封装,替换他的输出流为 GZipOutputStream 压缩输出流
- package compressionFilters;
- import java.io.IOException;
- import java.util.zip.GZIPOutputStream;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletResponse;
- public class CompressionResponseStream extends ServletOutputStream {
- //是否启用压缩的临界值
- ;
- //临时容纳写入的数据缓冲区
- protected byte[] buffer = null;
- //缓冲区实际写入的数据量
- ;
- protected GZIPOutputStream gzipstream = null;
- //当前流对象是否处于关闭状态
- protected boolean closed = false;
- ;
- //用于返回数据的 Response对象
- protected HttpServletResponse response = null;
- protected ServletOutputStream output = null;
- public CompressionResponseStream(HttpServletResponse response) throws IOException{
- super();
- closed = false;
- this.response = response;
- this.output = response.getOutputStream();
- }
- //设置启用压缩的临界值,并初始化输出缓冲区
- public void setBuffer(int threshold){
- compressThreshold = threshold;
- buffer = new byte[threshold];
- }
- /**
- * 关闭流对象
- */
- public void close() throws IOException{
- if(closed){
- throw new IOException("This output stream has already been closed");
- }
- //如果当前启用的是压缩流,用压缩流刷新缓冲区
- if(gzipstream != null){
- flushToGZip();
- gzipstream.close();
- gzipstream = null;
- }else{
- //如果未开启压缩,则用response的默认输出流刷新缓冲区
- ){
- , bufferCount);
- ;
- }
- }
- }
- /**
- * 刷新输出缓冲区
- */
- public void flush() throws IOException{
- if(closed){
- throw new IOException("Cannot flush a closed output stream");
- }
- if(gzipstream != null){
- gzipstream.flush();
- }
- }
- public void write(int b) throws IOException {
- if(closed){
- throw new IOException("Cannot write to a closed output stream");
- }
- //如果数据超出了缓冲区(启用压缩的临界值),则启用压缩模式
- if(bufferCount >= buffer.length){
- flushToGZip();
- }
- //如果没有超出缓冲区,则将数据写入缓冲区
- buffer[bufferCount++] = (byte)b;
- }
- public void write(byte[] b,int off,int len) throws IOException{
- if(closed){
- throw new IOException("Cannot write to a closed output stream");
- }
- ){
- return;
- }
- //如果缓冲区能容纳这些数据则写入缓冲区
- if(len <= buffer.length - bufferCount){
- System.arraycopy(b, off, buffer, bufferCount, len);
- bufferCount += len;
- return;
- }
- //如果缓冲区剩余空间不住足,则开启压缩流对象
- flushToGZip();
- //如果清空后的缓冲区能够容纳传送过来的数据,则将数据写入缓冲区
- if(len <= buffer.length - bufferCount){
- System.arraycopy(b, off, buffer, bufferCount, len);
- bufferCount += len;
- return;
- }
- //如果缓冲区不能容纳传送进来的数据,则直接将数据写入压缩流对象
- writeToGZip(b, off, len);
- }
- //刷新压缩流对象的缓冲区
- public void flushToGZip() throws IOException{
- ){
- , bufferCount);
- ;
- }
- }
- public void writeToGZip(byte b[],int off,int len)throws IOException{
- //如果压缩流对象为空,这里初始化它
- if(gzipstream == null){
- response.addHeader("Content-Encoding", "gzip");
- gzipstream = new GZIPOutputStream(output);
- }
- //将数据听过压缩流对象输出到response的输出流
- gzipstream.write(b,off,len);
- }
- public boolean closed(){
- return closed;
- }
- }
- package compressionFilters;
- import java.io.IOException;
- import java.util.zip.GZIPOutputStream;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletResponse;
- public class CompressionResponseStream extends ServletOutputStream {
- //是否启用压缩的临界值
- ;
- //临时容纳写入的数据缓冲区
- protected byte[] buffer = null;
- //缓冲区实际写入的数据量
- ;
- protected GZIPOutputStream gzipstream = null;
- //当前流对象是否处于关闭状态
- protected boolean closed = false;
- ;
- //用于返回数据的 Response对象
- protected HttpServletResponse response = null;
- protected ServletOutputStream output = null;
- public CompressionResponseStream(HttpServletResponse response) throws IOException{
- super();
- closed = false;
- this.response = response;
- this.output = response.getOutputStream();
- }
- //设置启用压缩的临界值,并初始化输出缓冲区
- public void setBuffer(int threshold){
- compressThreshold = threshold;
- buffer = new byte[threshold];
- }
- /**
- * 关闭流对象
- */
- public void close() throws IOException{
- if(closed){
- throw new IOException("This output stream has already been closed");
- }
- //如果当前启用的是压缩流,用压缩流刷新缓冲区
- if(gzipstream != null){
- flushToGZip();
- gzipstream.close();
- gzipstream = null;
- }else{
- //如果未开启压缩,则用response的默认输出流刷新缓冲区
- ){
- , bufferCount);
- ;
- }
- }
- }
- /**
- * 刷新输出缓冲区
- */
- public void flush() throws IOException{
- if(closed){
- throw new IOException("Cannot flush a closed output stream");
- }
- if(gzipstream != null){
- gzipstream.flush();
- }
- }
- public void write(int b) throws IOException {
- if(closed){
- throw new IOException("Cannot write to a closed output stream");
- }
- //如果数据超出了缓冲区(启用压缩的临界值),则启用压缩模式
- if(bufferCount >= buffer.length){
- flushToGZip();
- }
- //如果没有超出缓冲区,则将数据写入缓冲区
- buffer[bufferCount++] = (byte)b;
- }
- public void write(byte[] b,int off,int len) throws IOException{
- if(closed){
- throw new IOException("Cannot write to a closed output stream");
- }
- ){
- return;
- }
- //如果缓冲区能容纳这些数据则写入缓冲区
- if(len <= buffer.length - bufferCount){
- System.arraycopy(b, off, buffer, bufferCount, len);
- bufferCount += len;
- return;
- }
- //如果缓冲区剩余空间不住足,则开启压缩流对象
- flushToGZip();
- //如果清空后的缓冲区能够容纳传送过来的数据,则将数据写入缓冲区
- if(len <= buffer.length - bufferCount){
- System.arraycopy(b, off, buffer, bufferCount, len);
- bufferCount += len;
- return;
- }
- //如果缓冲区不能容纳传送进来的数据,则直接将数据写入压缩流对象
- writeToGZip(b, off, len);
- }
- //刷新压缩流对象的缓冲区
- public void flushToGZip() throws IOException{
- ){
- , bufferCount);
- ;
- }
- }
- public void writeToGZip(byte b[],int off,int len)throws IOException{
- //如果压缩流对象为空,这里初始化它
- if(gzipstream == null){
- response.addHeader("Content-Encoding", "gzip");
- gzipstream = new GZIPOutputStream(output);
- }
- //将数据听过压缩流对象输出到response的输出流
- gzipstream.write(b,off,len);
- }
- public boolean closed(){
- return closed;
- }
- }
- package compressionFilters;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.io.OutputStreamWriter;
- import java.io.PrintWriter;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpServletResponseWrapper;
- public class CompressionServletResponseWrapper extends
- HttpServletResponseWrapper {
- /**
- * 原始的response对象
- */
- protected HttpServletResponse origResponse = null;
- protected static final String info = "CompressionServletResponseWrapper";
- /**
- * response对象的输出流
- */
- protected ServletOutputStream stream = null;
- /**
- * response
- */
- protected PrintWriter writer = null;
- ;
- protected String contentType = null;
- public CompressionServletResponseWrapper(HttpServletResponse response) {
- super(response);
- origResponse = response;
- }
- /**
- * 设置实体类型
- */
- public void setContentType(String contentType){
- this.contentType = contentType;
- origResponse.setContentType(contentType);
- }
- /**
- * 设置启用压缩的临界值
- * @param threshold 临界值
- */
- public void setCompressionThreshold(int threshold){
- this.threshold = threshold;
- }
- public ServletOutputStream createOutputStream() throws IOException{
- CompressionResponseStream stream = new CompressionResponseStream(origResponse);
- stream.setBuffer(threshold);
- return stream;
- }
- //关闭输出对象
- public void finishResponse(){
- try {
- if(writer != null){
- writer.close();
- }else{
- if(stream != null){
- stream.close();
- }
- }
- } catch (IOException e) {
- }
- }
- public void flushBuffer() throws IOException{
- ((CompressionResponseStream)stream).flush();
- }
- public ServletOutputStream getOutputStream() throws IOException{
- //如果字符流打开,则抛出异常
- if(writer != null)
- throw new IllegalStateException("getWriter() has already been called for this response");
- 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 response");
- stream = createOutputStream();
- String charEnc = origResponse.getCharacterEncoding();
- if(charEnc != null){
- writer = new PrintWriter(new OutputStreamWriter(stream,charEnc));
- }else{
- writer = new PrintWriter(stream);
- }
- return writer;
- }
- private static String getCharsetFromContentType(String type){
- if(type == null){
- return null;
- }
- int semi = type.indexOf(":");
- ){
- return null;
- }
- );
- int charsetLocation = afterSemi.indexOf("charset=");
- ){
- return null;
- }else{
- );
- String encoding = afterCharset.trim();
- return encoding;
- }
- }
- }
reference:
1.http://onjava.com/pub/a/onjava/2003/11/19/filters.html
2.java filter 过滤机制详解 http://hi.baidu.com/linfengtingyu1/blog/item/e14a1af20de0505b352accda.html
3.java.servlet.Filter的应用http://yuhaining.spaces.live.com/Blog/cns!5BBD70DF0F6F839C!307.entry
4.使用filter机制来GZIP压缩网页http://www.javamilk.cn/article/notes/624.htm
JSP Filter,GZIP压缩响应流的更多相关文章
- thttpd增加gzip压缩响应报文体功能,以减少传输数据量
thttpd thttpd是一个非常小巧的轻量级web server,它非常非常简单,仅仅提供了HTTP/1.1和简单的CGI支持,在其官方网站上有一个与其他web server(如Apache, Z ...
- Android GZIP压缩IO流,优化APP数据传输(一)
我是小搬运工,今天讲解流的压缩传输 在我们安卓开发中,通常伴随着大量的数据传输,在此,楼主给出一个简单的压缩流的数据进行操作. public void GZIPCpf(String path) { / ...
- Springboot 之 Filter 实现超大响应 JSON 数据压缩
简介 项目中,请求时发送超大 json 数据外:响应时也有可能返回超大 json数据.上一篇实现了请求数据的 gzip 压缩.本篇通过 filter 实现对响应 json 数据的压缩. 先了解一下以下 ...
- 使用filter过滤GZIP压缩(二)
在代码之前,讲一下用filter实现GZIP压缩的原理: 因为GZIP压缩之后,是从服务器端传输到浏览器端,从servlet到浏览器(从jsp到浏览器),其实是response带回内容,所以我们要在f ...
- Java Web 减少网络 IO、静态资源磁盘 IO 有效的办法--响应使用 GZIP( 压缩http请求与响应gzip压缩)
(转载http://blog.csdn.net/hylclxy/article/details/7779662) 出于节约流量考虑, 客户端在向服务端发送request的时候对post数据进行gzip ...
- Springboot 之 Filter 实现 Gzip 压缩超大 json 对象
简介 在项目中,存在传递超大 json 数据的场景.直接传输超大 json 数据的话,有以下两个弊端 占用网络带宽,而有些云产品就是按照带宽来计费的,间接浪费了钱 传输数据大导致网络传输耗时较长 为了 ...
- GZIP压缩优化
使用gzip优化web应用(filter实现) 相关知识: gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户 ...
- 过滤器-->GZIP压缩
1.创建一个 可以使用GZIPOutputStream 压缩的流 package com.zh.yasuo2; import java.io.IOException; import java.util ...
- GZIP压缩提高网络传输效率
[spring]通过GZIP压缩提高网络传输效率(可以实现任何资源的gzip压缩.包括AJAX) gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将 ...
随机推荐
- Javascript中最常用的经典技巧
1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table border oncontextmenu= ...
- Andriod 字符串数组里加入字符串元素
private String[] t1 = { "姓名", "性别", "年龄", "居住地","邮箱&quo ...
- CSS选择器及其优先级
一:一些普通的选择器 <!DOCTYPE html> <html> <head lang="en"> <meta charset=&quo ...
- Entity Framework 第三篇 实体特性声明
Entity Framework中对实体的特性声明有着严格的要求 1.实体必须要有主键特性,但是如果实体没有主键特性那怎么办? public int ExecuteSqlCommand(string ...
- javascript中set与get方法详解
其中get与set的使用方法: 1.get与set是方法,因为是方法,所以可以进行判断. 2.get是得到 一般是要返回的 set 是设置 不用返回 3.如果调用对象内部的属性约定的命名方式是_a ...
- php redis(2)
[config_inc.php] <?php //APP的读账号 //$config['appServer']['servername'] = 'app.com'; $config['appSe ...
- 基于busybox和LFS的linux系统定制
自从在大学知道了Linux这玩意是可以定制的之后,一直想做出一版属于自己的Linux系统.最近工作比较闲,终于塌下心来好好学习了一下. 目前来说,我接触的定制Linux的方法主要有两种: 1. ...
- android 入门 003 (点击事件)
点击事件 有四种实现方式. 1.内部类实现方式 1.0 package cn.rfvip.clickevent; import android.app.Activity; import android ...
- 【转载】CMake 简介和 CMake 模板
转载自我的博客: CMake 简介和 CMake 模板 . 如果你用 Linux 操作系统,使用 cmake 会简单很多,可以参考一个很好的教程: CMake 入门实战 | HaHack .如果你用 ...
- HTML Meta标签中的viewport属性含义及设置
两篇文章 第1篇文章 第2篇文章 http://blog.hexu.org/archives/1947.shtml 随着高端手机(Andriod,Iphone,Ipod,WinPhone等)的盛行,移 ...