zoukankan      html  css  js  c++  java
  • spring gzip 静态压缩优化

     HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览。相对 于普通的浏览过程HTML ,CSS,Javascript , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等输出的网页也能进行压缩,压缩效率惊人。 
    目前实现gzip压缩有2种办法: 

    方法一、是有的容器(服务器)提供的功能,但这个局限于特定容器。比如 apache+tomcat 或者 resin-pro   
    方法二、是 部署前手动 gzip 压缩,配合 servlet 过滤器使用,这个能实现 gzip 功能,但是降低了灵活性。


    方案一
    1、TOMCAT配置GZIP压缩:

    tomcat5.5.x配置 
    修改%TOMCAT_HOME%conf server.xml启用支持gzip压缩. 
    添加下列属性 
    compression="on" 
    compressionMinSize="2048" 
    noCompressionUserAgents="gozilla, traviata" 
    compressableMimeType="text/html,text/xml" 
    TOMCAT配置说明 
    1) compression="on" 打开压缩功能 
    2) compressionMinSize="2048" 启用压缩的输出内容大小,这里面默认为2KB 
    3) noCompressionUserAgents="gozilla, traviata" 对于以下的浏览器,不启用压缩 
    4) compressableMimeType="text/html,text/xml" 压缩类型 

    Resin容器中配置GZIP压缩方法 

    http://localhost:8080/MyProj/pdf/0.jpg 可以打开一张图片。用Httpwatch查看 
    Accept-Encoding: gzip, deflate 
    Sent    :    315 
    Received    43106 

    开始配置Resin 

    我按照这样的配置: 
    <web-app id="/" root-directory="webapps/MyProj"> 
    <filter filter-name="gzip" filter-class="com.caucho.filters.GzipFilter"> 
    <init> 
    <use-vary>true</use-vary> 
    </init> 
    </filter> 
    <filter-mapping filter-name="gzip"> 
    <url-pattern> 
    <exclude-pattern>*.jpg</exclude-pattern> 
    <include-pattern>/*</include-pattern> 
    </url-pattern> 
    </filter-mapping> 
    </web-app> 

    再测试发现不起作用!不清楚如何配置哦! 
    我再看了一下资料上面有讲说 需要resin的专业版即resin-pro 
    现在再看下我的resin :Resin-3.2.1 (built Fri, 17 Oct 2008 04:11:01 PDT) 

    果然是我的版本不一致导致的。重新从网上下载一下专业版的RESIN下来再试! 
    以下是我再测试的过程: 
    测试发现还是不行呀!我昏~~~ 不过感觉专业版与普通版在配置上面还是有点差别的 
    待续未完! 

    方案二: 
    设置Content-Encoding 

    Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档 的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept- Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。 
    压缩流 
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws IOException, ServletException { 
    OutputStream out = null; 
    String encoding = request.getHeader("Accept-Encoding");   
    if (encoding != null && encoding.indexOf("gzip") != -1){ 
    request.setHeader("Content-Encoding" , "gzip");   
    out = new GZIPOutputStream(request.getOutputStream()); 
    }  
    else if (encoding != null && encoding.indexOf("comdivss") != -1){ 
    request.setHeader("Content-Encoding" , "comdivss");   
    out = new ZIPOutputStream(request.getOutputStream()); 
    }else{   
    out = request.getOutputStream(); 



    实例:
    采用gzip servlet filter实现
    从 HTTP/1.1 开始,客户端就可以在请求头中添加
    Accept-Encoding: gzip,deflate      (可以从HTTP WATCH中查看发现确实支持)
    来向请求的服务器表明自己支持 Gzip 压缩的响应。Web 服务器则在响应头中添加
    Content-Encoding: gzip
    来向客户端表明响应体是经过 gzip 压缩的。

    程序代码如下:
    (在此非常感谢 http://tdcq.iteye.com/blog/453644 提供代码)

    具体代码如下:
    package sh.blog.util.web.filter; 
    import java.io.IOException; 
    import java.util.zip.GZIPOutputStream; 
    import javax.servlet.ServletOutputStream; 
    public class CompressedStream extends ServletOutputStream { 
    private ServletOutputStream out; 
    private GZIPOutputStream     gzip; 
    /**
    * 指定压缩缓冲流
    * @param 输出流到压缩
    @throws IOException if an error occurs with the {@link GZIPOutputStream}.
    */ 
    public CompressedStream(ServletOutputStream out) throws IOException { 
    this.out = out; 
    reset(); 


    /** @see ServletOutputStream * */ 
    public void close() throws IOException { 
    gzip.close(); 


    /** @see ServletOutputStream * */ 
    public void flush() throws IOException { 
    gzip.flush(); 


    /** @see ServletOutputStream * */ 
    public void write(byte[] b) throws IOException { 
    write(b, 0, b.length); 


    /** @see ServletOutputStream * */ 
    public void write(byte[] b, int off, int len) throws IOException { 
    gzip.write(b, off, len); 


    /** @see ServletOutputStream * */ 
    public void write(int b) throws IOException { 
    gzip.write(b); 
    }      

    public void reset() throws IOException { 
    gzip = new GZIPOutputStream(out); 






    package sh.blog.util.web.filter;
    import java.io.IOException;
    import java.io.PrintWriter;    
    import javax.servlet.ServletOutputStream;    
    import javax.servlet.http.HttpServletResponse;    
    import javax.servlet.http.HttpServletResponseWrapper;     

    public class CompressionResponse extends HttpServletResponseWrapper{
    protected HttpServletResponse response;    
    private ServletOutputStream out;    
    private CompressedStream compressedOut;  
    private PrintWriter writer;    
    protected int contentLength;    

    public CompressionResponse(HttpServletResponse response) throws IOException {    
    super(response);
    this.response = response;    
    compressedOut = new CompressedStream(response.getOutputStream()); 
    }

    public void setContentLength(int len) { 
    contentLength = len;    
    }

    public ServletOutputStream getOutputStream() throws IOException {    
    if (null == out) {    
    if (null != writer) {  
    throw new IllegalStateException("getWriter() has already been called on this response.");    
    }
    out = compressedOut;    
    }
    return out; 
    }

    public PrintWriter getWriter() throws IOException {    
    if (null == writer) {    
    if (null != out) {    
    throw new IllegalStateException("getOutputStream() has already been called on this response.");
    }
    writer = new PrintWriter(compressedOut);  
    }
    return writer;    

    }

    public void flushBuffer() {    
    try {    
    if (writer != null) {
    writer.flush();
    }else if (out != null) {  
    out.flush();    
    }

    }catch (IOException e) {  
    e.printStackTrace();    
    }
    }

    public void reset() {
    super.reset();    
    try {    
    compressedOut.reset();    
    }catch (IOException e) {  
    throw new RuntimeException(e);    
    }
    }

    public void resetBuffer() {    
    super.resetBuffer();    
    try {    
    compressedOut.reset();    
    }catch (IOException e) {  
    throw new RuntimeException(e);
    }
    }

    public void close() throws IOException {    
    compressedOut.close();    
    }



    }



    package sh.blog.util.web.filter;

    import java.io.IOException;    
    import java.util.Enumeration;    
    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 org.apache.commons.logging.Log;    
    import org.apache.commons.logging.LogFactory;    

    public class CompressionFilter implements Filter {    
    protected Log log = LogFactory.getFactory().getInstance(this.getClass().getName());    

    @SuppressWarnings("unchecked")    
    public void doFilter(ServletRequest request, ServletResponse response,    
    FilterChain chain) throws IOException, ServletException {    
    boolean compress = false;    
    if (request instanceof HttpServletRequest){    
    HttpServletRequest httpRequest = (HttpServletRequest) request;  
    Enumeration headers = httpRequest.getHeaders("Accept-Encoding");    
    while (headers.hasMoreElements()){    
    String value = (String) headers.nextElement();    
    if (value.indexOf("gzip") != -1){    
    compress = true;    
    }    
    }    
    }    

    if (compress){//如果浏览器支持则压缩    
    HttpServletResponse httpResponse = (HttpServletResponse) response; 
    httpResponse.addHeader("Content-Encoding", "gzip");    
    CompressionResponse compressionResponse= new CompressionResponse(httpResponse);    
    chain.doFilter(request, compressionResponse);    
    compressionResponse.close();    
    }    
    else{//如果浏览器不支持则不压缩    
    chain.doFilter(request, response);    
    }    

    }    

    public void init(FilterConfig config) throws ServletException {    

    }    

    public void destroy(){    
    }    

    }    
    一共有三个CLASS文件!实现GZIP压缩输出响应 

    2.1 对图片输出做压缩处理测试
    建立目录pdf里面存储图片
    第一步:不配置过滤器用HTTP WATCHE发现
    image/jpeg : 42891 bytes, 670 x 446 pixels


    第二步:配置Web.xml配置过滤器
    <filter>
    <filter-name>gzip</filter-name>
    <filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>gzip</filter-name>
    <url-pattern>/pdf/*</url-pattern>
    </filter-mapping>

    再用HTTP WATCH查看发现
    image/jpeg : 42891 bytes, gzip compressed to 42712 bytes ( 0.417 % saving ), 670 x 446 pixels
    实现了一次压缩处理输出!
    PS:我再用png格式的图片做过一次测试发现一次可以实现GZIP压缩输出
    结论:通过上面的过滤器能够实现对图片的压缩处理,提高响应速度!


    2.2 对音乐的压缩处理以MP3的输出 为测试对象

    建立目录music里面存储音乐
    第一步:不配置过滤器发现
    audio/mpeg : 9001 bytes of binary data

    第二步:配置过滤器

    <filter>
    <filter-name>gzip</filter-name>
    <filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>gzip</filter-name>
    <url-pattern>/music/*</url-pattern>    
    </filter-mapping>

    再次查看发现:
    audio/mpeg : , gzip compressed to 0 bytes ( 0 % saving )
    结论:上面的算法对音乐文件不起压缩作用。感觉这种GZIP的算法应该是不同的格式算法不一样


    2.3 对JS文件压缩输出

    第一步:不做压缩
    4864

    第二步:配置压缩
    <filter>
    <filter-name>gzip</filter-name>
    <filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>gzip</filter-name>
    <url-pattern>/scripts/*.js</url-pattern>    
    </filter-mapping>

    输出:
    application/x-javascript : 4636 bytes, gzip compressed to 69 bytes ( 98.5 % saving )

    查看发现JS的压缩是相当高的了!
    结论:将JS存入指定的目录然后直接对此目录做GZIP压缩输出。可以看到效果是显著的!
    通过做GZIP压缩输出之后可以减少网络带宽流量从而加快下载速度!



    2.4 对CSS文件压缩输出

    第一步:没有压缩输出
    text/css : 413 bytes

    第二步:压缩

    配置:
    <filter>
    <filter-name>gzip</filter-name>
    <filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>gzip</filter-name>
    <url-pattern>/scripts/*.js</url-pattern>    
    <url-pattern>/style/*.css</url-pattern>
    </filter-mapping>
    结果:
    text/css : 413 bytes, gzip compressed to 101 bytes ( 75.5 % saving )
    结论:对CSS的压缩效果也是非常明显的哦!

    2.5 对HTML页面压缩输出

    第一步:不压缩
    text/html : 2272 bytes

    第二步;压缩
    <filter>
    <filter-name>gzip</filter-name>
    <filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>gzip</filter-name>
    <url-pattern>/scripts/*.js</url-pattern>    
    <url-pattern>/style/*.css</url-pattern>
    <url-pattern>*.html</url-pattern>
    </filter-mapping>
    结果:
    text/html : 2272 bytes, gzip compressed to 240 bytes ( 89.4 % saving )

    结论:对HTML的压缩效果也是非常明显的哦!

    2.6 对JSP页面的压缩
    第一步:未做压缩
    text/html; charset=iso-8859-1 : 1008 bytes

    第二步:压缩输出
    <filter>
    <filter-name>gzip</filter-name>
    <filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>gzip</filter-name>
    <url-pattern>/scripts/*.js</url-pattern>    
    <url-pattern>/style/*.css</url-pattern>
    <url-pattern>*.html</url-pattern>
    <url-pattern>*.jsp</url-pattern>
    </filter-mapping>

    结果:页面 无输出!

    结论:
    以上的算法可以应用于 图片、HTML、CSS、JS的GZIP压缩输出。对于JSP页面无效!

    应用:

    将来可以在站点中编写此类过滤器,将页面内容尽可能地做GZIP输出提高下载的速度

  • 相关阅读:
    黄聪:PowerPoint设计编辑动画的时候图层隐藏和显示问题
    黄聪:如何在Windows上安裝BeautifulSoup
    黄聪:二、如何通过URL获取其他网页源代码内容(火狐插件扩展开发教程)
    黄聪:2006 MySQL server has gone away错误,最大值溢出解决办法 mysql max_allowed_packet 查询和修改
    黄聪:解决python中文处理乱码,先要弄懂“字符”和“字节”的差别
    ExtAspNet v2.2.1
    ExtAspNet v2.3.2
    [原创]全球首款不使用ViewState的Asp.Net2.0控件库
    [原创]从程序员角度分析安徽电信HTTP劫持的无耻行径 草根的暂时胜利
    [原创]从程序员角度分析安徽电信HTTP劫持的无耻行径 – 之深度分析
  • 原文地址:https://www.cnblogs.com/ailiying/p/9132133.html
Copyright © 2011-2022 走看看