素材巴巴 > 程序开发 >

java web gzip,java web实现Gzip压缩传输

程序开发 2023-09-07 10:54:43

为了减少数据在网络中的传输量,从而减少传输时长,增加用户体验,浏览器大都是支持Gzip压缩技术的。

http的请求头Accept-Encoding:gzip, deflate 就表示这次请求可以接受Gzip压缩后的数据,但是这只表示客户端接受的数据可以是压缩数据,服务端具体要怎么实现压缩呢?我们就从代码层面讲解一下服务端实现压缩后的数据传输。

有两种方法:

1. 使用filter

2.在tomcat配置

我们为 Connector 添加了如下几个属性,他们意义分别是:

compression="on" 打开压缩功能

compressionMinSize="2048" 启用压缩的输出内容大小,这里面默认为 2KB

noCompressionUserAgents="gozilla, traviata" 对于以下的浏览器,不启用压缩

compressableMimeType="text/html,text/xml, image/png" 压缩类型

filter具体代码如下:

一、包装响应对象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 中配置需要压缩的请求路径

demo

gzipF

com.qbian.filter.GzipFilter

gzipF

*.js

gzipF

*.html

gzipF

*.css

最后我们可以对比下看看压缩的效果,将 web.xml 中的

gzipF

*.js

注释掉,然后我们请求服务器一个JavaScript文件,具体信息如下图所示:

55d7356fe82b3a4897d2535ee515a8e9.png

再将上面我们对*.js过滤器配置解开注释,让其起到作用。然后再请求刚刚请求的JavaScript文件看一看服务器响应的文件大小是多少,具体信息如下图所示。

3c1268feadfb7dc1fc8002d42dbec0dc.png

再看看我们后台打印的压缩前后的大小对比,如下图所示。

ae69d8e14df8e095da4b2d0bf1af9722.png

从以上对比信息中我们可以看到我们写的Gzip压缩过滤器起作用了,并且压缩率很高。

这是服务端的压缩,前端的JavaScript和CSS在上线时也是需要压缩的,不过前端构建工具很多,我就不在这里简绍了。

总结:现在的开发都是前后端分离,前端框架也有很多,我这次使用的就是angularJs,对于一个单一页面应用来说,ng需要加载的js文件有很多。ng的默认加载方式是在启动以后会执行angular.bootstrap()方法并挂载我们创建的相关控制器及其服务,也就是默认的加载方式是同步加载的,这时将JavaScript文件进行合并压缩还是很有必要的。


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。