最近一个同事问我,怎么快速实现在一个老系统的页面上统一添加用于页面性能分析的 JavaScript 脚本。确实,老系统这么多页面,如果一个一个去修改是非常费时而且笨的做法。
我想了一下,写了一个 Servlet Filter,可以实现在 HTTP 响应内容中的某个节点(比如 </body>
)前添加 HTML 代码,优雅的解决了这个问题。
使用样例
插入 html 代码的类
1 2 3 4 5 6 7 8 9 10 11 12
| package demo; * 继承 HtmlContentProvider,实现提供插入内容的方法。 */ public class HtmlContentProviderImpl implements HtmlContentProvider { public String getContent(HttpServletRequest request) { return "<div style=\"display:none\">" + "<script src=\"http://s16.cnzz.com/stat.php?id=xxxxxxx&web_id=xxxxxxx\"" + " language=\"javascript\"></script></div>"; } }
|
Spring 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <bean id="htmlContentAppendFilter" class="demo.HtmlContentAppendFilter"> <property name="htmlNode" value="</head>" /> <property name="reverseLookup" value="false" /> <property name="includes" value=".+\.htm" /> <property name="excludes" value="/.+/remote.+" /> <property name="htmlContentProvider"> <bean class="demo.HtmlContentProviderImpl" /> </property> </bean>
|
web.xml 配置
1 2 3 4 5 6 7 8 9 10 11 12 13
| <filter> <filter-name>htmlContentAppendFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetBeanName</param-name> <param-value>htmlContentAppendFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>htmlContentAppendFilter</filter-name> <url-pattern>*.htm</url-pattern> </filter-mapping>
|
这样,对于所有的 .htm
请求,只要响应消息中包含了 </head>
节点,都会自动添加 HtmlContentProviderImpl.getContent(request)
中返回的内容,即一段 CNZZ 脚本。
性能和不足之处
在使用此过滤器和不使用此过滤器的情况下,对常规的页面(1M 以内)做了压力测试,发现吞吐量相差不大,基本可以忽略添加过滤器的影响。对于数据量比较大的页面,比如超过 1M 的页面,那么可能比较服务器消耗内存,同时在查找节点时速度也会慢一些,从而对页面性能造成一些影响。从另外一方面来说,出于性能的考虑,也应该尽可能保持页面小一些,超过 100K 的页面都值得考虑是否只能这么大。