理解Servlet的生命周期的重点:非线程安全
初学Java Web 开发的者,常会忽略Servlet的特性:非线程安全。
所谓线程安全就是:每一次调用是独立的结果,不应当受其它调用的影响。从代码上看就是:函数执行中使用的变量都应该是临时的,不应该是全局变量或者实例成员变量,简单的说就是:执行函数必须是无状态执行。
再来说为什么Servlet是非线程安全:因为Servlet的所谓生命周期是由Web服务器的Servlet容器管理的,Web服务器对相同的Servlet 只会实例化一次,也就是说同一个URL地址的多次请求,都是由同一个Servlet的实例在执行。所以,响应请求的函数一定要做到无状态执行。
下面这个例子,演示了一个错误的代码:
public class HelloWorld extends HttpServlet { private PrintWriter pr; private void getWriter(HttpServletResponse resp) throws IOException { pr = resp.getWriter(); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { getWriter(resp);//问题所在,产生了状态变量 try { Thread.sleep(9000); } catch (InterruptedException e) { e.printStackTrace(); } out("getQueryString:"+req.getQueryString());//问题所在,使用了状态变量 } private void out(String s) { pr.write(gp(s)); } private String gp(String s) { return "<p>" + s + "<p>"; } }
开两个浏览窗口,先在第一个窗口的请求:http://127.0.0.1/hello?name=mike,
然后再在第二个窗口的请求:http://127.0.0.1/hello?name=jonh
会观察到第一个窗口没有任何输出,第二个窗口输出是:
getQueryString:name=mike getQueryString:name=jonh
之所以出现如此异常现象,就是因为 pr 是一个状态变量,第二次请求时,pr 被改写了,所以每一次请求的输出就定向到第二个窗口了。
servlet 是这样,同理JSP也一样,因为JSP本质上是Servlet.
相关推荐
三动 2020-06-21
shayuchaor 2020-06-07
Hy 2020-11-13
xrslt 2020-11-06
yutian0 2020-10-26
杨树 2020-09-21
zhuyonge 2020-08-01
zhuyonge 2020-07-26
xiaoemo0 2020-07-18
fraternityjava 2020-06-26
luohui 2020-06-26
dxyadc 2020-06-26
luohui 2020-06-21
fengyun 2020-06-14
fraternityjava 2020-06-14
waitui00 2020-06-14
fraternityjava 2020-06-10