從HelloWorld.jsp理解JSP技術的運行內幕
眾所周知,JSP和Servlet之間有著內在的血緣關系。
1.HelloWorld.jsp代碼:
<%
String message = "Hello World!";
%>
<%=message%>
這個文件非常簡單,僅僅定義了一個String的變量,并且輸出。把這個文件放到Tomcat的webapps\ROOT\目錄下,啟動Tomcat,在瀏覽器中訪問http://localhost:8080/HelloWorld.jsp,瀏覽器中的輸出為“HelloWorld!”
2.HelloWorld_jsp.java代碼:
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import org.apache.jasper.runtime.*;
public class HelloWorld_jsp extends HttpJspBase {
private static java.util.List _jspx_dependants;
public Object getDependants() {
return _jspx_dependants;
}
public void _jspService(HttpServletRequest request,
HttpServletResponse response)throws java.io.IOException, ServletException{
JspFactory _jspxFactory = null;
javax.servlet.jsp.PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
try {
_jspxFactory = JspFactory.getDefaultFactory();//調用JspFactory的getDefaultFactory()方法獲取容器實現的一個JspFactory對象的引用
response.setContentType("text/html;charset=ISO-8859-1");
pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);//填充一個PageContext返回,并賦給內置變量 pageConext
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
String message = "Hello World!";
out.print(message);
} catch (Throwable t) {
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (pageContext != null) pageContext.handlePageException(t);
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
}
}
}
轉到Tomcat的\work\Standalone\localhost\_目錄下,可以找到如下的HelloWorld_jsp.java,這個文件就是Tomcat解析HelloWorld.jsp時生成的源文件。由此可見,HelloWorld.jsp在運行時首先解析成一個Java類HelloWorld_jsp.java,該類繼承于org.apache.jasper.runtime.HttpJspBase基類,HttpJspBase實現了HttpServlet接口。因此,JSP在運行前首先將編譯為一個Servlet,這就是理解JSP技術的關鍵。
首先,調用JspFactory的getDefaultFactory()方法獲取容器實現的一個JspFactory對象的引用。JspFactory是javax.servlet.jsp包中定義的一個抽象類,其中定義了兩個靜態方法setDefaultFactory()/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變量,然后直接輸出。解析后的代碼如下:
String message = "Hello World!";
out.print(message);