bean:message标签的解析
代码清单7:_jspx_meth_bean_message_0()方法片断
//对message定制标签的处理方法 private boolean _jspx_meth_bean_message_0( javax.servlet.jsp.tagext.Tag _jspx_th_html_html_0, javax.servlet.jsp.PageContext pageContext) throws Throwable { JspWriter out = pageContext.getOut(); /* ---- bean:message ---- */ org.apache.struts.taglib.bean.MessageTag _jspx_th_bean_message_0 =(org.apache.struts.taglib.bean.MessageTag) _jspx_tagPool_bean_message_key.get(org.apache.struts.taglib.bean.MessageTag.class); _jspx_th_bean_message_0.setPageContext(pageContext); _jspx_th_bean_message_0.setParent(_jspx_th_html_html_0); _jspx_th_bean_message_0.setKey("index.title"); int _jspx_eval_bean_message_0 = _jspx_th_bean_message_0.doStartTag(); if (_jspx_th_bean_message_0.doEndTag()== javax.servlet.jsp.tagext.Tag.SKIP_PAGE) return true; _jspx_tagPool_bean_message_key.reuse(_jspx_th_bean_message_0); return false; } 同样,对html:bean也需要从池中得到一个标签类的实例,然后设置环境。这里不再赘述。我们只专注对MessageTag定制标签类特殊的处理部分。定制标签类的开发不在本文讨论范围之内。在index.jsp中定义了一个bean:message标签,并设置了一个属性:。Tomcat在解析时,调用MessageTag对象的key属性设置方法setKey(),将该属性置入。然后调用MessageTag的doStartTag()和doEndTag()方法,完成解析。如果doEndTag()方法的返回值为javax.servlet.jsp.tagext.Tag. SKIP_PAGE,表明已经完成解析,返回true,Tomcat将立即停止剩余页面代码的执行,并返回。否则把该MessageTag的实例放回池中。
标签类对象实例的池化
为了提高运行效率,Tomcat对所有的定制标签类进行了池化,池化工作由org.apache.jasper. runtime.TagHandlerPool类完成。TagHandlerPool类主要有两个方法,代码如下:
代码清单8:TagHandlerPool.java
public class TagHandlerPool { private static final int MAX_POOL_SIZE = 5; private Tag[] handlers; public synchronized Tag get(Class handlerClass) throws JspException {……} public synchronized void reuse(Tag handler) {……} } TagHandlerPool简单地实现了对标签类的池化,其中MAX_POOL_SIZE是池的初始大小,handlers是一个Tag的数组,存储标签类的实例。get(Class handlerClass)得到一个指定标签类的实例,如果池中没有可用实例,则新实例化一个。reuse(Tag handler)把handler对象放回池中。
至此,我们对JSP在容器中的运行过程已经了然于胸了。虽然每种JSP容器的解析结果会有差异,但其中的原理都雷同。对于编写JSP应用,我们并不需要干涉容器中的运行过程,但如果你对整个底层的运行机制比较熟悉,就能对JSP/Servlet技术有更深的认识。
|