JSP是简化的Servlet设计,在HTML标签中嵌套Java代码,用以高效开发Web应用的动态网页。在仅使用Servlet的web应用开发中,部分Servlet代码通过使用打印语句打印HTML标签来在浏览器中显示页面,而JSP可以代替显示页面的Servlet。
在学习JSP之前,服务器通过Servlet响应客户端界面,会有一些不足之处:
使用IDEA或者Eclipse创建一个JavaWeb项目,以IDEA为例,配置好Tomcat服务器,在项目名上右击创建一个first.jsp文件,IDEA会自动编写好JSP的基本结构:
在body标签中写入now:<%= new java.util.Date() %>
,<%=%>叫做输出脚本,其中可以编写Java代码。然后启动Tomcat服务器,访问所创建的JSP文件的路径,得到了如下界面:
页面显示了当前的时间,并且刷新浏览器,可以发现时间发生了改变。
Tomcat会将xxx.jsp转换成java代码,进而编译成.class文件运行,最终运行结果通过response响应给客户端。
为了理解上面一句话,我们可以实际看一下转换后的代码。在部署Tomcat后,从控制台里找到如下图所示的目录:
复制如上路径到文件管理器,进到该文件目录,主要关注work文件夹。
再依次进入work/Catalina/localhost目录,可以看到自己所创建的JavaWeb项目,Web_Jsp为第三节所创建的项目名。
再依次进入项目名/org/apache/jsp目录,可以看到一个.java文件,还有一个字节码文件,但是大家可以发现jsp文件在变成java文件时名字从first变成了first_jsp,这是容器做的事情。
打开first_jsp.java源文件或将其拖到开发工具里查看其代码。
public final class first_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
//为了更好地说明,中间代码已省略
}
首先它是一个名为first_jsp的类,继承了HttpJspBase类,需要说明的是后者是HttpServlet的子类,所以才说JSP本质上其实是一个Servlet。
同Servlet,该类也有一个service方法,不过方法名叫做_jspService,该方法也有两个参数,一个是HttpServletRequest,还有一个是HttpServletResponse,说明该方法有请求的对象也有响应的对象。
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
//为了更好地说明,中间代码已省略
}
不过重点是接下来的部分,在_jspService方法中可以找到这样一段代码:
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out.write(" Title \r\n");
out.write("\r\n");
out.write("\r\n");
out.write(" now:");
out.print( new java.util.Date() );
out.write("\r\n");
out.write("\r\n");
out.write("\r\n");
out是一个输出流,我们会发现,其实在第三节中所写的jsp代码,都在java文件中通过out做了一个打印,所以说在jsp中所展示的内容,都是通过流做的一个响应打印输出,而JSP本质上就是一个Servlet。这也是为什么在第一节说JSP是简化的Servlet,它不需要我们自己去写write或者print方法来打印页面,而是帮我们完成了这部分工作。
下面这张图可以很好地描述这个过程:
我们访问的是jsp页面,实际上访问的是java文件,通过class中的流响应给客户端一个页面。