我们先来看一个简单的 JSP 文件,如例 12-1 所示。 例 12-1 hello.jsp <% out.println("Hello World!"); %> 这个 JSP 页面向客户端输出“Hello World!”。我们把这个页面复制到%CATALINA_HOME%\web apps \ROOT 目录下,启动 Tomcat,打开浏览器,在地址栏中输入 localhost:8080/hello. jsp,看到“Hello World!”的输出后,读者可以转到%CATALINA_HOME%\work\Catalina\localhos t 目录,在这个目录下,有一些读者熟悉的目录,这些目录都是以前面章节的 Web 应用
程序的 上下文路径命名的,其中“_”目录对应的是 ROOT 目录。在_\org\apache\jsp 目录下,可以看到 两个文件:“hello_jsp.java”和“hello_jsp.class”,这两个文件就是在我们访问 hello.jsp 文件时, 由 JSP 容器生成的,整个过程如图 12-1 所示。
JSP 容器管理 JSP 页面生命周期的两个阶段:转换阶段(translation phase)和执行阶段(exec ution phase)。当有一个对 JSP 页面的客户请求到来时,JSP 容器检验 JSP 页面的语法是否正 确,将 JSP 页面转换为 Servlet 源文件,然后调用 javac 工具类编译 Servlet 源文件生成字节码文 件,这一阶段是转换阶段。接下来,Servlet 容器加载转换后的 Servlet 类,实例化一个对象处理 客户端的请求,在请求处理完成后,响应对象被 JSP 容器接收,容器将 HTML 格式的响应信息 发送到客户端,这一阶段是执行阶段。 从整个过程中我们可以知道,当第一次加载 JSP 页面时,因为要将 JSP 文件转换为 Servlet 类, 所以响应速度较慢。当再次请求时,JSP 容器就会直接执行第一次请求时产生的 Servlet,而不 会再重新转换 JSP 文件,所以其执行速度和原始的 Servlet 执行速度几乎就相同了。在 JSP 执行 期间,JSP 容器会检查 JSP 文件,看是否有更新或修改。如果有更新或修改,JSP 容器会再次编 译 JSP 或 Servlet;如果没有更新或修改,就直接执行前面产生的 Servlet,这也是 JSP 相对于 S ervlet 的好处之一。 下面我们看一下 JSP 容器在后台针对 hello.jsp 生成的 Servlet 源文件。虽然 JSP 页面转换为 Ser vlet 是在后台由
JSP 容器自动进行的, 但通过阅读 JSP 容器生成的
源代码来了解 JSP 背后运行的 机制,将有助于我们更好地理解 JSP 页面的运行,编写更加健壮、安全的 JSP 页面。 hello_jsp.java 的完整代码如例 12-2 所示。 例 12-2 hello_jsp.java 1.package org.apache.jsp; 2. 3.import javax.servlet.*; 4.import javax.servlet.http.*; 5.import javax.servlet.jsp.*; 6. 7.public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase 8. implements org.apache.jasper.runtime.JspSourceDependent { 9. 10. private static java.util.Vector _jspx_dependants; 11.
12. public java.
util.List getDependants() { 13. return _jspx_dependants; 14. } 15. 16. public void_jspService(HttpServletRequest request, HttpServletResponse response) 17. throws java.io.IOException, ServletException { 18. 19. JspFactory _jspxFactory = null; 20. PageContext pageContext = null; 21. HttpSession session = null; 22. ServletContext application = null; 23. ServletConfig config = null; 24. JspWriter out = null; 25. Object page = this; 26. JspWriter _jspx_out = null; 27. PageContext _jspx_page_context = null; 28. 29. 30. try { 31. _jspxFactory = JspFactory.getDefaultFactory(); 32. response.setContentType("text/html"); 33. pageContext = _jspxFactory.getPageContext(this, request, response, 34. null, true, 8192, true); 35. _jspx_page_context = pageContext; 36. application = pageContext.getServletContext(); 37. config = pageContext.getServletConfig(); 38. session = page