首页 > 学院 > 开发设计 > 正文

通过GZIP优化性能

2019-11-06 08:11:46
字体:
来源:转载
供稿:网友

              原创文章,转载请注明

              gzip为一种压缩技术,在网络http传输中得到应用。gzip需要web容器,浏览器的支持。

              看一下效果

              压缩前:

              

              压缩后:

 

             这里的时间不需要纠结,开发环境在本机,这里的性能损耗主要在cpu上,也就是压缩时消耗的cpu,而且本机还跑了其他东西,不同时刻的环境不太一样。

      1、tomcat配置

               tomcat中使用gzip需要进行配置,在server.xml中,在Connector标签中加入如下属性

              

comPRession="on"compressionMinSize="2048"noCompressionUserAgents="gozilla,traviata"compressableMimeType="text/html,text/CSS.text/javascript"               compression:指定是否开启压缩

               compressionMinSize:表示小于该值进行压缩,单位为Byte

               noCompressionUserAgents:表示不进行压缩的浏览器

               compressableMimeType:表示哪些格式的文件需要被压缩

               注意:图片不要进行压缩,因为图片完全可以在项目开发中使用压缩后的图片。这样避免了压缩对于CPU的消耗

      2、代码

              除了进行tomcat配置之外,还需要对请求写一个filter进行压缩。

        2.1、GZIPOutputStream

             主要是通过该类进行压缩,它由java.util.zip包提供

        2.2、ServletResponse、HttpServletResponse、ServletResponseWrapper、HttpServletResponseWrapper、WrappedOutputStream

              需要继承HttpServletResponseWrapper,复写其中的getWriter,getOutputStream方法从而获得响应数据,然后就可以调用gzipOutputStream进行压缩。

              这里顺道说一下这几个类的关系

               ServletResponse为最基本的接口,表示response。

               HttpServletResponse扩展了ServletRespones,表示http协议下的response

               ServletResponseWrapper实现了ServletResponse

               HttpServletResponseWrapper实现了HttpServletResponse

               所以我们平时用的HttpServletResponse默认的实现为HttpServletResponseWrapper,struts2似乎在这之上又包装了一层。

               WrappedOutputStream:在我们调用getOutputStream方法时,会通过该接口的write方法输出byte

        2.3思路

              思路很清晰了,通过继承HttpServletResponseWrapper重写getWriter,getOutputStream获得响应数据,在stream的输出时,需要通过WrappedOutputStream的write方法输出byte。最后把输出的byte通过gzipOutputStream进行压缩

              来看一个实现代码

package com.zs.vehicle.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.ServletOutputStream;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.zs.vehicle.utils.Wrapper;public class GZipFilter implements Filter{	@Override	public void destroy() {		// TODO Auto-generated method stub			}	@Override	public void doFilter(ServletRequest request, ServletResponse response,			FilterChain chain) throws IOException, ServletException {		// TODO Auto-generated method stub		HttpServletResponse resp=(HttpServletResponse) response;		HttpServletRequest req=(HttpServletRequest) request;		if(isGZipEncoding(req)){			Wrapper wrapper=new Wrapper(resp);			chain.doFilter(request, wrapper);			byte[] gzipData=gzip(wrapper.getResponseData());			resp.addHeader("Content-Encoding", "gzip");			resp.setContentLength(gzipData.length);			ServletOutputStream output=response.getOutputStream();			output.write(gzipData);			output.flush();		}else{			chain.doFilter(request, response);		}	}	@Override	public void init(FilterConfig arg0) throws ServletException {		// TODO Auto-generated method stub	}	private static boolean isGZipEncoding(HttpServletRequest request){		boolean flag=false;		String encoding=request.getHeader("Accept-Encoding");		if(encoding.indexOf("gzip")!=-1){			flag=true;		}		return flag;	}		private byte[] gzip(byte[] data){		ByteArrayOutputStream byteOutput=new ByteArrayOutputStream(10240);		GZIPOutputStream output=null;		try{			output=new GZIPOutputStream(byteOutput);			output.write(data);		}catch(Exception e){			e.printStackTrace();		}finally{			try{				output.close();			}catch(Exception e){				e.printStackTrace();			}		}		return byteOutput.toByteArray();	}	}
package com.zs.vehicle.utils;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.PrintWriter;import javax.servlet.ServletOutputStream;import javax.servlet.WriteListener;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServletResponseWrapper;public class Wrapper extends HttpServletResponseWrapper{		public static final int OT_NONE=0;	public static final int OT_WRITER=1;	public static final int OT_STREAM=2;	private int outputType=OT_NONE;	private ServletOutputStream output=null;	private PrintWriter writer=null;	private ByteArrayOutputStream buffer=null;	public Wrapper(HttpServletResponse response) {		super(response);		buffer=new ByteArrayOutputStream();	}	@Override	public PrintWriter getWriter() throws IOException{		if(outputType==OT_STREAM)			throw new IllegalStateException();		else if(outputType==OT_WRITER)			return writer;		else{			outputType=OT_WRITER;			writer=new PrintWriter(new OutputStreamWriter(buffer,getCharacterEncoding()));			return writer;		}	}		@Override	public ServletOutputStream getOutputStream() throws IOException{		if(outputType==OT_WRITER)			throw new IllegalStateException();		else if(outputType==OT_STREAM)			return output;		else{			outputType=OT_STREAM;			output=new WrappedOutputStream(buffer);			return output;		}	}		@Override	public void flushBuffer() throws IOException{		if(outputType==OT_WRITER)			writer.flush();		if(outputType==OT_STREAM)			output.flush();	}		@Override	public void reset(){		outputType=OT_NONE;		buffer.reset();	}		public byte[] getResponseData() throws IOException{		flushBuffer();		return buffer.toByteArray();	}		class WrappedOutputStream extends ServletOutputStream{		private ByteArrayOutputStream buffer;				public WrappedOutputStream(ByteArrayOutputStream buffer){			this.buffer=buffer;		}				@Override		public void write(int b) throws IOException {			buffer.write(b);		}				public byte[] toByteArray(){			return buffer.toByteArray();		}		@Override		public boolean isReady() {			// TODO Auto-generated method stub			return true;		}		@Override		public void setWriteListener(WriteListener listener) {			// TODO Auto-generated method stub					}			}	}

      3、spring-boot

              对于spring-boot来说,由于其内嵌了web容器,那么它的行为是怎样的呢。

              spring-boot的web容器是默认开启了gzip压缩的,而且不会对图片进行压缩。


上一篇:关于const的小结

下一篇:install numpy

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表