名扬数据:关于Servlet和JSP的潜在隐患

不要使用实例变量,线程平安问题主要是由实例变量造成的不论在Servlet和JSP或者在StrutAction里面。任何方法里面都不要出现实例变量,顺序就是线程安全的

1.Servlet和JSP线程安全

先定义一个Servlet类,Servlet规范已经声明Servlet不是线程安全的所以在开发Servlet时候要注要这个问题。这里以一个现实的模型来说明问题。再定义一个SmulateMultiThread类和WebContain类。

2.Servlet生命周期

容器负责初始化Servlet也就是实例化这个Servlet类。以后这个实例就负责客户端的请求,Servlet生命周期是由Web容器负责的当客户端第一次请求Servlet时。一般不会再实例化其他Servlet类,也就是有多个线程在使用这个实例。Servlet之所以比CGI效率高就是因为Servlet多线程的如果该Servlet被声明为单线程模型的话,容器就会维护一个实例池,那么将存在多个实例。


importjavax.servlet.http.HttpServlet 

importjavax.servlet.ServletExcept 

importjavax.servlet.http.HttpServletRequest 

importjavax.servlet.http.HttpServletRespons 

importjava.io.IOExcept 

//该类模拟多线程Servlet情况 

publicclassSmulateMultiThreadimplementsRunnable{ 

publicSmulateMultiThread{ 

publicstaticvoidmainString[]arg{ 

//处置100个请求 

forinti=0i<100i++ 

newThreadnewSmulateMultiThreadstart 

publicvoidrun{ 

HttpServletRequestrequest=nul 

HttpServletResponseresponse=nul 

try{ 

WebContainer.getServletdoGetrequestrespons 

}catchIOExceptionex{ 

catchServletExceptionex{ 

//这是一个Servlet类 

classUnsafeServletextendsHttpServlet{ 

privateStringunsaf 

publicvoidinitthrowsServletException{ 

//ProcesstheHTTPGetrequest 

publicvoiddoGetHttpServletRequestrequestHttpServletResponserespons

throwsServletExceptIOException{ 

unsafe=Thread.currentThreadgetNam 

System.out.printlnunsaf 

//这个是容器类 

classWebContainer{ 

privatestaticUnsafeServletus=newUnsafeServlet 

publicstaticUnsafeServletgetServlet{ 

returnu 

}

如果有100个请求同时被这个Servlet处置的话,输出了100不同的线程名称。那么unsaf就可能有100种去值,最后客户端将得到错误的值。比如客户1请求的线程名为thread-1但是返回给他可能是thread-20.表示在现实中就是登陆的用户名是user1登陆后变成了user2.那么怎样才干是Servlet平安呢,凡是多个线程可以共享的就不要使用(实例变量+类变量)就这么简单。也可以使用synchron同步方法,但是这样效率不高,还可以使用单线程模型,这样的话效率就更低了100个请求同时来的时候就要实例化100个实例。

而且每个线程都有自己私有的栈空间。方法中的临时变量是不会影响线程安全的因为他栈上分配空间。

3.JSP中线程安全

Servlet和JSP平安问题应该很容易理解。使用<%%>声明的变量是Servlet实例变量,JSP实质是Servlet所有只要明白了Servlet平安问题。不是线程安全的其他都是线程安全的

<%StringunsafeVar%>//不是线程安全的 

<%StringsafeVar%>//线程安全的