Java 为什么ApacheServlet是单例的?

Java 为什么ApacheServlet是单例的?,java,servlets,Java,Servlets,如果这个servlet一次接收多个请求,会发生什么 我们面临着反应不匹配的问题。这是个问题吗?当然是个问题。servlet是一个单例。同一个servlet实例用于处理对此servlet的所有请求。当然,这些请求是同时处理的。这意味着,如果您这样做,thread1将使用thread2通常处理的请求和响应。您的web应用程序容器只加载servlet的一个实例 要编写线程安全的servlet,几乎不应该使用实例变量。将请求和响应设置为实例变量完全是错误的。servlet的实例不属于单个请求 如果需要将

如果这个servlet一次接收多个请求,会发生什么


我们面临着反应不匹配的问题。这是个问题吗?当然是个问题。servlet是一个单例。同一个servlet实例用于处理对此servlet的所有请求。当然,这些请求是同时处理的。这意味着,如果您这样做,thread1将使用thread2通常处理的请求和响应。

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

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


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

这肯定会产生问题,任何实例变量都是共享的,因为servlet是单实例的,所以并发请求和响应对象将被覆盖

这是一个问题,不建议将HttpServletRequest/HttpServletResponse声明为实例变量。实际上,Servlet正在实现单线程模型,这意味着只创建一个Servlet实例。每个请求一个线程。所以,如果它们有许多请求,那么thr必须有许多线程,每个线程共享同一个servlet实例,这将产生数据不匹配或数据不一致的问题。线程将在相同的实例上工作。

引用Servlet规范

每个请求和响应对象仅在servlet的服务方法范围内或过滤器的doFilter方法范围内有效。容器通常是循环使用的 请求对象,以避免请求对象的性能开销 创造开发人员必须知道,维护对请求对象的引用 不建议超出上述范围,因为它可能具有不确定性
结果

发生的情况是,您的servlet立即变为不可重入,并且在多个客户端同时调用它时肯定会失败。你不能这样做。

不要那样做。真正地不要这样做。这让世界陷入了一个黑暗的境地:学习servlet的工作原理:尝试编写一个没有实例变量的非平凡servlet;servlet必须在某个点将控制权委托给某个对象,即服务。您的意思是不要使用非线程安全的实例变量。单线程模型!=单例servlet。单线程模型正是没有人使用的模型,因为它效率太低,只能保证一个线程使用给定的servlet。也不建议使用单线程实现。它已经被弃用了;这个答案没有提供任何价值。正如其他人已经指出的,这部分是错误的。根据定义,servlet不是单例。ServletAPI不会将特定Servlet类的创建限制为单个实例。容器通常会为部署描述符中的每个servlet声明创建一个servlet实例。然而,单例是一种设计模式,它将其类的对象的创建限制为1且仅为1。它们不是GoF模式意义上的单例,但实际上是因为servlet规范要求容器仅为每个servlet声明实例化一个实例。单例不只是GoF设计模式。您是否曾经使用过像Spring或Guice这样的依赖注入框架?从未见过在这种情况下使用singleton?是的,我见过。我试图与GoF对独生子女的定义相关联。对于您的细化,加上1:所以您选择了一个特定的单例定义,并决定servlet不遵循这个特定的定义,因此不是单例?这就像说免费啤酒不是免费的,因为它甚至没有开源许可证。这与OP的问题没有多大关系。如果他在doGet的末尾取消了实例变量,那么请求和响应对象的范围就不会扩展到服务方法之外,但是他仍然会有很大的问题。但仍然如此。如果规范在保存对这些对象的引用时保证了不确定的结果,那么到底为什么要这样做呢?它不能保证任何类似的结果。只要不在服务方法的范围之外使用这些引用,就可以保存任意多的引用。你只需要以线程安全的方式来做。例如,许多框架将对请求的引用存储在ThreadLocal变量中。我学会了,谢谢。实际上,这变成了一场争论,我不想卷入其中。我批评你和我的。谢谢你的澄清,我可没那么想。我只是喜欢捍卫我的观点,仅此而已。
  HttpServletRequest request;
  HttpServletResponse response;

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