浏览器请求服务器内的JSP文件时,服务器的Servlet容器会在第一次调用这个JSP文件时进行编译。编译完成后,该JSP实际是一个Servlet类,该Servlet产生对应的输出结果,把输出结果发送给Servlet容器,Servlet容器把这些结果以HTML文件形式发送给浏览器。
应注意,Servlet容器会在第一次调用JSP时进行编译,之后这个JSP会存在在内存中,之后再次调用无需编译(除非JSP文件有修改)。这个工作是由JSP引擎完成的。JSP引擎把客户端请求发送给JSP源文件,再把JSP源文件的相应发送给客户端。JSP引擎需要支持HTTP协议。JSP引擎在传递request和response对象之前,会通过JSP源文件创建一个类(Servlet类),并在调用时进行编译。
以下用例子说明:
在Tomcat的webapps下创建jsplearn目录,并创建helloworld.jsp文件。
helloworld.jsp内容如下:
<%@ page language="java" contentType="text/html;charset=utf-8"%>
<%@ page info="a hello wxample"%>
<html>
<head>
<title>理解JSP的原理</title>
</head>
<body>
<center>
<h1>
<%
int times = 10;
for(int i =0;i<times;i++){
out.println("HELLOWORLD");
out.println("<br>");
}
%>
</h1>
</center>
</body>
</html>
启动Tomcat后,访问路径为http://localhost:8080/jsplearn/helloworld.jsp
。
可以在浏览器内看到相应输出。在开发人员工具选项中,可以看到浏览器解析的HTML文件为:
<html>
<head>
<title>理解JSP的原理</title>
</head>
<body>
<center>
<h1>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
HELLOWORLD
<br>
</h1>
</center>
</body>
</html>
该HTML是服务器中JSP源文件经过编译被调用后,对请求的相应。
此时在Tomcat的本地目录work\Catalina\localhost\jsplearn中,可以看到JSP源文件所对应生成的helloworld_jsp.java和helloworld_jsp.class。helloworld_jsp.java就相当于一个Servlet类。
其最主要的代码片段为:
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=utf-8");
pageContext = _jspxFactory.getPageContext(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;
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("\t<head>\r\n");
out.write("\t\t<title>理解JSP的原理</title>\r\n");
out.write("\t</head>\r\n");
out.write("\t<body>\r\n");
out.write("\t\t<center>\r\n");
out.write("\t\t\t<h1>\r\n");
out.write("\t\t\t");
int times = 10;
for(int i =0;i<times;i++){
out.println("HELLOWORLD");
out.println("<br>");
}
out.write("\r\n");
out.write("\t\t\t</h1>\r\n");
out.write("\t\t</center>\r\n");
out.write("\t</body>\r\n");
out.write("</html>");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
使用out.write来作为浏览器请求的相应。当请求该JSP源文件时,JSP引擎就会调用该_jspService()方法。