• Servlet 学习


    一、Servlet为何物?

          Servlet(Server Applet),全称Java Servlet,暂无中文译文。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。
          Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。

    二、Servlet的实现过程

          最早支持 Servlet 技术的是 JavaSoft 的 Java Web Server。此后,一些其它的基于 Java 的 Web Server 开始支持标准的 Servlet API。Servlet 的主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。这个过程为:
          1、客户端发送请求至服务器端;
          2、服务器将请求信息发送至 Servlet;
          3、Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
          4、服务器将响应返回给客户端。


          Servlet 看起来像是通常的 Java 程序。Servlet 导入特定的属于 Java Servlet API 的包。因为是对象字节码,可动态地从网络加载,可以说 Servlet 对 Server 就如同 Applet对 Client 一样,但是,由于 Servlet 运行于 Server 中,它们并不需要一个图形用户界面。从这个角度讲,Servlet 也被称为 FacelessObject。
          一个 Servlet 就是 Java 编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然 Servlet 可以对任何类型的请求产生响应,但通常只用来扩展 Web 服务器的应用程序。

    三、Servlet生命周期

          1、客户端请求该 Servlet;
          2、加载 Servlet 类到内存;
          3、实例化并调用init()方法初始化该 Servlet;
          4、service()(根据请求方法不同调用doGet() 或者 doPost(),此外还有doHead()、doPut()、doTrace()、doDelete()、doOptions()、destroy()。
          5、加载和实例化 Servlet。这项操作一般是动态执行的。然而,Server 通常会提供一个管理的选项,用于在 Server 启动时强制装载和初始化特定的 Servlet。

          对于更多的客户端请求,Server 创建新的请求和响应对象,仍然激活此 Servlet 的 service() 方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用 init() 方法。一般 Servlet 只初始化一次(只有一个对象),当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方法。

    四、建议

          在 Web 应用程序中,一个 Servlet 在一个时刻可能被多个用户同时访问。这时 Web 容器将为每个用户创建一个线程来执行 Servlet。如果 Servlet 不涉及共享资源的问题,不必关心多线程问题。但如果 Servlet 需要共享资源,需要保证 Servlet 是线程安全的。
          下面是编写线程安全的 Servlet 的一些建议:
          (1)用方法的局部变量保存请求中的专有数据。对方法中定义的局部变量,进入方法的每个线程都有自己的一份方法变量拷贝。任何线程都不会修改其他线程的局部变量。如果要在不同的请求之间共享数据,应该使用会话来共享这类数据。
          (2)只用 Servlet的成员变量来存放那些不会改变的数据。有些数据在 Servlet 生命周期中不发生任何变化,通常是在初始时确定的,这些数据可以使用成员变量保存,如数据库连接名称、其他资源的路径等。
          (3)对可能被请求修改的成员变量同步。有时数据成员变量或者环境属性可能被请求修改。当访问这些数据时应该对它们同步,以避免多个线程同时修改这些数据。
          (4)如果 Servlet 访问外部资源,那么需要同步访问这些资源。例如,假设 Servlet 要从文件中读写数据。当一个线程读写一个文件时,其他线程也可能正在读写这个文件。文件访问本身不是线程安全的,所以必须编写同步访问这些资源的代码。

          在编写线程安全的 Servlet 时,下面两种方法是不应该使用的:
          (1)在 Servlet API 中提供了一个 SingleThreadModel 接口,实现这个接口的 Servlet 在被多个客户请求时一个时刻只有一个线程运行。这个接口已被标记不推荐使用。
          (2)对 doGet() 或doPost() 方法同步。如果必须在 Servlet 中使用同步代码,应尽量在最小的代码块范围上进行同步。同步代码越小,Servlet 执行得才越好。

    五、编程实践

         1、访问Servlet的URL映射配置

      为了达到保密性和多样性。我们把servlet程序映射到一个URL地址上,客户端就可以通过URL地址访来问web服务器中的资源。当把一个servlet映射到多个不同URL地址,就可以分配给客户端不一样的URL地址。这个工作由WebContent/WEB-INF/web.xml文件来完成。
      <servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>和<servlet-class>,分别用于指定Servlet的注册名称和Servlet的完整类名。
          <servlet-mapping>元素用于把一个已注册的Servlet映射到一个URL地址上,它包含有两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的客户端访问URL地址。例如:

    <!-- 注册 Servlet -->

    <servlet>
    <servlet-name>ServletDemo</servlet-name>
    <servlet-class>zs_servlet.ServletDemo</servlet-class>
    </servlet>

    <!-- 映射 Servlet -->

    <servlet-mapping>
    <servlet-name>ServletDemo</servlet-name>
    <url-pattern>/ServletDemo2</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>ServletDemo</servlet-name>
    <url-pattern>/WebContent/*</url-pattern><!-- 通配符 -->
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>ServletDemo</servlet-name>
    <url-pattern>*.do</url-pattern><!-- 通配符 -->
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>ServletDemo</servlet-name>
    <url-pattern>/</url-pattern><!-- 缺省值 -->
    </servlet-mapping>

         2、访问Servlet的线程安全问题

          当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的请求创建一个线程,并在这个线程上调用Servlet的service方法,因此如果service方法访问了全局变量,就有可能引发线程安全问题。
    比如在Servlet类中定义了全局变量LoginCount,每一个客户端都有可能修改其值,导致数据错乱。可以加锁实现排队形式单线程修改,此方法对并发多请求则遇到瓶颈。

     synchronized (this) {
    //do something...
    }

          针对Servlet的线程安全问题,Sun公司是提供有解决方案的:让Servlet去实现一个SingleThreadModel接口,如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。

  • 相关阅读:
    Linux常用命令
    IBM Java多线程 1. 线程基础
    IBM Java多线程 6.其它线程 API 详细信息
    Jakarta Commons Logging学习笔记
    Linux 下存放ssh信息的文件位置
    ArrayList的使用方法
    JAVA基础--JAVA中的反射机制详解
    使用 Bash shell脚本进行功能测试
    log4j详细解
    Eclipse Template用法探讨
  • 原文地址:https://www.cnblogs.com/johsan/p/6957376.html
Copyright © 2020-2023  润新知