java web实现Gzip压缩传输
来源:互联网 发布:彩票预测算法 编辑:程序博客网 时间:2024/05/01 11:08
为了减少数据在网络中的传输量,从而减少传输时长,增加用户体验,浏览器大都是支持Gzip压缩技术的。http的请求头 Accept-Encoding:gzip, deflate
就表示这次请求可以接受Gzip压缩后的数据,但是这只表示客户端接受的数据可以是压缩数据,服务端具体要怎么实现压缩呢?我们就从代码层面讲解一下服务端实现压缩后的数据传输。
第一步、将响应对象HttpServletResponse
包装为我们自己继承HttpServletResponseWrapper
的MyResponse
对象,MyResponse
类会重写父类的getWriter()
方法,在getWriter()
方法内我们可以将响应数据缓存到PrintWriter
中, 然后对外提供一个获取缓存在PrintWriter
中数据的方法getBytes()
。
第二部、包装完HttpServletResponse
对象后就需要创建一个过滤器GzipFilter
来过滤我们需要压缩的请求数据了,在执行chain.doFilter()
方法前我们需要将HttpServletResponse
包装为我们自己的MyResponse
对象,然后执行doFilter()
方法。然后再取得我们第一步缓存的响应数据,并将数据进行GZIPOutputStream
压缩,最后将压缩后的数据返回给客户端。
第三部、配置需要过滤的请求类型,即配置过滤路径。
具体代码如下:
一、包装响应对象HttpServletResponse
package com.qbian.gzip;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.io.UnsupportedEncodingException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServletResponseWrapper;public class MyResponse extends HttpServletResponseWrapper{ private ByteArrayOutputStream bytes = new ByteArrayOutputStream(); private HttpServletResponse response; private PrintWriter pwrite; public MyResponse(HttpServletResponse response) { super(response); this.response = response; } @Override public ServletOutputStream getOutputStream() throws IOException { return new MyServletOutputStream(bytes); // 将数据写到 byte 中 } /** * 重写父类的 getWriter() 方法,将响应数据缓存在 PrintWriter 中 */ @Override public PrintWriter getWriter() throws IOException { try{ pwrite = new PrintWriter(new OutputStreamWriter(bytes, "utf-8")); } catch(UnsupportedEncodingException e) { e.printStackTrace(); } return pwrite; } /** * 获取缓存在 PrintWriter 中的响应数据 * @return */ public byte[] getBytes() { if(null != pwrite) { pwrite.close(); return bytes.toByteArray(); } if(null != bytes) { try { bytes.flush(); } catch(IOException e) { e.printStackTrace(); } } return bytes.toByteArray(); } class MyServletOutputStream extends ServletOutputStream { private ByteArrayOutputStream ostream ; public MyServletOutputStream(ByteArrayOutputStream ostream) { this.ostream = ostream; } @Override public void write(int b) throws IOException { ostream.write(b); // 将数据写到 stream 中 } }}
二、创建过滤器 GzipFilter
package com.qbian.filter;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.zip.GZIPOutputStream;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;import com.qbian.gzip.MyResponse;public class GzipFilter implements Filter{ @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; MyResponse mResp = new MyResponse(resp); // 包装响应对象 resp 并缓存响应数据 chain.doFilter(req, mResp); byte[] bytes = mResp.getBytes(); // 获取缓存的响应数据 System.out.println("压缩前大小:" + bytes.length); ByteArrayOutputStream bout = new ByteArrayOutputStream(); GZIPOutputStream gzipOut = new GZIPOutputStream(bout); // 创建 GZIPOutputStream 对象 gzipOut.write(bytes); // 将响应的数据写到 Gzip 压缩流中 gzipOut.close(); // 将数据刷新到 bout 字节流数组 byte[] bts = bout.toByteArray(); System.out.println("压缩后大小:" + bts.length); resp.setHeader("Content-Encoding", "gzip"); // 设置响应头信息 resp.getOutputStream().write(bts); // 将压缩数据响应给客户端 } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("+++启动压缩。"); }}
三、在 web.xml 中配置需要压缩的请求路径
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>demo</display-name> <!-- Gzip 过滤器配置 --> <filter> <filter-name>gzipF</filter-name> <filter-class>com.qbian.filter.GzipFilter</filter-class> </filter> <!-- Gzip for JavaScript --> <filter-mapping> <filter-name>gzipF</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <!-- Gzip for HTML --> <filter-mapping> <filter-name>gzipF</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <!-- Gzip for CSS --> <filter-mapping> <filter-name>gzipF</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping></web-app>
最后我们可以对比下看看压缩的效果,将 web.xml 中的
<filter-mapping> <filter-name>gzipF</filter-name> <url-pattern>*.js</url-pattern></filter-mapping>
注释掉,然后我们请求服务器一个JavaScript文件,具体信息如下图所示:
再将上面我们对*.js过滤器配置解开注释,让其起到作用。然后再请求刚刚请求的JavaScript文件看一看服务器响应的文件大小是多少,具体信息如下图所示。
再看看我们后台打印的压缩前后的大小对比,如下图所示。
从以上对比信息中我们可以看到我们写的Gzip压缩过滤器起作用了,并且压缩率很高。
这是服务端的压缩,前端的JavaScript
和CSS
在上线时也是需要压缩的,不过前端构建工具很多,我就不在这里简绍了。
总结:现在的开发都是前后端分离,前端框架也有很多,我这次使用的就是angularJs
,对于一个单一页面应用来说,ng需要加载的js文件有很多。ng的默认加载方式是在启动以后会执行angular.bootstrap()
方法并挂载我们创建的相关控制器及其服务,也就是默认的加载方式是同步加载的,这时将JavaScript
文件进行合并压缩还是很有必要的。
- java web实现Gzip压缩传输
- java web实现Gzip压缩传输
- Java实现GZIP压缩
- 开启gzip压缩传输
- Web系统使用Gzip进行文件压缩传输
- ext_js使用GZIP压缩传输
- Java实现Gzip的压缩和解压
- web gzip压缩
- 【spring】通过GZIP压缩提高网络传输效率(可以实现任何资源的gzip压缩、包括AJAX)
- 通过GZIP压缩提高网络传输效率(可以实现任何资源的gzip压缩、包括AJAX)
- 【spring】通过GZIP压缩提高网络传输效率(可以实现任何资源的gzip压缩、包括AJAX)
- Servlet/Jsp实现发送压缩Web页面 Gzip技术
- Java 高性能Web 开发(5)-GZIP 压缩
- java 文件压缩 GZIP
- java GZIP 压缩数据
- java gzip 压缩字符串
- JAVA压缩Gzip
- java gzip 内存压缩
- 导入名字为xx的项目,结果到了Eclipse里面名字变成了oo
- Java中的char类型
- android中你所不知道的高效的ArrayMap
- TCP连接的建立和释放
- 使用网店复制工具的注意事项及操作流程
- java web实现Gzip压缩传输
- CocoaPods安装和使用教程
- js 将Date 日期对象转换成时间戳
- ArrayList,LinkedList,Vector,Stack之间的区别
- lingux初学<习题七>如何使用快捷键调用历史命令!
- GAN:生成式对抗网络介绍和其优缺点以及研究现状
- hashtree处理哈希冲突的数据结构
- 继承的相关知识以及多态的概念及理解
- 在App中跳转到AppStore下载应用