`

理解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.

分享到:
评论

相关推荐

    servlet线程安全问题

    此外,需要了解 Servlet 的生命周期,以避免在 Servlet 的不同阶段出现问题。例如,在 init 方法中可以执行一些初始化操作,而在 destroy 方法中可以执行一些清理操作。 Servlet 线程安全问题是指在使用 Servlet ...

    servlet与Struts action线程安全问题分析

    Servlet的多线程机制源于其生命周期的管理。当Web容器接收到客户端的首次请求时,会根据web.xml配置文件创建Servlet的一个实例。后续的请求,Web容器通常不会重新创建Servlet实例,而是复用已存在的实例,这就意味着...

    Servlet生命周期

    ### Servlet 生命周期详解 #### 一、概述 Servlet 是 Java Web 开发的核心技术之一,用于处理客户端的 HTTP 请求并返回响应。了解 Servlet 的生命周期对于更好地控制和优化 Web 应用程序至关重要。Servlet 的生命...

    Servlet 生命周期.pdf

    在Servlet生命周期中,init()方法只会被调用一次,service()方法会在每次用户请求时被调用,destroy()方法只会被调用一次,在Servlet生命周期结束时被调用。Servlet生命周期的正确实现是保证Servlet正确运行的关键。

    Servlet笔记,servlet生命周期、定义

    Servlet的生命周期指的是从创建到销毁的过程。这个过程包括以下几个阶段: 1. 初始化阶段:通过调用init()方法来完成,这个方法在Servlet创建后被调用一次。 2. 处理请求阶段:通过调用service()方法处理客户端请求...

    servlet的架构与生命周期

    **Servlet生命周期** Servlet的生命周期分为四个阶段:加载和初始化、服务、销毁和卸载。 1. **加载和初始化**:当Servlet容器首次接收到对Servlet的请求,或者通过web.xml或注解配置明确声明需要加载Servlet时,...

    Servlet线程安全问题.docx

    在Servlet的生命周期中,Tomcat容器会根据需求实例化Servlet并管理其生命周期。当第一个请求到达时,Tomcat会创建Servlet实例,后续的请求将复用同一个实例,这意味着多个线程可能同时访问Servlet的同一实例,从而...

    Servlet生命周期与工作原理

    `init()`方法在整个Servlet生命周期中只被调用一次,通常用来进行一些一次性配置,如加载配置文件、初始化数据库连接池等。 2. **响应客户请求阶段** 当客户发送请求到Servlet时,Servlet容器会调用Servlet的`...

    Web编程(Java )-Servlet的生命周期.doc

    Servlet的生命周期包括四个主要阶段:加载和实例化、初始化、服务以及销毁。在本实验中,我们将通过编写和配置Servlet类来理解这些阶段。...在实际开发中,理解Servlet生命周期有助于优化性能,确保资源的有效利用。

    servlet生命周期

    理解 Servlet 的生命周期对于有效地管理和优化 Web 应用程序至关重要。 #### 二、Servlet 生命周期阶段 Servlet 的生命周期主要分为以下几个阶段: 1. **创建**:当容器启动或接收到客户端的第一次请求时,Servlet...

    Servlet线程同步计数器实验

    在这个实验中,我们将深入理解Servlet生命周期、线程模型以及线程同步的概念。 Servlet是Java EE规范中用于处理HTTP请求的服务端组件。默认情况下,Servlet容器(如Tomcat)会为每个HTTP请求创建一个新的线程来执行...

    深入研究Servlet线程安全性问题

    Servlet的多线程机制源于其生命周期的管理。当首次请求一个Servlet时,Web容器会根据配置文件创建一个Servlet实例。之后的请求通常会复用这个实例,而不是每次都创建新的。这就意味着多个客户端请求可能会共享同一个...

    servlet多线程

    - `ServletRequest`:每个请求对应一个独立的`ServletRequest`对象,因此它是线程安全的,但不应在其生命周期之外保留引用。 3. **使用同步的集合类**:如`Vector`代替`ArrayList`,`Hashtable`代替`HashMap`,以...

    深入研究Servlet线程安全性问题.pdf

    Servlet容器(如Tomcat)负责管理Servlet的整个生命周期,包括初始化、服务请求和销毁。当客户端首次请求某个Servlet时,容器会创建该Servlet的实例;随后的请求则由容器通过多线程的方式复用这个单一实例来处理。这...

    Servlet的生命周期1

    总之,Servlet生命周期的管理是Java Web应用程序中的关键环节,理解这三个阶段以及如何在每个阶段操作是开发高效、稳定Web服务的基础。通过正确地实现`init()`, `service()`, 和 `destroy()`方法,开发者能够确保...

Global site tag (gtag.js) - Google Analytics