2012-05-19 70 views
-3
HttpServletRequest request; 
    HttpServletResponse response; 

    public void doGet(HttpServletRequest request , HttpServlet response){ 
     this.request = request; 
     this.response = response; 
    } 

如果此servlet一次接收多个请求,会发生什么情况?为什么apache servlet是单身人士?

我们遇到了响应不匹配问题。这是一个问题吗?

+8

不要这样做。真。别。 – skaffman

+1

这使得世界陷入黑洞 –

+0

了解servlet如何工作:http://stackoverflow.com/questions/3106452/how-do-servlets-work-instantiation-session-variables-and-multithreading/3106909#3106909 – BalusC

回答

-2

它是一个问题,绝不建议将HttpServletRequest请求/ HttpServletResponse响应声明为实例变量。实际上Servlet正在实现单线程模型,这意味着只有一个servlet实例被创建。并为每个请求提供一个线程。因此,如果他们有很多请求,那么thr必须是多个线程,并且每个共享相同的servlet实例会导致数据不匹配或数据不一致问题。线程将在相同的实例上工作。

+2

单线程模型!=单例servlet。单线程模型正是模型(没有人使用,因为它效率非常低),以确保只有一个线程使用给定的servlet。 –

+0

也不建议使用“单线程实现”。它已被弃用。 – verisimilitude

+0

-1;这个答案不提供任何价值。正如其他人已经表明,这是部分错误。 – home

2

当然这是一个问题。一个servlet是一个单身人士。同一个servlet实例用于处理对这个servlet的所有请求。并且请求当然是同时处理的。这意味着如果你这样做,thread1将使用通常由thread2处理的请求和响应。

+0

根据定义,Servlet不是单身人士。 Servlet API不会将创建特定的Servlet类限制为单个实例。 Container通常会为部署描述符中的每个servlet声明创建一个servlet实例。而单例是一种设计模式,它将其类的对象的创建限制为1并且仅为1. – verisimilitude

+1

它们不是在GoF模式的含义中的单例,而是它们有效地是因为容器是**必需的** servlet规范只为每个servlet声明实例化一个实例。单身并不仅仅是GoF的设计模式。你有没有使用像Spring或Guice这样的依赖注入框架?从未见过单身人士在这方面使用? –

+0

是的,我有。我试图将GoF的单身人士的定义联系起来。并加1为你的阐述:) – verisimilitude

4

您的Web应用程序容器只加载一个servlet实例。

要编写线程安全的servlet,几乎不应该使用实例变量。将请求和响应设置为实例变量显然是错误的。该servlet的实例不属于单个请求。

如果您需要使请求或响应的元素可用于其他方法,请将它们传递给这些方法。你不需要它们作为实例变量。

+1

尝试编写一个不带实例变量的非平凡servlet; servlet必须在某个时间点将控制委派给* something *(即服务)。你的意思是说不使用非线程安全的实例变量。 – skaffman

0

这肯定会造成问题,任何实例变量作为servlet共享为单例,因此并发请求和响应对象将被覆盖。

1

引用Servlet规范

“每个请求和响应对象是有效的只有一个servlet的服务的方法的范围内,或一个过滤器的doFilter方法的范围之内。容器,以避免通常回收 请求对象请求对象 创建的性能开销。开发者必须意识到,维持引用请求对象 上述范围之外,不推荐,因为它可能有不确定的 结果。“

+0

这与OP的问题没有多大关系。如果他在'doGet()'末尾取消了实例变量,那么请求和响应对象的范围就不会在服务方法之外扩展,但他仍然会遇到很大的问题。 –

+0

合理。但仍然。如果规范保证了保存对这些对象的引用的不确定结果,为什么要这样做呢? – verisimilitude

+0

它不保证这种类型。您可以保存尽可能多的引用,只要您不要在服务方法范围之外使用这些引用。你只需要以线程安全的方式来完成。例如,许多框架在ThreadLocal变量中存储对请求的引用。 –

0

发生什么事是你的servlet instan tly变得不可重入,并且在第一次同时被更多的客户端调用时肯定会失败。你不能这样做。