首先,调用JspFactory的getDefaultFactory()方法获取容器实现(本文中指Tomcat 4.1.17)的一个JspFactory对象的引用。JspFactory是javax.servlet.jsp包中定义的一个抽象类,其中定义了两个静态方法set/getDefaultFactory()。set方法由JSP容器(Tomcat)实例化该页面Servlet(即HelloWorld_jsp类)的时候置入,所以可以直接调用JspFactory.getDefaultFactory()方法得到这个JSP工厂的实现类。Tomcat是调用org.apache.jasper.runtime.JspFactoryImpl类。 然后,调用这个JspFactoryImpl的getPageContext()方法,填充一个PageContext返回,并赋给内置变量pageConext。其它内置对象都经由该pageContext得到。具体过程见上面的代码,这里不再赘述。该页面Servlet的环境设置完毕,开始对页面进行解析。HelloWorld.jsp页面仅仅定义了一个String变量,然后直接输出。解析后的代码如下: 代码清单3:JSP页面解析后的代码片断 String message = "Hello World!"; out.print(message); 定制标签的解析过程
在一个中大型的Web应用中,通常使用JSP定制标签来封装页面显示逻辑。剖析容器对定制标签的解析过程,对我们深入理解定制标签的运行机理非常有帮助。下面我们以Struts1.1b中附带的struts-example应用的主页运行为例加以说明。 包含定制标签的index.jsp Struts1.1b的下载地址是http://jakarta.apache.org/struts/index.html。将下载的包解压,在webapps目录下可以找到struts-example.war。将该War包拷贝到Tomcat的webapps目录下,Tomcat会自动安装此应用包。在浏览器中通过http://localhost:8080/struts-example访问struts-example应用,将显示应用的首页(见图1)。 图一 应用的首页 代码清单4:index.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <html:html locale="true"> <head> <title><bean:message key="index.title"/></title> <html:base/> </head> <body bgcolor="white"> …… </body> </html:html> 我们仅以index.jsp中的<bean:message/>标签的解析为例进行分析,看容器是怎样把这个自定义标签解析成HTML输出的。上面代码省略了页面的其它显示部分。首先,查看上面浏览器中页面的源文件:
<html lang="zh"> <head> <title>MailReader Demonstration Application (Struts 1.0)</title> </head> <body bgcolor="white"> …… </body> </html> 可见,容器已经把<bean:message key="index.title"/>替换成一个字串,显示为页面的标题。
解析过程 那么,JSP容器是怎样完成解析的呢?查看在工作目录jakarta-tomcat-4.1.17\work\Standalone\localhost\struts-example下解析后的index_jsp.java文件: 代码清单5:index_jsp.java package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; import org.apache.jasper.runtime.*; public class index_jsp extends HttpJspBase { //为所有的定制标签定义处理器池类的引用 private org.apache.jasper.runtime.TagHandlerPool ; _jspx_tagPool_bean_message_key; …… //页面类构造方法 public index_jsp() { _jspx_tagPool_bean_message_key = new org.apache.jasper.runtime.TagHandlerPool(); …… } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { …… _jspxFactory = JspFactory.getDefaultFactory(); response.setContentType("text/html;charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true); application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; …… if (_jspx_meth_html_html_0(pageContext)) return; …… } //页面在处理退出时释放所有定制标签的属性 public void _jspDestroy() { _jspx_tagPool_bean_message_key.release(); …… } } |