一、使用GZip压缩/解压缩文件: 1.1 Java对GZip的支持
虽然网上可以找到GZip的应用程序,但是由于是用C++编写的,且是dos命令行的方式,使用方面有一些限制,而实际上,Java也提供了GZip的支持,示例代码如下:
/** * 将数据压缩成GZip格式的数据 */ public static void compress(InputStream is, OutputStream os) } /** * GZip格式数据解压缩 */ public static void decompress(InputStream is, OutputStream os) throws Exception { } GZIPInputStream gis = new GZIPInputStream(is); int count; byte data[] = new byte[BUFFER]; while ((count = gis.read(data, 0, BUFFER)) != -1) { } gis.close(); os.write(data, 0, count); throws Exception { GZIPOutputStream gos = new GZIPOutputStream(os); int count; byte data[] = new byte[BUFFER]; while ((count = is.read(data, 0, BUFFER)) != -1) { } gos.finish(); gos.flush(); gos.close(); gos.write(data, 0, count);
1.2 用Java将文件夹中的js文件压缩
如果需要遍历某一文件夹,将其中指定格式的文件压缩成GZip格式的文件,完全可以用遍历文件夹的方式来处理。下面的代码将遍历文件夹,将其中的.js文件压缩成GZip格式文件后,并同时将后缀名更改为.gzjs(注:1.下面的代码为我自己写的,可能有某方面的不足;2.可将gzjs格式文件的默认打开方式为winrar,可以用winrar直接解压)
/** * 压缩文件夹,如是js格式,则压缩为.gzjs,如果不是原样复制! * @param folderFrom 要压缩的文件夹 * @param folderTo 目标文件夹 * @param compressSonFolder 是否压缩子文件夹 * @throws Exception */ public static void compressJsFolder(File folderFrom,File folderTo,boolean compressSonFolder) throws Exception{ File[]files=folderFrom.listFiles(); for(int i=0;i 1.3、单独的一个Servlet使用GZip 只需要加入下面的一句代码: response.setHeader(\"Content-Encoding\参考信息: 《Java压缩技术(五) GZIP相关——浏览器解析》 二、将GZip用到项目中(不建议!) 2.1创建GZip过滤器 下面的过滤器是从网上找的,功能就是在response的文件头中加入“Cntent-Encoding=gzip”。 package yupont.pf.util; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; 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; public class GzipJsFilter implements Filter { } public void init(FilterConfig config) throws ServletException { } String headersStr = config.getInitParameter(\"headers\"); String[] headers = headersStr.split(\); for (int i = 0; i < headers.length; ++i) { } String[] temp = headers[i].split(\"=\"); this.headers.put(temp[0].trim(), temp[1].trim()); } FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(\"UTF-8\"); for (Iterator it = this.headers.entrySet().iterator(); } chain.doFilter(request, response); Map.Entry entry = (Map.Entry) it.next(); response.addHeader((String) entry.getKey(), (String) entry .getValue()); public void doFilter(HttpServletRequest request, HttpServletResponse response, throws IOException, ServletException { } if (req instanceof HttpServletRequest) doFilter((HttpServletRequest) req, (HttpServletResponse) public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) public void destroy() { } Map 2.2 web.xml中添加过滤器配置信息 以项目“短信平台”为例,web.xml所在位置为:/webitem/WebContent/WEB-INF/web.xml。 (下面的这个配置信息中,gzjs为.js文件被GZip压缩后,将其后缀更改为.gzjs;而.gzjpg则为.jpg文件用GZip压缩后,将其后缀更改为的.gzjpg。) web.xml中添加如下信息: 2.3 压缩文件,并修改其引用信息 用GZip压缩需要压缩的文件,并更改其相应的后缀,并在其引用的位置修改相应的引用信息。 仍然以“短信平台”为例,如其登陆页面/webitem/WebContent/appmsn/login.htm中有如下js文件的引用 type=\"text/javascript\" 现在已将其项目中的所有js均压缩并更改后缀为.gzjs,则此处应该改为: type=\"text/javascript\" 然而,globalFunc.gzjs中也有引用其他的.js文件,如:jquery-1.4.4.min.js、utilComboBoxLoadData.js,而现在这些文件均已经被替换成了同名,但是后缀为.gzjs的文件,所以,需要把globalFunc.gzjs重新解压,修改其中相应的地方,再重新压缩。 2.4测试信息 (因为51.9挂了,所以无法连上数据库,只能测单个页面,测试页面详情:webitem项目,主页,其引用的js压缩后其后缀更改为.gzjs,其引用的jpg图片压缩后其后缀更改为.gzjpg) 测试工具:IETestv0.5.2 经初步测试,使用了gzjs、gzjpg的主页在IE5模式下报“Script error”!在IE8、IE9下图片未显示出来! 测试工具:IE9,版本号:9.0.8112.16421 经初步测试,“浏览器模式”使用IE7模式、IE8模式、IE9模式均未报错!,不过“文档模式”,只有在“Quick模式”下才不会出现排版错误! 测试工具:谷歌chrome,版本:31.0.1650.63 m 经初步测试,未发现异常。 测试工具:FireFox ,版本:26.0 经初步测试,未发现异常。 测试工具:Opera ,版本:18.0.1284.68 经初步测试,未发现异常。 测试工具:遨游, 版本:4.2.0.4000 经初步测试,未发现异常。 测试工具:360浏览器, 版本:6.2.1.200 经初步测试,未发现异常。 结论:可能会在某些较低版本的IE浏览器中显示不正常! 三、使用tk-filters 3.1 tk-filters简介 Tk-filters是我在网上搜到的一个带源码的过滤器。 实现GZip压缩的机制是:拦截response的包,并对其中的数据进行压缩,再发送出去。为了实现该功能,它自定义了一个HttpServletResponseWrapper的子类,该类使用ByteArrayOutputStream来操作数据。 public class GenericResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream output; …… public GenericResponseWrapper(HttpServletResponse response) { super(response); output = new ByteArrayOutputStream(); } public byte[] getData() { return output.toByteArray(); } …… } 在该过滤器中,首先创建了GenericResponseWrapper,再从GenericResponseWrapper中将response的数据读取出来,经过GZip压缩,并在头文件中添加gzip识别信息。 该过滤器主要代码如下:父类com.tacitknowledge.filters.GenericFilter的过滤方法: public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { doFilterInternal((HttpServletRequest) request, (HttpServletResponse) response, chain); } 子类com.tacitknowledge.filters.gzipfilter.GZIPFilter的过滤方法的实现 public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (isEnabled()) { response.addHeader(\"Vary\", ACCEPT_ENCODING); GenericResponseWrapper wrapper = new GenericResponseWrapper(response); chain.doFilter(request, wrapper); OutputStream out = response.getOutputStream(); if (!isCached(wrapper) && !isIncluded(request) && acceptsGzip(request)) { byte[] compressedData = compressData(wrapper.getData()); response.setHeader(CONTENT_ENCODING, \"gzip\"); response.setContentLength(compressedData.length); out.write(compressedData); } else { // we can't compress this data, just write it straight through out.write(wrapper.getData()); } // make sure all the data made it to the client out.flush(); out.close(); } else { chain.doFilter(request, response); } } protected byte[] compressData(byte[] data) throws IOException { // do the compression ByteArrayOutputStream compressed = new ByteArrayOutputStream(); GZIPOutputStream gzout = new GZIPOutputStream(compressed); gzout.write(data); gzout.flush(); gzout.close(); // If statistics are desired, compute them and log them out if (getBooleanConfigEntry(\"GZIPFilter.LogStats\")) { StringBuffer stats = new StringBuffer(\"\" + data.length); stats.append(\" / \" + compressed.size()); stats.append(\" / \" + (data.length - compressed.size())); if (data.length > 0) { double doubleRatio = (double) compressed.size() / (double) data.length; int ratio = (int) (doubleRatio * 100); stats.append(\" / \" + ratio + \"%\"); } else { stats.append(\" / NaN\"); } getFilterConfig().getServletContext().log( \"GZIPFilter: Original / GZip / Saved / Ratio: \" + stats); } return compressed.toByteArray(); } 3.2 tk-filter使用 一,首先,下载tk-filters-1.0.1.zip 二,解压这个tk-filters-1.0.1.zip压缩文件 ; 三,将解压后的文件tk-filters.jar放在Ext项目的WEB-INF/lib/下 四,打开解压后的文件夹tk-filters\\conf\k-filters.properties GZIPFilter.Enabled=false(默认为false,true打开GZIP压缩功能) GZIPFilter.LogStats=false(默认为false,true打开GZIP压缩功能日志,可以在后台看到压缩比例信息) CacheFilter.Enabled=false(默认为false,true打开GZIP缓存功能) 注:可以自行选择想打开的功能,再将此文件复制到Ext项目的WEB-INF/class文件夹下(我是把该配置文件放到项目目录src下面) com.tacitknowledge.filters.GenericFilter读取配置文件,具体代码如下: public abstract class GenericFilter implements Filter { private static final String CONFIG_FILE = \"tk-filters.properties\"; …… } 五,打开Ext项目的WEB-INF/web.xml文件 (因为51.9挂了,所以无法连上数据库,只能测单个页面,测试项目为enplatform,测试页为主页,tk-filter过滤器启用了对js、jpg压缩) 测试工具:IETestv0.5.2 经初步测试,使用了的主页在IE5模式下报“Script error”,更进一步导致IE5挂掉!在IE6下图片未显示出来! 测试工具:IE9,版本号:9.0.8112.16421 经初步测试,“浏览器模式”使用IE7模式、IE8模式、IE9模式均未报错!,不过“文档模式”,在“Quick模式”下会出现排版错误! 测试工具:谷歌chrome,版本:31.0.1650.63 m 经初步测试,未发现异常。 测试工具:FireFox ,版本:26.0 经初步测试,未发现异常。 测试工具:Opera ,版本:18.0.1284.68 经初步测试,未发现异常。 测试工具:遨游, 版本:4.2.0.4000 经初步测试,未发现异常。 测试工具:360浏览器, 版本:6.2.1.200 经初步测试,未发现异常。 结论:可能会在某些较低版本的IE浏览器中显示不正常! 四、配置Tomcat启用GZip压缩 配置Tomcat,启用其对GZip的支持。 修改Tomcat目录下conf/server.xml中的Connector节点: 1) compression=\"on\" 打开压缩功能 2) compressionMinSize=\"2048\" 启用压缩的输出内容大小,这里面默认为2KB 3) noCompressionUserAgents=\"gozilla, traviata\" 对于以下的浏览器,不启用压缩 4) compressableMimeType=\"text/html,text/xml\" 压缩类型 因篇幅问题不能全部显示,请点此查看更多更全内容