Servlet容器将Servlet动态地加载到服务器上。HTTP Servlet使用HTTP请求和HTTP响应标题与客户端进行交互。因此Servlet容器支持请求和相应所用的HTTP协议。Servlet应用程序体系结构如图1.6所示。
图1.6说明客户端对Servlet的请求首先会被HTTP服务器接收,HTTP服务器将客户的HTTP请求提交Servlet容器,Servlet容器调用相应的Servlet,Servlet作出的响应传递到Servlet容器,并进而由HTTP服务器将响应传输给客户端。Web服务器提供静态内容并将所有客户端对Servlet作出的请求传递到Servlet容器。
我们已经学习过Tomcat,它是一个小型的轻量级应用服务器,在中小型系统和并发用户不是很多的情况下被广泛应用,和IIS、Apache一样,具有处理HTML的功能(但处理静态HTML的能力不如Apache强),同时,它还是一个Servlet和JSP容器,开发和调试JSP、Servlet的首选。对于图1.6,Tomcat就是HTTP服务器和Servlet容器两个部分。
Servlet是实现javax.servlet.Servlet接口的对象。大多数Servlet通过从GenericServlet或HttpServlet类进行扩展来实现。Servlet API包含于两个包中,即javax.servlet和javax.servlet.http。下边我们分别来介绍。
Ø javax.servlet
接口 |
|
ServletConfig |
定义了在Servlet初始化的过程中由Servlet容器传递给Servlet的配置信息对象 |
ServletContext |
定义Servlet使用的方法以获取其容器的信息 |
ServletRequest |
定义一个对象封装客户向Servlet的请求信息 |
ServletResponse |
定义一个对象辅助Servlet将请求的响应信息发送给客户端 |
Servlet |
定义所有Servlet必须实现的方法 |
类 |
|
ServletInputStream |
定义名为readLine()的方法,从客户端 读取二进制数据 |
ServletOutputStream |
向客户端发送二进制数据 |
GenericServlet |
抽象类,定义一个通用的、独立于底层协议的Servlet |
Ø javax.servlet.http
接口 |
|
HttpSession |
用于标识客户端并存储有关客户端的信息 |
HttpSessionAttributeListener |
这个侦听接口用于获取会话的属性列表的改变的通知 |
HttpServletRequest |
扩展ServletRequest接口,为HTTP Servlet提供HTTP请求信息 |
HttpServletResponse |
扩展ServletResponse接口,提供HTTP特定的发送响应的功能 |
类 |
|
HttpServlet |
扩展了GenericServlet的抽象类,用于扩展创建Http Servlet |
Cookie |
创建一个Cookie,用于存储Servlet发送给客户端的信息 |
在这里,我们需要详细了解下HttpServletRequest获得参数名和参数值的方法。
getParameter(String key) |
返回一个字符串,获得name和key一样的表单控件的数据,如果有重复的name,则返回第一个的值。 |
getParameterValues(String key) |
返回一个字符串数组,获得name和key一样的表单控件的数据,但相同name的控件会有多个,如同名的多个checkbox等。 |
getParameterMap() |
返回一个包含所有参数的Map,为key-String[]模式,即,key是表单控件的name,同时,为了防止有重复name的控件存在,每个name对应的值是一个字符串数组。 |
getParameterNames() |
返回一个枚举类型值,返回所有表单中所有表看控件的name。 |
图1.2
这一节我们来讲讲Servlet的生命周期,Servlet的生命周期如图1.1所示。
Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示。
Servlet的生命周期包含了下面4个阶段:
Ø 加载和实例化
Servlet容器负责加载和实例化Servlet。当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Servlet实例。当Servlet容器启动后,它必须要知道所需的Servlet类在什么位置,Servlet容器可以从本地文件系统、远程文件系统或者其他的网络服务中通过类加载器加载Servlet类,成功加载后,容器创建Servlet的实例。因为容器是通过Java的反射API来创建Servlet实例,调用的是Servlet的默认构造方法(即不带参数的构造方法),所以我们在编写Servlet类的时候,不应该提供带参数的构造方法。
Ø 初始化
在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象。初始化的目的是为了让Servlet对象在处理客户端请求前完成一些初始化的工作,如建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只被调用一次。在初始化期间,Servlet实例可以使用容器为它准备的ServletConfig对象从Web应用程序的配置信息(在web.xml中配置)中获取初始化的参数信息。这样servlet的实例就可以把与容器相关的配置数据保存起来供以后使用,在初始化期间,如果发生错误,Servlet实例可以抛出ServletException异常,一旦抛出该异常,servlet就不再执行,而随后对它的调用会导致容器对它重新载入并再次运行此方法。
Ø 请求处理
Servlet容器调用Servlet的service()方法对请求进行处理。要注意的是,在service()方法调用之前,init()方法必须成功执行。在service()方法中,通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。对于HttpServlet类,该方法作为HTTP请求的分发器,这个方法在任何时候都不能被重载。当请求到来时,service()方法决定请求的类型(GET、POST、HEAD、OPTIONS、DELETE、PUT、TRACE),并把请求分发给相应的处理方法(doGet()、doPost()、doHead()、doOptions()、doDelete()、doPut()、doTrace())每个do方法具有和第一个service()相同的形式。我们常用的就是doGet()和doPost()方法,为了响应特定类型的HTTP请求,我们必须重载相应的do方法。如果Servlet收到一个HTTP请求而你没有重载相应的do方法,它就返回一个说明此方法对本资源不可用的标准HTTP错误。
Ø 服务终止
当容器检测到一个Servlet实例应该从服务中被移除的时候,容器就会调用实例的destroy()方法,以便让该实例可以释放它所使用的资源,保存数据到持久存储设备中。当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收。如果再次需要这个Servlet处理请求,Servlet容器会创建一个新的Servlet实例。
在整个Servlet的生命周期过程中,创建Servlet实例、调用实例的init()和destroy()方法都只进行一次,当初始化完成后,Servlet容器会将该实例保存在内存中,通过调用它的service()方法,为接收到的请求服务。
Ø HTTP协议定义了GET和POST两种请求方法,POST方法对请求发送的数据量没有限制。
Ø Servlet允许用户在服务器上运行Java代码和生成动态内容。
Ø Servlet运行于Servlet容器中。
Ø 扩展HttpServlet类的Servlet必须覆盖如下至少一个方法:doGet、soPost、doPut、doDelete、init、destroy和getServletInfo。
Ø Servlet声明周期包含三种方法:init()、service()和destroy()。
Ø Servlet API包含在两个包中,javax.servlet和javax.servlet.http。
Ø 通过从GenericServlet类或HttpServlet类扩展,可以编写Servlet。