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服务器端发出了请求后,通常情况下服务器端会将 ...
随机推荐
- vmdk虚拟机转换为OVF模板,导入esxi
VMware WorkStation安装目录下,有一个OVFTool文件夹,例如我电脑上的路径为:D:\VMware\VMware\OVFTool.通过CMD进入到命令行模式,更改到该目录下,运行如下 ...
- 编码-截取中文-去除HTML字符
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> < ...
- 每日一九度之 题目1033:继续xxx定律
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5502 解决:1351 题目描述: 当n为3时,我们在验证xxx定律的过程中会得到一个序列,3,5,8,4,2,1,将3称为关键数, ...
- ACM题目————数独
描述 数独是一种运用纸.笔进行演算的逻辑游戏.玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个3*3宫内的 数字均含1-9,不重复. 每一道合格的数独谜题都有 ...
- Unity-Animator深入系列---Foot IK
回到 Animator深入系列总目录 最近在做一个demo,遇到了角色跑动不自然的问题(注意双腿): 后来得知勾选FootIK之后Unity会智能修复这类问题: 好像这个功能还能做到斜面地形匹配,不过 ...
- C++中的const详解
const的用法,特别是用在函数后面 在普通的非 const成员函数中,this的类型是一个指向类类型的 const指针.可以改变this所指向的值,但不能改变 this所保存的地址. 在 const ...
- WebForm 发送邮箱
首先在设置发件邮箱的SMTP服务,以新浪邮箱为例:设置区----客户端pop/imap/smtp----"POP3/SMTP服务"和"IMAP4服务/SMTP服务&quo ...
- cetos6.5安装Tomcat
一. 下载Tomcat 官网下载Tomcat tar.gz文件 二. 解压tar.gz文件 tar -zxvf tomcat.tar.gz 三. 在catalina.sh最上面添加一下内容 expo ...
- bouncycastle创建csr
public static void main(String[] args) { String subjectDN = "CN=duwenlei"; String algorith ...
- C堆栈
C堆栈实现的表达式求值 //Luangeng #include<stdio.h> #include<conio.h> #include<windows.h> #de ...