1.Servlet
![](/icons/97262de.gif)
生命周期
Servlet
![](/icons/97262de.gif)
生命周期是由Web容器负责
![](/icons/97262de.gif)
,当客户端第
![](/icons/97262yi.gif)
次请求Servlet时,容器负责
![](/icons/97262chushi.gif)
化Servlet,也就是例子化这个Servlet类.以后这个例子就负责客户端
![](/icons/97262de.gif)
请求,
![](/icons/97262yi.gif)
般不会再例子化其他Servlet类,也就是有多个线程在使用这个例子.Servlet的所以比CGI效率高就是
![](/icons/97262yinwei.gif)
Servlet是多线程
![](/icons/97262de.gif)
.如果该Servlet被声明为单线程模型
![](/icons/97262de.gif)
话,容器就会维护
![](/icons/97262yi.gif)
个例子池,那么将存在多个例子.
2.Servlet
![](/icons/97262de.gif)
线程安全
Servlet规范标准已经声明Servlet不是线程安全
![](/icons/97262de.gif)
,所以在开发Servlet
![](/icons/97262de.gif)
时候要注要这个问题.这里以
![](/icons/97262yi.gif)
个现实
![](/icons/97262de.gif)
模型来介绍说明问题,先定义
![](/icons/97262yi.gif)
个Servlet类,再定义
![](/icons/97262yi.gif)
个SmulateMultiThread类和WebContainer类.
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//该类模拟多线程Servlet
![](/icons/97262de.gif)
情况
public
![](/icons/97262class.gif)
SmulateMultiThread implements Runnable{
public SmulateMultiThread
![](/icons/97262kh.gif)
{
}
public
![](/icons/97262static.gif)
void
![](/icons/97262main.gif)
(String
![](/icons/97262zhk2.gif)
args) {
//处理100个请求
for(
![](/icons/97262int.gif)
i=0;i<100;i
![](/icons/97262jiajia.gif)
)
{
![](/icons/97262new.gif)
Thread(
![](/icons/97262new.gif)
SmulateMultiThread
![](/icons/97262kh.gif)
).start
![](/icons/97262kh.gif)
;
}
}
public void run
![](/icons/97262kh.gif)
{
HttpServletRequest request=null;
HttpServletResponse response=null;
try {
WebContainer.getServlet
![](/icons/97262kh.gif)
.doGet(request, response);
}
catch (IOException ex) {
}
catch (ServletException ex) {
}
}
}
//这是
![](/icons/97262yi.gif)
个Servlet类
![](/icons/97262class.gif)
UnsafeServlet extends HttpServlet{
private String unsafe;
public void init
![](/icons/97262kh.gif)
throws ServletException {
}
//Process the HTTP Get request
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
unsafe=Thread.currentThread
![](/icons/97262kh.gif)
.getName
![](/icons/97262kh.gif)
;
![](/icons/97262System.gif)
.out.pr
![](/icons/97262int.gif)
ln(unsafe);
}
}
//这个是容器类
![](/icons/97262class.gif)
WebContainer{
private
![](/icons/97262static.gif)
UnsafeServlet us=
![](/icons/97262new.gif)
UnsafeServlet
![](/icons/97262kh.gif)
;
public
![](/icons/97262static.gif)
UnsafeServlet getServlet
![](/icons/97262kh.gif)
{
![](/icons/97262return.gif)
us;
}
}
输出了100区别
![](/icons/97262de.gif)
线程名称,如果有100个请求同时被这个Servlet处理
![](/icons/97262de.gif)
话,那么unsafe就可能有100种去值,最后客户端将得到
![](/icons/97262cuowu.gif)
![](/icons/97262de.gif)
值.比如客户1请求
![](/icons/97262de.gif)
线程名为thread-1,但是返回给他
![](/icons/97262de.gif)
可能是thread-20.表现在现实中就是,我登陆
![](/icons/97262de.gif)
用户名是user1,登陆后变成了user2.
那么怎样才能是Servlet安全呢,凡是多个线程可以共享
![](/icons/97262de.gif)
就不要使用(例子变量+类变量),就这么简单.也可以使用synchronized同步思路方法,但是这样效率不高,还可以使用单线程模型,这样
![](/icons/97262de.gif)
话效率就更低了,100个请求同时来
![](/icons/97262de.gif)
时候就要例子化100个例子.
思路方法中
![](/icons/97262de.gif)
临时变量是不会影响线程安全
![](/icons/97262de.gif)
,
![](/icons/97262yinwei.gif)
他们是在栈上分配空间,而且每个线程都有自己私有
![](/icons/97262de.gif)
栈空间.
3.JSP中线程安全
JSP
![](/icons/97262de.gif)
本质是Servlet,所有只要明白了Servlet
![](/icons/97262de.gif)
安全问题,JSP
![](/icons/97262de.gif)
安全问题应该很容易理解.使用声明
![](/icons/97262de.gif)
变量是Servlet
![](/icons/97262de.gif)
例子变量,不是线程安全
![](/icons/97262de.gif)
,其他都是线程安全
![](/icons/97262de.gif)
.
<%! String unsafeVar; %> //不是线程安全
![](/icons/97262de.gif)
<% String safeVar; %> // 线程安全
![](/icons/97262de.gif)
整理总结:线程安全问题主要是由例子变量造成
![](/icons/97262de.gif)
,不管在Servlet还是JSP,或者在Struts
![](/icons/97262de.gif)
Action里面,不要使用例子变量,任何思路方法里面都不要出现例子变量,你
![](/icons/97262de.gif)
![](/icons/97262chengxu.gif)
就是线程安全