今天忽然看到几篇博客,一个说 Servlet 是单例的,一个说不是单例的,于是自己试下。
废话不说上代码:
web.xml
<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>com.xdnote.test.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
TestServlet.java
private int time=0;
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
String id=request.getParameter("id");
this.time=Integer.parseInt(request.getParameter("time"));
System.out.println(id+":"+time);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(id+":"+time);
}
先请求test?id=6&time=6000
过1秒后再请求 test?id=10&time=10000
结果如下:
6:6000
10:10000
6:10000
10:10000
可见第三个6秒时的time被改为了10000,说明servlet是单例的。
结果就是这样,虽然如果不用Thread,很少重现,但一但出现就会摸不着头脑。
这样的代码让我马上想起了Struts。Struts2里面使用 Action 和 Servlet 有点类似,执行时会先 set 操作,由于不是 Servlet 所以不会单例。但是目前极度崇尚手 ssh 框架会让你不加思索的去配置一个 Spring,谁都知道 Spring 的核心是单例,减少 new 操作提高性能。可能就会这么写,把一个action变成单例。
<!-- struts.xml -->
<action name="testAction" class="testAction"></action>
<!-- application.xml -->
<bean id="testAction" class="com.xdnote.action.testAction"></bean>
很多书或文章都会教人这样结合 Struts 和 Spring,但用的时候就得注意了!!!,这里要是出了问题,重现也比较麻烦,损失还是相当大的。