您的位置:首页 > 其它

使用gzip优化web应用(filter实现)

2012-07-23 22:25 302 查看


相关知识:

  gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能够进行压缩。

实 现:  

Tomcat 开启Gzip :

1.找到Tomcat 目录下的conf下的server.xml,并找到如下信息

Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false"redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true"

将它改成如下的形式(其实在上面代码的下面已经有了,将他们打开而已。):

<!-- Define a non-SSL HTTP/1.1 Connector on port 8080 --> <Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150"minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000"disableUploadTimeout="true" compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla,
traviata"compressableMimeType="text/html,text/xml" >

这样,就能够对html和xml进行压缩了,如果要压缩css 和 js,那么需要将

compressableMimeType=”text/html,text/xml”加入css和js:

<Connector port="8080" ......... compressableMimeType="text/html,text/xml,text/css,text/javascript" >

你甚至可以压缩图片:

compressableMimeType=”text/html,text/xml”加入css和js:
<Connector port="8080" ......... compressableMimeType="text/html,text/xml,text/css,text/javascript,image/gif,image/jpg" >

开启后重启Tomcat ,通过浏览器查看headers信息就能看到是否开启(firebug中有),如果开启了,那么transfer-encoding就会是Gzip,否则就是chunked。

在代码级别完成web应用的gzip压缩的开启:

1.Wrapper 用来包装HttpServletResponse 对象

Java代码

package com.shop.gzip;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.OutputStreamWriter;

import java.io.PrintWriter;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpServletResponseWrapper;

public class Wrapper extends HttpServletResponseWrapper {

public static final int OT_NONE = 0, OT_WRITER = 1, OT_STREAM = 2;

private int outputType = OT_NONE;

private ServletOutputStream output = null;

private PrintWriter writer = null;

private ByteArrayOutputStream buffer = null;

public Wrapper(HttpServletResponse resp) throws IOException {

super(resp);

buffer = new ByteArrayOutputStream();

}

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;

}

}

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;

}

}

public void flushBuffer() throws IOException {

if (outputType == OT_WRITER)

writer.flush();

if (outputType == OT_STREAM)

output.flush();

}

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;

}

public void write(int b) throws IOException {

buffer.write(b);

}

public byte[] toByteArray() {

return buffer.toByteArray();

}

}

}

2.过滤器

Java代码

package com.shop.gzip;

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;

public class GZipFilter implements Filter {

public void destroy() {

}

/**

* 判断浏览器是否支持GZIP

* @param request

* @return

*/

private static boolean isGZipEncoding(HttpServletRequest request){

boolean flag=false;

String encoding=request.getHeader("Accept-Encoding");

if(encoding.indexOf("gzip")!=-1){

flag=true;

}

return flag;

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

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);

}

}

public void init(FilterConfig arg0) throws ServletException {

}

private byte[] gzip(byte[] data) {

ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(10240);

GZIPOutputStream output = null;

try {

output = new GZIPOutputStream(byteOutput);

output.write(data);

} catch (IOException e) {

} finally {

try {

output.close();

} catch (IOException e) {

}

}

return byteOutput.toByteArray();

}

}

3.在web.xml中配置 GZipFilter,当我们访问应用中以.do结尾的资源的使用,服务器端就开启http gzip压缩,将压缩后的信息通过http 协议传递给浏览器.

Xml代码

<filter>

  <filter-name>ecsideExport</filter-name>

  <filter-class>com.web.servlet.GZipFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>ecsideExport</filter-name>

<url-pattern>*.do</url-pattern>

</filter-mapping>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: