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服务器端发出了请求后,通常情况下服务器端会将 ...
随机推荐
- Oracle之主键的创建、添加、删除操作
一.创建表的同时创建主键约束 1.1.无命名 SQL)); Table created SQL> select table_name,index_name from user_indexes w ...
- Sqoop安装及操作
一.集群环境: Hostname IP Hadoop版本 Hadoop 功能 系统 node1 192.168.1.151 0.20.0 namenode hive+sqoop rhel5.4X86 ...
- Java 使用 Redis | 菜鸟教程
入门教程: http://www.runoob.com/redis/redis-java.html 中文手册: http://redis.readthedocs.io/en/2.4/index.htm ...
- 删除ecshop云服务及授权关于官方等信息
一.删除[云服务中心] 删除/admin/cloud.php 删除/admin/templates/menu.htm中以下代码 Ajax.call('cloud.php?is_ajax=1>ac ...
- 使用 MNIST 图像识别数据集
机器学习领域中最迷人的主题之一是图像识别 (IR). 使用红外系统的示例包括使用指纹或视网膜识别的计算机登录程序和机场安全系统的扫描乘客脸寻找某种通缉名单上的个人.MNIST 数据集是可用于实验的简单 ...
- SlickGrid example 2: 按想要的风格展示列
先上效果图. 代码: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http:// ...
- Bellman-Ford 算法及其优化
Bellman-Ford 算法及其优化 转自:http://hi.baidu.com/jzlikewei/blog/item/94db7950f96f995a1038c2cd.html Bellman ...
- mysqli报错(HY000/2002)
Warning: mysqli::mysqli(): (HY000/2002): 没有那个文件或目录 解决:把localhost 换成127.0.0.1就好了.
- Redis的WEB界面管理工具phpRedisAdmin
下载地址:http://down.admin5.com/php/75024.html 官方网址:https://github.com/ErikDubbelboer/phpRedisAdmin
- git版本控制器
Git 是一个开源的分布式版本控制系统 Google用于android 源代码的管理就是Git, 它支持离线工作, 本地提交可以稍后提交到服务器上. 众多的开源项目都使用 Git 作为版本控制系统 ...