http://hi.baidu.com/yanhua365/blog/item/a05930ad04b777094a36d662.html
页面中太多的自定义标签会不会影响性能?
太多的自定义标签(尤其是这种包含了一部分业务逻辑的标签)会不会影响性能呢?下面一段文字是我以前写的,可以说明一些问题,但真正对性能会不会产生太大的影响,还要看具体的情况,如果有必要的话,做一下性能测试得出的结果才是可靠的。
我们知道,JSP归根到底是Servlet,也就是说最终是要编译成Servlet的。如果是在Servlet的service方法中new一个Tag处理类来处理出现的标签的话,那就意味着每一次客户的请求都会生成新的Tag处理类,这样对服务器的性能和资源影响都很大。而如果把Tag处理类的对象做为Servlet的一个属性的话,又会遇到线程安全等问题。据说,不同的JSP容器有不同的处理方式,有的容器下,一个页面上出现太多的自定义标签,响应速度就会很慢。真担心太多的JSP和太多的自定义标签会使服务器承受不了啊。--今天突然想到,可以看一下Tomcat是怎么把包含有自定义标签的JSP页面编译成Servlet的,也许就清楚自定义标签对性能的影响有多大了!
原来,Tomcat用了缓冲池的概念来解决。。。
比如我在JSP中用到了一个Struts标签<html:text property="username"></html:text>那么,在对应的JSP编译的Servlet中会有一个这样的属性private org.apache.jasper.runtime.TagHandlerPool _jspx_tagPool_html_text_property;可以看出来,这是Tomcat提供的一个标签处理的缓冲池,在下面会用到它。在Servlet中会生成下面这个方法:
private boolean _jspx_meth_html_text_0(javax.servlet.jsp.tagext.JspTag _jspx_th_html_form_0, PageContext pageContext)
throws Throwable {
JspWriter out = pageContext.getOut();
/* ---- html:text ---- */
org.apache.struts.taglib.html.TextTag _jspx_th_html_text_0 = (org.apache.struts.taglib.html.TextTag) _jspx_tagPool_html_text_property.get(org.apache.struts.taglib.html.TextTag.class);
_jspx_th_html_text_0.setPageContext(pageContext);
if (_jspx_th_html_form_0 instanceof javax.servlet.jsp.tagext.SimpleTag)
_jspx_th_html_text_0.setParent(new javax.servlet.jsp.tagext.TagAdapter((javax.servlet.jsp.tagext.SimpleTag) _jspx_th_html_form_0));
else
_jspx_th_html_text_0.setParent((javax.servlet.jsp.tagext.Tag) _jspx_th_html_form_0);
_jspx_th_html_text_0.setProperty("username");
int _jspx_eval_html_text_0 = _jspx_th_html_text_0.doStartTag();
if (_jspx_th_html_text_0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)
return true;
_jspx_tagPool_html_text_property.reuse(_jspx_th_html_text_0);
return false;
}
可以看出,在这个方法中,对标签处理类做了缓冲池处理,可以大大提高性能。
当然,_jspx_tagPool_html_text_property这个Servlet的属性,要在初始化时赋值,在最后释放掉。
public void _jspInit() {
_jspx_tagPool_html_text_property = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(getServletConfig());
}
public void _jspDestroy() {
_jspx_tagPool_html_text_property.release();
}
需要说明的是,这种缓冲池是在这个JSP生命周期的范围内的,也就是说,另一个JSP页面用到了相同的标签,也会重新建立一个缓冲池,和这个页面毫无关系。还有一点,就是在同一个JSP页面中,也不是一个标签对应一个缓冲池,比如说我用到了link标签的两种形式,它们属性的个数是不一样的:
<html:link action="/test">Test with a link</html:link>
<html:link action="/test" paramId="username" paramName="haha">
那就会生成两个缓冲池:
private org.apache.jasper.runtime.TagHandlerPool _jspx_tagPool_html_link_action;
private org.apache.jasper.runtime.TagHandlerPool _jspx_tagPool_html_link_paramName_paramId_action;
这样,虽然服务器上会有很多这样的缓冲池,不过相对于每次请求创建Tag处理类来说,这不算什么,大大提高了性能和利用了服务器资源。
我们这里说的都是Tomcat的解决方案,至于其它容器,也许有不同的解决方案。