一、JSP原理介绍
jsp是运行在web服务端的JAVA展现技术,JSP的实质是一个servlet,也就是一个java文件,在运行的时候也要被JVM编译和装载
二、Jsp运行原理
在一个JSP文件第一次被请求时,JSP引擎把该JSP文件转换成为一个Servlet。而这个引擎本身也是一个Servlet。JSP的运行过程如下所示:
(1)JSP引擎先把该JSP文件转换成一个Java源文件(Servlet),在转换时如果发现JSP文件有任何语法错误,转换过程将中断,并向服务端和客户端输出出错信息。
(2)如果转换成功,JSP引擎用javac把该Java源文件编译成相应的class文件。
(3)创建一个该Servlet(JSP页面的转换结果)的实例,该Servlet的jspInit()方法被执行,jspInit()方法在Servlet的生命周期中只被执行一次。
(4)jspService()方法被调用来处理客户端的请求。对每一个请求,JSP引擎创建一个新的线程来处理该请求。如果有多个客户端同时请求该JSP文件,则JSP引擎会创建多个线程。每个客户端请求对应一个线程。以多线程方式执行可以大大降低对系统的资源需求,提高系统的并发量及响应时间。但不过也应该注意多线程的编程限制,由于该Servlet始终驻于内存,所以响应是非常快的。
(5)如果.jsp文件被修改了,服务器将根据设置决定是否对该文件重新编译,如果需要重新编译,则将编译结果取代内存中的Servlet,并继续上述处理过程。
(6)虽然JSP效率很高,但在第一次调用时由于需要转换和编译而有一些轻微的延 迟。此外,在任何时候如果由于系统资源不足的原因,JSP引擎将以某种不确定的方式将Servlet从内存中移去。当这种情况发生时jspDestroy()方法首先被调用。
(7)然后Servlet实例便被标记加入“垃圾收集”处理。可在jspInit()中进行一些初始化工作,如建立与数据库的连接,或建立网络连接,从配置文件中取一些参数等,在jspDestory()中释放相应的资源。
三、jsp原理图
其步骤如下:
1.jsp引擎将jsp文件翻译为Servlet源程序;
2.之后又将Servlet源程序编译为.class类文件;
其中:
1.Jsp引擎是通常一个Servlet程序,Tomcat中的jsp引擎就是org.apache.jasper.servlet.JspServlet;
2.在Tomcat中编译的源文件和.class文件放在”[TOMCAT_HOME]\work\Catalina\[主机名,如localhost]\应用程序名称” 目录下;
3.默认情况下,第一次访问某jsp文件时,才对该jsp文件进行翻译、编译,所以较慢。不过在以后的访问中将不会在出现该情况,因为已经被编译过了,呵呵。
四、jsp相关类
4.1 jsp相关uml图
其中,org.apache.jsp.index_jsp是tomcat将index.jsp转化为servlet源代码后的结果
。其代码可以在如下目录中看到(当然,你要首先访问index.jsp才会翻译,编译)
4.2 具体类源代码
4.2.1 JspPage源代码
Java代码
package
import
public abstract interface JspPage extends
{
public abstract void
public abstract void
}
4.2.2 HttpJspPage源代码
Java代码
package
import
import
import
import
public abstract interface HttpJspPage extends
{
public abstract void
throws
}
4.2.2 HttpJspBase 源代码
和HttpJspPage名称虽然很香精 ,但已经位于不同的包中了。下面的源代码是我从tomcat6中的jasper.jar拉出来的。
Java代码
package
import
import
import
import
import
import
import
import
public abstract class HttpJspBase extends
implements
{
public final void
throws
{
super.init(config);
jspInit();
_jspInit();
}
public
return Localizer.getMessage("jsp.engine.info");
}
public final void
jspDestroy();
_jspDestroy();
}
public final void
throws
{
_jspService(request, response);
}
public void
{
}
public void
{
}
public void
{
}
protected void
{
}
public abstract void
throws
}
4.2.2 JspSourceDependent源代码
Java代码
package
public abstract interface
{
public abstract
}
4.2.2 org.apache.jsp.index_jsp 源代码
上面提到过org.apache.jsp.index_jsp是tomcat将index.jsp转化为servlet的源代码。
Java代码
package
import
import
import
import
public final class index_jsp extends
implements
private static final
private static
private
private
public
return
}
public void
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
class.getName());
}
public void
}
public void
throws
null;
null;
null;
null;
null;
this;
null;
null;
try
"text/html;charset=GB18030");
this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
'\r');
'\n');
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
"\r\n");
"\r\n");
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
"<html>\r\n");
" <head>\r\n");
" <base href=\"");
out.print(basePath);
"\">\r\n");
" \r\n");
" <title>My JSP 'index.jsp' starting page</title>\r\n");
"\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
"\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
"\t<meta http-equiv=\"expires\" content=\"0\"> \r\n");
"\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
"\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
"\t<!--\r\n");
"\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
"\t-->\r\n");
" </head>\r\n");
" \r\n");
" <body>\r\n");
" This is my JSP page. <br>\r\n");
" </body>\r\n");
"</html>\r\n");
catch
if (!(t instanceof
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer(); } catch
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
}
finally
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
其对应的index.jsp为
Html代码
<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<br>
</body>
</html>
4.2.3 九大隐藏对象
从jsp转换的源码中,很容易的就可以发现了传说中的9大jsp内置隐藏对象中的8个。如下:
Java代码
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
至于第9个,只有page指令被设置为:
Html代码
<%@ page isErrorPage="true" %>
才会出现:
Java代码
Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);