1.JSP原理分析
我们知道,jsp是动态资源的一种,它包含HTML代码,Java脚本以及jsp标签。在
jsp入门中我们了解到,jsp弥补了Servlet和HTML的不足。其实jsp是一种特殊的Servle,后面我们会详细介绍。动态资源不能被浏览器直接显示,需要翻译成静态资源后再发送给浏览器。下面,我们就来了解jsp是如何被翻译成静态资源。
分步骤解析jsp原理,如下所示:
- 当浏览器第一次访问jsp页面时,服务器会把jsp翻译成一个Java文件,该Java类是一个Servlet类;
- 然后服务器再把Java文件编译成class文件;
- 接着创建该类对象;
- 最后调用该类的service()方法;
- 当第二次再访问该jsp页面时,直接调用jsp页面对应Java类的service()方法。
由以上步骤可知,jsp被翻译成Servlet后,服务器会为该Servlet类创建对象,并常驻内存,当服务器关闭才销毁。以后每次访问该jsp都会调用该jsp的Servlet类的service()方法。如果jsp页面被修改,那么再次访问时,服务器会重新翻译该jsp页面。
下面,通过一张图来了解第一次访问jsp页面的流程图,如图1-1所示:
图1-1 第一次访问jsp流程图
2.jsp对应Java文件分析
通过以上对jsp原理的理解,我们知道jsp文件会被服务器翻译成对应的Java文件,下面我们就对jsp对应的Java文件进行分析。在web应用中,对index.jsp进行编辑,如例1-1所示:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
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>
This is my JSP page. <br>
<%
int a = 10;
%>
<%
out.print(a++);
%>
<br>
使用Java脚本输出a的值: <%=a%>
<br>
<%!
int a = 100;
public void fun1() {
System.out.println(a);
}
%>
<%
out.print(this.a++);
fun1();
%>
</body>
</html>
当第一次访问index.jsp后,服务器会将index.jsp翻译成对应的Java文件,文件名为index_jsp.java。该文件存放的目录如图1-2所示:
图1-2 Java文件所在目录
由图1-2可知,jsp编译后的Java文件都存放在tomcat安装目录的work/Catalina/localhos目录中,其中Example15是项目名称。
找到文件所在的目录,点击此处
查看index_jsp.java文件。下面来分析该文件的代码,如下所示:
(1)在index.jsp文件中使用<%!%>脚本声明了成员变量和成员方法,它们在index_jsp.java中的位置如图1-3所示:
图1-3 成员所在位置
由图1-3可知,该java文件的类名就是index_jsp,它继承了HttpJspBase类,这个类是Tomcat定义的类。该类实现了Servlet接口,因此index_jsp类也是Servlet类。在index_jsp类的成员位置定义了成员变量a,值为100,定义了成员方法fun1()。
(2)接着看index_jsp类的service()方法,如图1-4所示:
图1-4 service方法
由图1-4可知,在index_jsp类中,service()方法的名字是_jspService。我们知道jsp有九大内置对象,我们可以由图1-4看出,在_jspService()方法中,定义了6个变量,分别是session,application,config,out,page,pageContext。由于在_jspService()方法中定义了,因此再jsp页面中我们可以直接使用这些变量,另外,其他三个内置对象:request、response是做为参数传递给了_jspService()方法,exceptionn在后面我们会讲解。
(3)每次一请求,服务器都会调用_jspService()方法,那么浏览器中显示的页面信息必然和该放方法有关,下面我们来了解如何将页面中的信息显示在浏览器,如图1-5所示:
图1-5 输出页面信息
图1-5所示中,index.jsp页面中<%%>里面的代码在index_jsp.java文件中出现的位置是_jspService()方法中,并且按原样显示,而其他的HTML代码都是以字符串的形式通过out对象调用write()方法输出到浏览器端。其中:
<base href="<%=basePath%>">
<%= basePath%>被out.print(basePath)方法输出在浏览器端。out对象的writer()方法和print()方法没有什么区别,这样用是为了区别HTML代码和Java代码的输出。
(4)下面来看在jsp中使用for循环,在index_jsp.java中是如何显示的,如图1-6所示:
图1-6 for循环
由图1-6可知,在for循环中,使用out.write()方法将HTML代码输出,对应在页面中的代码如下所示:
<%
for(int i = 0; i < 10; i++) {
%>
<tr>
<td>张三</td>
<td>29</td>
</tr>
<% } %>
(5)在_jspService()方法中,有一个异常处理,如图1-7所示:
图1-7 异常处理
当执行_jspService()方法过程中,出现了异常,那么图1-7中的代码就会捕获该异常,并进行处理。出现异常之前的代码不会被输出在浏览器端,服务器会给浏览器端响应500状态码。并且地址栏地址不变,可以理解为服务器在做转发,我们知道在进行转发时,response响应输出流中的信息会被清空,因此之前的向response缓冲区存放的信息不会显示在浏览器端。
本文版权归传智播客Java培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:传智播客Java培训学院
首发:http://www.itcast.cn/javaee