- 浏览: 800238 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
yuhanwm910731:
我现在需要实现复选(非级联选择)的树形下拉菜单,麻烦发给我一份 ...
extjs3.X支持树型的下拉控件 -
shine1200:
“所以咱们现在设置的虚拟路径“/message/upload/ ...
weblogic虚拟路径的配置和使用(2) -
icefireforest:
Fangrn 写道jx_dream 写道楼主,我最近在做树形下 ...
extjs3.X支持树型的下拉控件 -
cloudfile:
谢谢分享!
c++库c#调用开发时需要注意的一点 -
xuweilinbegin:
我也要一份哦:xuweilin15353@163.com,谢谢 ...
extjs3.X支持树型的下拉控件
前言:
上一篇随笔中网友 skyaspnet 问我如何压缩HTML,当时回答是推荐他使用gzip,后来想想,要是能把所有的 html,jsp(aspx)在运行前都压缩成1行未免不是一件好事啊。一般我们启动gzip都比较少对html启动gzip,因为现在的html都是动 态的,不会使用浏览器缓存,而启用gzip的话每次请求都需要压缩,会比较消耗服务器资源,对js,css启动gzip比较好是因为js,css都会使用 缓存。我个人觉得的压缩html的最大好处就是一本万利,只要写好了一次,以后所有程序都可以使用,不会增加任何额外的开发工作。
在“JS、CSS的合并、压缩、缓存管理 ”一文中说到自己写过的1个自动合并、压缩JS,CSS,并添加版本号的组件。这次把压缩 html的功能也加入到该组件中,流程很简单,就是在程序启动(contextInitialized or Application_Start)的时候扫描所有html,jsp(aspx)进行压缩。
压缩的注意事项:
实现的方式主要是用正则表达式去查找,替换。在html压缩的时候,主要要注意下面几点:
1. pre,textarea 标签里面的内容格式需要保留,不能压缩。
2. 去掉html注释的时候,有些注释是不能去掉的,比如:<!--[if IE 6]> ..... <![endif]-->
3. 压缩嵌入式js中的注释要注意,因为可能注释符号会出现在字符串中,比如: var url = "http://www.cnblogs.com"; // 前面的//不是注释
去掉JS换行符的时候,不能直接跟一下行动内容,需要有空格,考虑下面的代码:
else
return;
如果不带空格,则变成elsereturn。
4. jsp(aspx) 中很有可能会使用<% %>嵌入一些服务器代码,这个时候也需要单独处理,里面注释的处理方法跟js的一样。
源代码:
下面是java实现的源代码,也可以 猛击此处 下载该代码,相信大家都看的懂,也很容易改成net代码:
import java.io.StringReader; import java.io.StringWriter; import java.util.*; import java.util.regex.*; /******************************************* * 压缩jsp,html中的代码,去掉所有空白符、换行符 * @author bearrui(ak-47) * @version 0.1 * @date 2010-5-13 *******************************************/ public class HtmlCompressor { private static String tempPreBlock = "%%%HTMLCOMPRESS~PRE&&&"; private static String tempTextAreaBlock = "%%%HTMLCOMPRESS~TEXTAREA&&&"; private static String tempScriptBlock = "%%%HTMLCOMPRESS~SCRIPT&&&"; private static String tempStyleBlock = "%%%HTMLCOMPRESS~STYLE&&&"; private static String tempJspBlock = "%%%HTMLCOMPRESS~JSP&&&"; private static Pattern commentPattern = Pattern.compile("<!--\\s*[^\\[].*?-->", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static Pattern itsPattern = Pattern.compile(">\\s+?<", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static Pattern prePattern = Pattern.compile("<pre[^>]*?>.*?</pre>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static Pattern taPattern = Pattern.compile("<textarea[^>]*?>.*?</textarea>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static Pattern jspPattern = Pattern.compile("<%([^-@][\\w\\W]*?)%>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); // <script></script> private static Pattern scriptPattern = Pattern.compile("(?:<script\\s*>|<script type=['\"]text/javascript['\"]\\s*>)(.*?)</script>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static Pattern stylePattern = Pattern.compile("<style[^>()]*?>(.+)</style>", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); // 单行注释, private static Pattern signleCommentPattern = Pattern.compile("//.*"); // 字符串匹配 private static Pattern stringPattern = Pattern.compile("(\"[^\"\\n]*?\"|'[^'\\n]*?')"); // trim去空格和换行符 private static Pattern trimPattern = Pattern.compile("\\n\\s*",Pattern.MULTILINE); private static Pattern trimPattern2 = Pattern.compile("\\s*\\r",Pattern.MULTILINE); // 多行注释 private static Pattern multiCommentPattern = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); private static String tempSingleCommentBlock = "%%%HTMLCOMPRESS~SINGLECOMMENT&&&"; // //占位符 private static String tempMulitCommentBlock1 = "%%%HTMLCOMPRESS~MULITCOMMENT1&&&"; // /*占位符 private static String tempMulitCommentBlock2 = "%%%HTMLCOMPRESS~MULITCOMMENT2&&&"; // */占位符 public static String compress(String html) throws Exception { if(html == null || html.length() == 0) { return html; } List<String> preBlocks = new ArrayList<String>(); List<String> taBlocks = new ArrayList<String>(); List<String> scriptBlocks = new ArrayList<String>(); List<String> styleBlocks = new ArrayList<String>(); List<String> jspBlocks = new ArrayList<String>(); String result = html; //preserve inline java code Matcher jspMatcher = jspPattern.matcher(result); while(jspMatcher.find()) { jspBlocks.add(jspMatcher.group(0)); } result = jspMatcher.replaceAll(tempJspBlock); //preserve PRE tags Matcher preMatcher = prePattern.matcher(result); while(preMatcher.find()) { preBlocks.add(preMatcher.group(0)); } result = preMatcher.replaceAll(tempPreBlock); //preserve TEXTAREA tags Matcher taMatcher = taPattern.matcher(result); while(taMatcher.find()) { taBlocks.add(taMatcher.group(0)); } result = taMatcher.replaceAll(tempTextAreaBlock); //preserve SCRIPT tags Matcher scriptMatcher = scriptPattern.matcher(result); while(scriptMatcher.find()) { scriptBlocks.add(scriptMatcher.group(0)); } result = scriptMatcher.replaceAll(tempScriptBlock); // don't process inline css Matcher styleMatcher = stylePattern.matcher(result); while(styleMatcher.find()) { styleBlocks.add(styleMatcher.group(0)); } result = styleMatcher.replaceAll(tempStyleBlock); //process pure html result = processHtml(result); //process preserved blocks result = processPreBlocks(result, preBlocks); result = processTextareaBlocks(result, taBlocks); result = processScriptBlocks(result, scriptBlocks); result = processStyleBlocks(result, styleBlocks); result = processJspBlocks(result, jspBlocks); preBlocks = taBlocks = scriptBlocks = styleBlocks = jspBlocks = null; return result.trim(); } private static String processHtml(String html) { String result = html; //remove comments // if(removeComments) { result = commentPattern.matcher(result).replaceAll(""); // } //remove inter-tag spaces // if(removeIntertagSpaces) { result = itsPattern.matcher(result).replaceAll("><"); // } //remove multi whitespace characters // if(removeMultiSpaces) { result = result.replaceAll("\\s{2,}"," "); // } return result; } private static String processJspBlocks(String html, List<String> blocks){ String result = html; for(int i = 0; i < blocks.size(); i++) { blocks.set(i, compressJsp(blocks.get(i))); } //put preserved blocks back while(result.contains(tempJspBlock)) { result = result.replaceFirst(tempJspBlock, Matcher.quoteReplacement(blocks.remove(0))); } return result; } private static String processPreBlocks(String html, List<String> blocks) throws Exception { String result = html; //put preserved blocks back while(result.contains(tempPreBlock)) { result = result.replaceFirst(tempPreBlock, Matcher.quoteReplacement(blocks.remove(0))); } return result; } private static String processTextareaBlocks(String html, List<String> blocks) throws Exception { String result = html; //put preserved blocks back while(result.contains(tempTextAreaBlock)) { result = result.replaceFirst(tempTextAreaBlock, Matcher.quoteReplacement(blocks.remove(0))); } return result; } private static String processScriptBlocks(String html, List<String> blocks) throws Exception { String result = html; // if(compressJavaScript) { for(int i = 0; i < blocks.size(); i++) { blocks.set(i, compressJavaScript(blocks.get(i))); } // } //put preserved blocks back while(result.contains(tempScriptBlock)) { result = result.replaceFirst(tempScriptBlock, Matcher.quoteReplacement(blocks.remove(0))); } return result; } private static String processStyleBlocks(String html, List<String> blocks) throws Exception { String result = html; // if(compressCss) { for(int i = 0; i < blocks.size(); i++) { blocks.set(i, compressCssStyles(blocks.get(i))); } // } //put preserved blocks back while(result.contains(tempStyleBlock)) { result = result.replaceFirst(tempStyleBlock, Matcher.quoteReplacement(blocks.remove(0))); } return result; } private static String compressJsp(String source) { //check if block is not empty Matcher jspMatcher = jspPattern.matcher(source); if(jspMatcher.find()) { String result = compressJspJs(jspMatcher.group(1)); return (new StringBuilder(source.substring(0, jspMatcher.start(1))).append(result).append(source.substring(jspMatcher.end(1)))).toString(); } else { return source; } } private static String compressJavaScript(String source) { //check if block is not empty Matcher scriptMatcher = scriptPattern.matcher(source); if(scriptMatcher.find()) { String result = compressJspJs(scriptMatcher.group(1)); return (new StringBuilder(source.substring(0, scriptMatcher.start(1))).append(result).append(source.substring(scriptMatcher.end(1)))).toString(); } else { return source; } } private static String compressCssStyles(String source) { //check if block is not empty Matcher styleMatcher = stylePattern.matcher(source); if(styleMatcher.find()) { // 去掉注释,换行 String result= multiCommentPattern.matcher(styleMatcher.group(1)).replaceAll(""); result = trimPattern.matcher(result).replaceAll(""); result = trimPattern2.matcher(result).replaceAll(""); return (new StringBuilder(source.substring(0, styleMatcher.start(1))).append(result).append(source.substring(styleMatcher.end(1)))).toString(); } else { return source; } } private static String compressJspJs(String source){ String result = source; // 因注释符合有可能出现在字符串中,所以要先把字符串中的特殊符好去掉 Matcher stringMatcher = stringPattern.matcher(result); while(stringMatcher.find()){ String tmpStr = stringMatcher.group(0); if(tmpStr.indexOf("//") != -1 || tmpStr.indexOf("/*") != -1 || tmpStr.indexOf("*/") != -1){ String blockStr = tmpStr.replaceAll("//", tempSingleCommentBlock).replaceAll("/\\*", tempMulitCommentBlock1) .replaceAll("\\*/", tempMulitCommentBlock2); result = result.replace(tmpStr, blockStr); } } // 去掉注释 result = signleCommentPattern.matcher(result).replaceAll(""); result = multiCommentPattern.matcher(result).replaceAll(""); result = trimPattern2.matcher(result).replaceAll(""); result = trimPattern.matcher(result).replaceAll(" "); // 恢复替换掉的字符串 result = result.replaceAll(tempSingleCommentBlock, "//").replaceAll(tempMulitCommentBlock1, "/*") .replaceAll(tempMulitCommentBlock2, "*/"); return result; } }
使用注意事项 :
使用了上面方法后,再运行程序,是不是发现每个页面查看源代码的时候都变成1行啦,还不错吧,但是在使用的时候还是要注意一些问题:
1. 嵌入js本来想调用yuicompressor来压缩,yuicompressor压缩JS前,会先编译js是否合法,因我们嵌入的js中可能很多会用到 一些服务器端代码,比如 var now = <%=DateTime.now %> ,这样的代码会编译不通过,所以无法使用yuicompressor。
最后只能自己写压缩JS代码,自己写的比较粗燥,所以有个问题还解决,就是如果开发人员在一句js代码后面没有加分号的话,压缩成1行就很有可能出问 题。所以使用这个需要保证每条语句结束后都必须带分号。
2. 因为是在程序启动的时候压缩所有jsp(aspx),所以如果是用户请求的时候动态产生的html就无法压缩。
发表评论
-
提供IT系统运维支持、系统优化方案
2012-10-26 14:46 6提供IT系统运维支持、系统优化方案,有多个运维实施经验。 ... -
Java指定编码读写文件(UTF-8)
2010-11-30 14:00 3102有时我们需要程序动态生成jsp文件,采取系统默认的编码操作的文 ... -
was6.0发布struts2项目异常
2010-11-18 18:39 1982[10-11-18 18:31:33:609 CST] 000 ... -
利用spring提供的字符编码过滤器
2010-11-14 11:55 1964<!-- spring的字符集过滤器 --> ... -
简单的几句CSS布局口诀
2010-11-10 16:41 960简单的几句CSS布局口诀,就可以写出精简,标准的样式。 ... -
commons-email笔记
2010-11-10 14:38 1370import java.io.UnsupportedE ... -
如何解决 调用jar程序时出现 outofMemory的问题
2010-10-29 12:02 1198我们在调用 打包好的java程序时,如果程序要加载大量数据的话 ... -
GC策略的调优
2010-09-30 22:30 1617GC 策略在 G1 还没成熟的情况下,目前主要有串行、并 ... -
关于Spring和WebLogic版本兼容的一点小提示
2010-09-30 16:31 2060首先 WebLogic 的各个版本和 JDK 绑定的很紧, 或 ... -
删除WebLogic 10的缓存
2010-09-30 16:07 4636在WebLogic 10上部署了一个应用,最近作了更新并重新部 ... -
weblogic如何强制先加载web-inf/lib下的jar
2010-09-30 16:05 4779方法1: 修改WEB-INF\weblogic.xml (如 ... -
用Log4j自动生成日志
2010-09-27 13:28 1633Log4j是Apache基金会的一 ... -
java smslib发送短信
2010-09-10 10:02 1628public class SendMessage { ... -
Spring定时器的两种实现方式
2010-09-01 21:07 1453有两种流行Spring定时 ... -
使用 Commons-Email 在邮件内容中直接嵌入图片
2010-08-31 20:25 1319我们在发送邮件的时候,如果使用HTML在邮件内容中嵌入图片,& ... -
Struts2中转换Date类型的问题
2010-08-29 09:43 1334Web开发会涉及到很多类型转换的情况。我们知道,页面中的一切值 ... -
java smslib 发送短信错误信息
2010-08-25 15:02 4242org.smslib.GatewayException: GS ... -
rxtx取代javax.comm实现Java跨平台设备端口通信
2010-08-24 08:53 2158From Rxtx <!-- start conte ... -
javascript汉字转拼音代码
2010-08-22 08:21 4571使用方法(1):pinyin.go('汉字'); //例:张家 ... -
关于IE等浏览器在下载JAR文件时的,将后缀更改为zip等问题及解决方案
2010-08-03 12:19 1206httpd.conf这个文件中的mime.types上面,打开 ...
相关推荐
我个人觉得的压缩html的最大好处就是一本万利,只要写好了一次,以后所有程序都可以使用,不会增加任何额外的开发工作。 在“JS、CSS的合并、压缩、缓存管理”一文中说到自己写过的1个自动合并、压缩JS,CSS,并添加...
从HTTP服务器,性能测试,图片,html压缩等详细阐述如果构建高性能web开发
本书立足于Web前端开发的基础,介绍如何编写符合W3C规范、可维护性好且高性能的Web前端代码。 本书的主要内容和特色: 以W3C Web规范为基础展开讨论,介绍Web前端开发中的最佳实践方法及编码风格。为Web前端开发...
本书适合Web架构师、信息架构师、Web开发人员及产品经理阅读和参考。 序 前言 绪言A前端性能的重要性 绪言BHTTP概述 第1章规则1——减少HTTP请求 第2章规则2——实用内容发布网络 第3章规则3——添加Expires头 第4章...
在国外的网站普遍支持压缩的时候国内仍然没有提高对数据压缩的重视,致使网络资源白白浪费,几乎所有的ICP不提供数据压缩功能,就连web开发人员数据压缩也鲜有人知,提及数据压缩时一脸茫然。作为一个致力于网络信息...
它还提供了一些有用的功能,如代码验证、代码清理和代码压缩等,以确保生成的HTML代码符合标准并具有最佳性能。 除了基本的HTML编辑功能外,JSP网页HTML编辑器还提供了许多高级功能,如代码库、模板、片段、代码注释...
Framework7 或者叫 F7 是全功能的绑定 iOS 7 应用的... 高性能动画效果7. 炫酷的分页动画 8. 支持 iOS 7 的刷回9. 动态导航10. 非常容易自定义11. 自定义 DOM 库12. 原生滚动效果13. 下拉刷新 标签:Framework7
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...
2.web应用优化(json,sql ,web前端html,css,js压缩格式化代码,web客户端性能提升) 3.数据库性能优化,数据库参数设置,查询,数据库连接字符串优化,SQL耗时优化,SQL格式化,SQL美化 4.服务器高并发性能优化( ...
本书中的秘诀演示了开发和测试人员在进行单元测试、回归测试或探索性测试的同时,如何去检查最常见的Web安全问题。与即兴的安全评估不同的是,这些秘诀是可重复的、简洁的、系统的——可以完美地集成到你的常规测试...
Asp.net 开发企业网站 http://edu.ibeifeng.com/view-index-id-350.html专题:JavaScript 压缩、调试及性 能调优 专题:asp.net 下的工作流技术 WF4.0 专题:Excel 数据导出导入功能详解 专题:ExtJs 的图表高级应用...
ComponentOne Studio for ASP.NET Wijmo 拥有40多个不同风格的高性能且易于使用的控件,这些控件都基于常用的 Web 标准,如 AJAX、CSS、HTML5 和 jQuery 。这些控件都可作为 ASP.NET 控件、扩展和 MVC 工具进行使用...
ComponentOne Studio for ASP.NET Wijmo 拥有40多个不同风格的高性能且易于使用的控件,这些控件都基于常用的 Web 标准,如 AJAX、CSS、HTML5 和 jQuery 。这些控件都可作为 ASP.NET 控件、扩展和 MVC 工具进行使用...
Visual Web Development 2005开发ASP.NET使用小技巧 ASP.NET 2.0 异步页面原理浅析 [1] [原] 自定义通用System.Web.UI.IHierarchicalDataSource简单实现 在 ASP.NET 2.0 中创建 Web 应用程序主题 ASP.NET 2.0 中的...
最近几年,Web前端的发展非常迅速,并呈现出一片欣欣向荣的景象。但同时层出不穷的新技术又扰乱了开发者的思绪,造成了很多开发者疲于学习新技术而忽略了最基础的技术修炼,产生了浮躁的...本书立足于Web前端开发的基础
xSocket是一个轻量级的基于nio的服务器框架用于开发高性能、可扩展、多线程的服务器。该框架封装了线程处理、异步读/写等方面。 Java多线程程序死锁检查 JCarder JCarder 是一个用来查找多线程应用程序中一些潜在的...