java web gzip,java web实现Gzip压缩传输
为了减少数据在网络中的传输量,从而减少传输时长,增加用户体验,浏览器大都是支持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文件,具体信息如下图所示:
再将上面我们对*.js过滤器配置解开注释,让其起到作用。然后再请求刚刚请求的JavaScript文件看一看服务器响应的文件大小是多少,具体信息如下图所示。
再看看我们后台打印的压缩前后的大小对比,如下图所示。
从以上对比信息中我们可以看到我们写的Gzip压缩过滤器起作用了,并且压缩率很高。
这是服务端的压缩,前端的JavaScript和CSS在上线时也是需要压缩的,不过前端构建工具很多,我就不在这里简绍了。
总结:现在的开发都是前后端分离,前端框架也有很多,我这次使用的就是angularJs,对于一个单一页面应用来说,ng需要加载的js文件有很多。ng的默认加载方式是在启动以后会执行angular.bootstrap()方法并挂载我们创建的相关控制器及其服务,也就是默认的加载方式是同步加载的,这时将JavaScript文件进行合并压缩还是很有必要的。
标签:
相关文章
-
无相关信息