<html>
<head><title>www.javaworld.com.tw – 台湾 Java 论坛</title></head>
<body>
<%
out.println(" Hello World <br>");
out.println("大家好");
%>
</body>
</html>
这样就简化了 Web 网页程序员的负担,不用为了网页内容编排的更动,又需要由程序员来做修 改。
3-4 JSP 的执行过程
在介绍 JSP 语法之前,先向读者说明一下 JSP 的执行过程(见图 3-1)。 (1) 客户端发出 Request (请求);
(2) JSP Container 将 JSP 转译成 Servlet 的源代码;
(3) 将产生的 Servlet 的源代码经过编译后,并加载到内存执行;
(4) 把结果 Response (响应)至客户端。
图 3-1 JSP 的执行过程
一般人都会以为 JSP 的执行性能会和 Servlet 相差很多,其实执行性能上的差别只在第一次的 执行。因为 JSP 在执行第一次后,会被编译成 Servlet 的类文件[玉玉 2],即为 XXX.class,当再重
复调用执行时,就直接执行第一次所产生的 Servlet,而不用再重新把 JSP 编译成 Servlet。因此,
除了第一次的编译会花较久的时间之外,之后 JSP 和 Servlet 的执行速度就几乎相同了。
在执行 JSP 网页时,通常可分为两个时期:转译时期(Translation Time)和请求时期(Request Time)(见图 3-2)。
转译时期:JSP 网页转译成 Servlet 类。
请求时期:Servlet 类执行后,响应结果至客户端。
补充
转译期间主要做了两件事情:将 JSP 网页转译为 Servlet 源代码(.java),此段称为转译时 期(Translation time);将 Servlet 源代码(.java)编译成 Servlet 类(.class),此段称为 编译时期(Compilation time)。
当 JSP 网页在执行时,JSP Container 会做检查的工作,若发现 JSP 网页有更新修改时,JSP Container 才会再次编译 JSP 成 Servlet;JSP 没有更新时,就直接执行前面所产生的 Servlet。
笔者在这里以 Tomcat 为例,看看 Tomcat 如何将 JSP 转译成 Servlet。首先笔者写一个简单的 JSP 网页 —— HelloJSP.jsp:
HelloJSP.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>CH3 - HelloJSP.jsp</title>
</head>
<body>
<h2>JSP 将会被转译为 Servlet</h2>
<%!
int k = 0;
%>
<c:out value="Hi" />
<%
String name = "browser";
out.println("大家好 !!");
%>
<%= name %>
</body>
</html>
当 执行 HelloJSP.jsp 时, Tomcat 会将 它先 转译为 Servlet 。这个 Servlet 程序 是放 在 {Tomcat_Install}\Apache Software Foundation\Tomcat 5.0\ work\Catalina\localhost\JSPBook\
org\apache\jsp\CH3 目录下的 HelloJSP_jsp.java 和 HelloJSP_jsp.class。其中 HelloJSP_jsp.java 就是 HelloJSP.jsp 所转译的 Servlet 源代码,它的程序如下:
HelloJSP_jsp.java
package org.apache.jsp.CH3;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class HelloJSP_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent {
int k = 0;
private static java.util.Vector _jspx_dependants;
private org.apache.jasper.runtime.TagHandlerPool _ jspx_tagPool_c_out_value;
public java.util.List getDependants() { return _jspx_dependants;
}
public void _jspInit() { _jspx_tagPool_c_out_value =
org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(
getServletConfig());
}
public void _jspDestroy() {
_jspx_tagPool_c_out_value.release();
}
public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException {
JspFactory _jspxFactory = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=GB2312");
pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out.write("<title>CH3 - HelloJSP.jsp");
out.write("</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n\r\n");
out.write("<h2>JSP 将会被转译为 Servlet");
out.write("</h2>\r\n\r\n");
out.write("\r\n");
if (_jspx_meth_c_out_0(pageContext)) return;
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0) out.clearBuffer();
if (pageContext != null) pageContext.handlePageException(t);
}
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
} }
private boolean _jspx_meth_c_out_0(PageContext pageContext) throws Throwable {
JspWriter out = pageContext.getOut();
// c:out
org.apache.taglibs.standard.tag.rt.core.OutTag _jspx_th_c_out_0 = (org.apache.taglibs.standard.tag.rt.core.OutTag) _jspx_tagPool_c_out_value.
get( org.apache.taglibs.standard.tag.rt.core.OutTag.class);
_jspx_th_c_out_0.setPageContext(pageContext);
_jspx_th_c_out_0.setParent(null);
_jspx_th_c_out_0.setValue(new String("Hi"));
int _jspx_eval_c_out_0 = _jspx_th_c_out_0.doStartTag();
if (_jspx_th_c_out_0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) return true;
_jspx_tagPool_c_out_value.reuse(_jspx_th_c_out_0);
return false;
public void _jspInit() {
…. 略 }
public void _jspDestroy() { …. 略
}
public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException {
…. 略 }
_jspInit( ):当 JSP 网页一开始执行时,最先执行此方法。因此,我们通常会把初始化的工作写在 此方法中。
_jspDestroy( ):JSP 网页最后执行的方法。
_jspService( ):JSP 网页最主要的程序都是在此方法中。
接下来笔者将 HelloJSP.jsp 和 HelloJSP_jsp.java 做一个简单的对照:
<%@ page contentType="text/html;charset=GB2312" %>
response.setContentType("text/html;charset=GB2312");
<%! int k = 0; %>
int k = 0; // 此为全局变量
<html>
<head>
<title>CH3 - HelloJSP.jsp</title>
</head>
<body>
<h2>JSP 将会被转译为 Servlet</h2>
out.write("\r\n");
out.write("\r\n\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n ");
out.write("<title>CH3 - HelloJSP.jsp");
out.write("</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n\r\n");
out.write("<h2>JSP 将会被转译为 Servlet");
out.write("</h2>\r\n\r\n");
out.write("\r\n");
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:out value="Hi" />
if (_jspx_meth_c_out_0(pageContext))
return;
…. 略
private boolean _jspx_meth_c_out_0(PageContext pageContext)
JspWriter out = pageContext.getOut();
// c:out
org.apache.taglibs.standard.tag.rt.core.OutTag _jspx_th_c_out_0 = (org.apache.taglibs.standard.tag.rt.core.OutTag) _jspx_tagPool_c_out_value.
get(org.apache.taglibs.standard.tag.rt.core.OutTag.class);
_jspx_th_c_out_0.setPageContext(pageContext);
_jspx_th_c_out_0.setParent(null);
_jspx_th_c_out_0.setValue(new String("Hi"));
int _jspx_eval_c_out_0 = _jspx_th_c_out_0.doStartTag();
if (_jspx_th_c_out_0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) return true;
_jspx_tagPool_c_out_value.reuse(_jspx_th_c_out_0);
return false;
String name = "browser";
out.println("大家好 !!");
out.write("\r\n");
out.print( name );