在上篇博文中介绍了JavaWeb开发中比较基础也是比较经典的Servlet技术,同时也在文章的结尾点出了Servlet技术所带来的问题,那就是由于包括大量的HTML标签,大量的静态文本及格式等,导致Servlet的开发效率极为低下。所有的表现逻辑,包括布局、色彩及图像等,都必须耦合在Java代码中,这的确让人觉得非常糟糕。
JSP的出现弥补了这种不足,JSP通过在标准的HTML页面中嵌入Java代码,其静态的部分无须Java程序控制,只有那些需要从数据库读取或者需要动态生成的页面内容,才使用Java脚本控制。从本质上来说,JSP也是Servlet,当用户向指定的Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每一个静态的HTML标签和所有在HTML页面中出现的内容。
JSP页面的组成部分:
#静态部分:标准的HTML标签、静态的页面内容,这些内容与静态HTML页面相同。
#动态部分:受Java程序控制的内容,这些内容由Java脚本动态生成。
下面我们来看一个最简单的JSP页面代码。
<%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
<html>
<head>
<title>欢迎</title>
</head>
<body>
尊敬的用户:您好!<br>
当前时间是:<br>
<% out.println(new java.util.Date());%>
</body>
</html>
上面的代码中,使用<%……%>符号包起来的内容,称之为Java脚本,这就是所谓的动态内容,通过这种方式可以把Java代码嵌入在HTML页面中,这样就成了动态的JSP页面。我们在浏览器中访问改页面,可以看到如下页面:
从表面上看,JSP页面似乎已经不再需要Java类,好像完全脱离了Java面向对象的核心思想。事实上,JSP的本质依然是Servlet,这个在上文中已经提到,这里详细阐述一下。
其实每个JSP页面就是一个Servlet实例——JSP页面由系统编译成Servlet,Servlet再负责响应用户的请求。也就是说,JSP其实也是Servlet的一种简化,使用JSP时,其实还是在使用Servlet,因为Web应用中的每个JSP页面都会由Servlet容器生成对应的Servlet。对于Tomcat而言,JSP页面生成的Servlet放在work路径对应的Web应用下。
我们打开Tomcat的文件路径,来查看一下上面的JSP页面所对应的类文件和Java代码文件,如下图所示:
打开welcome_jsp.java文件,我们来看看它的代码是什么样的:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.42
* Generated at: 2015-12-17 08:33:01 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class welcome_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
public void _jspDestroy() {
}
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=GBK");
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("<html>\r\n");
out.write("\t<head>\r\n");
out.write("\t\t<title>欢迎</title>\r\n");
out.write("\t</head>\r\n");
out.write("\t<body>\r\n");
out.write("\t\t尊敬的用户:您好!<br>\r\n");
out.write("\t\t当前时间是:<br>\r\n");
out.write("\t\t");
out.println(new java.util.Date());
out.write("\r\n");
out.write("\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 { 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);
}
}
}
对于初学者来说,看到上面的Java类可能有点懵,这是什么玩意啊?其实这就是一个Servlet类的源代码,该Java类主要包含三个方法:
#init():初始化JSP/Servlet的方法。
#destroy():销毁JSP/Servlet之前的方法。
#service():对用户请求生成响应的方法。
即使不了解,也没关系,这不影响我们开发自己JSP页面,因为编译的工作是由Web容器完成的。比如我们使用Tomcat就是一个Web容器。
小结一下:
关于JSP的工作原理,我们先来看一张图,这是从网上找的,我觉得还不错,可能对大家的理解有帮助。
综上所述,我们可以得到几个结论:
1JSP文件必须在JSP服务器内才可以运行
2JSP文件必须生成Servlet才可以被执行
3每个JSP页面的第一个访问者的响应速度会很慢,因为这个用户需要等待JSP被编译成Servlet。
4JSP页面的访问者无需安装任何客户端,甚至不需要可以运行Java的运行环境,因为JSP页面输送到客户端的是标准的HTML页面,你有个浏览器就够了。
JSP技术的出现,大大的提高了Java动态网站的开发效率,所以得到了广大动态网站开发人士的青睐。