复习JSP的概念

JSP是Java Server Page的缩写,在传统的HTML页面中加入JSP标签和java的程序片段就构成了JSP。

JSP的基本语法:两种注释类型、三个脚本元素、三个元素指令、八个动作指令。

JSP的内置对象常用的有:Request、Response、Out、Session、cookie、Application等。

JSP中的局部变量和全局变量

在JSP基本语法博文中有个小例子counter.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head></head>
<body>
<%!int count = 0;
synchronized void setCount() {
count++;
};
%>
<h2>
欢迎阅读本文
<h2>
<br> 本文阅读次数:
<% setCount();
out.println(count);
%>
<br>
i=0,计算i++=
<%
int i = 0;
out.println(i++);
%> </body>
</html>

这个例子的目的是为了区分在<%! %>和<%%>中定义的变量:

<%! %>内的变量和方法是一个类内的变量和方法也就是页面的成员变量和成员方法,每当一个用户访问此页面,count会加一。

<% %>内的变量是一个方法的变量也就是局部变量,无论访问页面多少次,i++的值总是0。

我们看到两种变量的不同,但是并没理解为什么会造成这样的不同。下面就详细讲解。

JSP执行过程图解

第一次请求:

当服务器上的一个JSP页面被第一次请求执行时,服务器上的JSP引擎首先将JSP页面文件转译成一个.java文件,也就是servlet,并编译这个java文件生成.class的字节码文件,然后执行字节码文件响应客户端的请求。

再次请求:

JSP引擎将直接执行字节码文件来响应客户。

由JSP转译的servlet

我们可以查看由JSP转译成的servelt,由此来加深多JSP的理解。存放JSP转译成的servlt的目录如下:

apache-tomcat-7.0.59\work\Catalina\localhost\yourwebapp\org\apache\jsp 

这些servlet的名字都是以_jsp.java结尾。下面是counter_jsp.java的具体内容:

/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.59
* Generated at: 2015-08-07 05:13:13 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.*;
import java.util.*; public final class counter_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent { int count = 0;
synchronized void setCount() {
count++;
}; 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=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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write("<head></head>\r\n");
out.write("<body>\r\n");
out.write("\t");
out.write("\r\n");
out.write("\t<h2>\r\n");
out.write("\t\t欢迎阅读本文\r\n");
out.write("\t\t<h2>\r\n");
out.write("\t\t\t<br> 本文阅读次数:\r\n");
out.write("\t\t\t");
setCount();
out.println(count); out.write("\r\n");
out.write("\t\t\t<br>\r\n");
out.write("\t\t\ti=0,计算i++=\r\n");
out.write("\t\t\t"); int i = 0;
out.println(i++); out.write("\r\n");
out.write("\t\t\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} 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);
}
}
}

也许你回疑问,counter_jsp.java并没有继承HttpServlet,为什么称它们为servlet?请注意下面

public final class counter_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent

在apache-tomcat-7.0.59\java\org\apache\jasper\runtime目录下存HttpJspBase这个类的源代码文件,

public abstract class HttpJspBase extends HttpServlet
implements HttpJspPage{...}

因为下面的关系,所以这些_jsp.java文件都是servlet。

HttpServlet
继承者 HttpJspBase
继承者 counter_jsp

回到counter_jsp.java中,我们可以应用记事本的查找功能,找到我们在JSP页面定义的变量。可以看到:

<%! %>中定义的变量和方法是类的成员变量和成员方法,是全局变量。

<% %>中定义的变量是_jspService(){}方法中的局部变量。

JSP的内部方法

_jspInit(){}:jsp Page被初始化的时候调用该方法,并且该方法仅在初始化时执行一次,所以可以在这里进行一些初始化的参数配置等一次性工作,由作者创建

_jspDestroy(){}:jsp Page由于某种原因被关闭的时候调用该方法,由作者创建

_jspService(){}:由jsp容器自动创建的处理jsp Page的方法,由jsp容器创建,不能由作者定义。

当jsp文件第一次被处理时,他会被转化成一个servlet文件。然后再创建一个 Servlet对象,首先执行_jspInit()方法进行初始化操作,由于整个执行过程_jspInit()方法只执行一次,所以可以在这个方法中进行一些必要的操作比如连接数据库,初始化部分参数等等,接着执行_jspService()方法,对客户端的请求进行处理,对每一个请求会创建一个线程,如果同时有多个请求需要处理的话就会创建多个线程。由于servlet长期贮存与内存中,所以执行速度快,但是由于初始化需要编译,所以第一次执行还是比较慢的,如果由于某种原因导致jsp网页关闭或者销毁的话会执行jspDestroy()方法。

JSP的多线程思考

当多个用户请求一个JSP页面时,Tomcat服务器为每个客户启动一个线程,该线程负责执行常住内存的字节码文件来响应客户的请求。这些线程有Tomcat服务器来管理。

这些线程共享JSP页面的成员变量(实例变量),因此任何一个用户对JSP页面成员变量的操作,都会影响到其他用户,这可能导致线程的不安全。为了保证线程安全,我们不要使用(实例变量+类变量),就这么简单。也可以使用synchronized同步方法,但是这样效率不高。

方法中的局部变量是不会影响线程安全的,因为他们是在栈上分配空间,而且每个线程都有自己私有的栈空间,运行在不同线程中的java程序片中的局部变量互不干扰。

JSP执行过程详解的更多相关文章

  1. Hadoop MapReduce执行过程详解(带hadoop例子)

    https://my.oschina.net/itblog/blog/275294 摘要: 本文通过一个例子,详细介绍Hadoop 的 MapReduce过程. 分析MapReduce执行过程 Map ...

  2. ping命令执行过程详解

    [TOC] ping命令执行过程详解 机器A ping 机器B 同一网段 ping通知系统建立一个固定格式的ICMP请求数据包 ICMP协议打包这个数据包和机器B的IP地址转交给IP协议层(一组后台运 ...

  3. Hadoop学习之Mapreduce执行过程详解

    一.MapReduce执行过程 MapReduce运行时,首先通过Map读取HDFS中的数据,然后经过拆分,将每个文件中的每行数据分拆成键值对,最后输出作为Reduce的输入,大体执行流程如下图所示: ...

  4. mysql中SQL执行过程详解与用于预处理语句的SQL语法

    mysql中SQL执行过程详解 客户端发送一条查询给服务器: 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一阶段. 服务器段进行SQL解析.预处理,在优化器生成对应的 ...

  5. MySQL 语句执行过程详解

    MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...

  6. IIS 内部运行机制及Asp.Net执行过程详解

    一直以来对一个Asp.net页面穿过IIS后就返回给浏览器一个HTML页面感觉很是神奇.虽然做技术这么长时间了,也曾经大致了解过一点来龙去脉,但是如果你真的问起我比较详细的过程,我还真的回答不上来,好 ...

  7. PHP - pcntl_fork() 执行过程详解

    <?php   $pid = pcntl_fork();if ($pid == -1){    die("could not fork");}elseif($pid == 0 ...

  8. Java的初始化块及执行过程详解

    问题:Java对象初始化方式主要有哪几种?分别是什么?针对上面的问题,想必大家脑海中首先浮现出的答案是构造器,没错,构造器是Java中常用的对象初始化方式. 还有一种与构造器作用非常相似的是初始化块, ...

  9. [转]MySQL查询语句执行过程详解

    Mysql查询语句执行原理 数据库查询语句如何执行?语法分析:首先进行语法分析,对使用sql表示的查询进行语法分析,生成查询语法分析树.语义检查:检查sql中所涉及的对象以及是否在数据库中存在,用户是 ...

随机推荐

  1. 第八篇、SVN在Mac上使用

    Mac自带svn软件 1.创建目录 svn-repository/source-code 2.svnadmin create /Users/liaokailin/svn-repository/sour ...

  2. java的动态绑定与双分派(规避instanceof)

    1. 动态绑定的概念 指程执行期间(而不是在编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法 . 例如: package org.demo.clone.demo; public c ...

  3. PHP数据库

    目录 1.创建数据库连接 2.创建数据库 3.选择数据库 4.设置当前连接使用的字符编码 5.创建表 6.插入数据 7.取得数据查询结果 8.关闭连接 1.创建数据库连接 //mysql_connec ...

  4. js 判断时间,满足执行框架

    // 8点到早上19点关var curr = new Date();var time = curr.getHours(); if ( time >=0 && time <2 ...

  5. window 配置 sendmail

    从http://glob.com.au/sendmail/下载sendmail.zip 解压sendmail.zip到目录下(最好使用短路径,长路径会导致问题的出现),我安装的路径是: E:\wamp ...

  6. js+css3 动画数字累加

    css: .kk{ width:100px; height:100px; display:inline-block; color:red; text-align:center; position: r ...

  7. Android SlidingMenu开源库及其使用

    极客学院教程: http://www.jikexueyuan.com/course/61_5.html?ss=1 1. SlidingMenu开源库的配置 2. SlidingMenu 的使用 --- ...

  8. Java高精度学习第三弹——ACM中使用JAVA的详细介绍

    Chapter I. Java的优缺点各种书上都有,这里只说说用Java做ACM-ICPC的特点: (1) 最明显的好处是,学会Java,可以参加Java Challenge . (2) 对于熟悉C/ ...

  9. Struts2 Tomcat的配置

    1. 下载Struts2包,网站http://struts.apache.org/download.cgi#struts2315 2. 将struts-2.3.15-all.zip 包解压到本地 3. ...

  10. 关于form.item不兼容的问题

    form.item()能在IE下运行,在firefox中会报脚本错误,没有这个函数. 可以使用 Form.elements 方法得到 HTMLCollection 后再使用 item 方法获取表单内元 ...