关于输出mini版HTML代码的方法
在实际开发中,我们不可避免需要优化输出的内容,使得用户体验优化的效果。
其中,在Web开发当中就有tomcat的gzip来压缩输出流,使得网络带宽压力下降,从而提升浏览器的文件下载速度。这个办法的好处是配置简单,资源较多的情况下效果明显。
但是也有缺点:
1、增加CPU的负担。故此方法不适合CPU资源紧张的服务器。
2、压缩得还不算彻底。
3、需要相应支持的浏览器。
哪怕有上面这些问题,总体上来讲,这个技术还是利大于弊。毕竟CPU便宜过带宽。
为了压缩得更加彻底,我们可以尝试在gzip的基础上,实现一个进一步的代码压缩,把所有jsp、HTML、css、js这些资源文件自动输出成mini版。这样就可以到达进一步压缩的目的。但是会加深CPU、RAM的消耗以及,这个方法是通过自行写代码实现,所以有一定的难度以及可能不够灵活。
具体实现方式是:
1、继承javax.servlet.http.HttpServletResponseWrapper来编写一个Java类。
2、创建一个专门处理资源文件输出的Filter。
3、实现一段处理字符串的逻辑。
4、Filter过滤全部的请求,并且里面要分开各种资源请求的类型来进行不同处理。
5、字符串输出。
继承HttpServletResponseWrapper的Java代码:
import java.io.CharArrayWriter; import java.io.PrintWriter; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class ResponseWrapper extends HttpServletResponseWrapper { private CharArrayWriter out; public ResponseWrapper(HttpServletResponse response) { super(response); out = new CharArrayWriter(); } public PrintWriter getWriter() { return new PrintWriter(out); } public String toString() { return getCharArrayWriter().toString(); } public CharArrayWriter getCharArrayWriter() { return out; } }
负责过滤请求并返回处理后的信息的Filter以及内部写的一些处理方法:
import java.io.IOException; 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 org.apache.commons.lang.StringUtils; import com.winsun.warpper.ResponseWrapper; /** * 专门用于对输出的内容进行格式化 * 可以起到一定的保密作用,以及优化服务器的流量带宽,但是对服务器CPU、RAM有一定的消耗 * @author Lph * @date 2015年11月27日 */ public class HTMLFilter implements Filter { //用于控制本FIlter的功能是否启动 private static boolean FILTER_SWITCH = true; public void destroy() { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { if(FILTER_SWITCH) { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; String servletPath = request.getServletPath(); String url = request.getContextPath() + servletPath; if(url.endsWith(".jsp") || url.endsWith(".action")) { ServletOutputStream outStream = servletResponse.getOutputStream(); ResponseWrapper wrapper = new ResponseWrapper(response); chain.doFilter(request, wrapper); String code = wrapper.toString(); String[] rows = code.split("\n"); StringBuffer codeBuffer = new StringBuffer(); String row = null; for(int i = 0 ; i < rows.length; i++) { row = rows[i]; row = clearTabcharacter(row); row = clearRowTheNodes(row); if(StringUtils.isBlank(row) || row.equals("\n")) { //清除空行 continue; } codeBuffer.append(row); } String result = codeBuffer.toString(); /*if(url.endsWith("css") || url.endsWith("js") || url.endsWith("map")) { System.out.println("Output Content:"); System.out.println(result); }*/ //result = clearRowsTheNodes(result); outStream.write(result.getBytes("UTF-8")); outStream.flush(); outStream.close(); } else { chain.doFilter(request, response); } } else { chain.doFilter(servletRequest, servletResponse); } } public void init(FilterConfig config) throws ServletException { String filterSwitch = config.getInitParameter("FilterSwitch"); FILTER_SWITCH = StringUtils.isBlank(filterSwitch) || filterSwitch.equals("on"); } /** * 清除字符串对象的其实制表符和结束的制表符 * @param row * @return */ public String clearTabcharacter(String row) { char[] chars = row.toCharArray(); int startIndex = -1, endIndex = -1; int i = 0; for(i = 0; i < chars.length; i++) { if(chars[i] == "\t".charAt(0) || chars[i] == " ".charAt(0)) { startIndex = i; } else { break; } } for(i = chars.length - 1; i >= 0; i--) { if(chars[i] == "\t".charAt(0) || chars[i] == " ".charAt(0)) { endIndex = i; } else { break; } } if(startIndex < 0) { return row; } else { if(endIndex < 1) { endIndex = row.length(); } return row.substring(startIndex + 1, endIndex); } } /** * 清除行注释,仅仅是判断"//" * 满足则返回空字符串。否则原样返回 * @param row 一行的内容 * @return */ public String clearRowTheNodes(String row) { if(row.startsWith("//")) { row = ""; } return row; } public String clearRowsTheNodes(String content) { StringBuffer code = new StringBuffer(); char[] chars = content.toCharArray(); boolean captureStart = false, captrueEnd = false; for(int i = 0; i < chars.length; i++) { if(i + 1 < chars.length) { if(chars[i] == "/".charAt(0) && chars[i + 1] == "*".charAt(0)) { captureStart = true; } if(chars[i] == "*".charAt(0) && chars[i + 1] == "/".charAt(0)) { captrueEnd = true; } if(captureStart == false && captrueEnd == false) { code.append(chars[i]); captureStart = false; captrueEnd = false; } } } return code.toString(); } }
- 这里仅仅是举例,没有彻底完成所以并不能完成的mini输出。
- 目前贴出来的代码仅仅支持jsp。其他资源文件还没处理。
- 支持JSP内“//”这种行注释的去除。
- 具体可以达到什么样的效果要看代码的实现。
- 自动输出迷你版在自动去除注释的情况下可以起到一定的保密作用。
- 方便更新版本,不需要每次修改文件都生成一次迷你版。
- 此方法是在jsp编译完毕之后才会进行处理,故jstl\el等情况不需要考虑
相关推荐
gufudhn 2020-06-06
lupeng 2020-11-14
sjcheck 2020-11-10
sjcheck 2020-11-03
meylovezn 2020-08-28
owhile 2020-08-18
Francismingren 2020-08-17
pythonclass 2020-07-29
sunzhihaofuture 2020-07-19
爱读书的旅行者 2020-07-07
行吟阁 2020-07-05
tianqi 2020-07-05
行吟阁 2020-07-04
冰蝶 2020-07-04
lyg0 2020-07-04
owhile 2020-07-04
opspider 2020-06-28
lengyu0 2020-06-28
tianqi 2020-06-21