在服务器端写个JSP,经过Tomcat中的JSP解析器将jsp文件解析成Servlet程序,也就是.java程序了,.java再有JDK编译成.class文件加载到内存中去。
实际上生成的Servlet对象有且仅有一个,也就是说,只要有一个客户端访问了服务器上的这个Servlet资源,服务器就为这个客户端起一个线程,
用来操纵这个Servlet对象!这里就涉及到一个问题,为什么jsp声明很少用,比如<%! int a = 5; %>,因为这个jsp声明被转换成Servlet程序后就成了成员变量了。
既然是单例,那成员变量就会被多个线程共享共同操作了,变来变去了都,如果有多个客户端访问这个Servlet对象,则这个成员变量大家都操作,不好不好。
所以很多情况下使用jsp定义<% int b = 5; %>,jsp定义的变量就成了_jspService(HttpServletRequest req, HttpServletResponse resp)中的成员变量了,注意一下,
这个_jspService()方法是jsp转换成servlet程序后,在servlet中的方法,它就等价于我们自己写个Servlet类后重写了doGet方法一样,
因为每次客户端访问我们自己写的servlet程序,就会调用一次doGet方法,所以,用户每次访问一个jsp资源,就会调用_jspService()方法了。
下面用线程和单例模式的代码来模拟一下Servlet单例模式的现象吧,很简单的小代码:
class Test
{
}
class ServletSimulation //这是一个即将被线程操作的类,等价于java web中的Servlet类。它是单例的
{
}
class MyThread implements Runnable
{
}
输出结果为:
a = 5
b = 5
------
a = 4
b = 5
------
a = 3
b = 5
------
由此可见,如果在一个jsp页面
<body>
</body>
每一次刷新一次页面,就等于调用了一次_jspService()方法,所得到的结果和上面结果一样。