Java Servlet Specification 3.0 之 the servlet interface

来源:互联网 发布:win2008r2装sql 编辑:程序博客网 时间:2024/04/29 18:11





Servlet接口是Java Servlet API中的最重要的接口。所有实现这个接口的servlet要不直接实现,或者更一般的是继承已经实现这个接口的类。直接实现servlet接口的有两个类分别是:GenericServlet和HttpServlet。对于大多数而言,直接继承HttpServlet来实现自己的Servlet。


2.1 请求处理方法

          Servlet接口定义了一个service方法来处理客户端请求。每次Servlet容器根据请求的路径找到对应的Servlet实例的时候就会调用这个方法。

          web应用程序中的并发请求的处理需要web开发者设计的Servlets能够使service方法在某个时间段内处理多个线程的执行。

          一般而言,web容器通过不同的线程来执行service方法来处理同一个Servlet的并发请求。

  

         2.1.1 HTTP指定请求处理方法

                    HttpServlet抽象子类除了实现了Servlet接口外,还额外添加了其他的方法,这些方法是:

                            doGet 处理HTTP GET请求

                            doPost 处理HTTP POST请求

                            doPut 处理HTTP PUT请求

                            doDelete 处理HTTP DELETE请求

                            doHead 处理HTTP HEAD请求

                            doOptions 处理HTTP OPTIONS请求

                           doTrace 处理HTTP TRACE请求

                 

                  一般而言 当开发基于HTTP的Servlet的时候,一个Servlet开发人员仅仅关注doGet和doPost方法。其他的方法用于与HTTP编程相似的开发人员使用。


          2.1.2 额外的方法

                       doPut和doDelete方法允许Servlet开发人员支持HTTP/1.1客户端,其部署了这些功能。doHead方法是HttpServlet中doGet的特殊形式,仅仅返回数据头信息。doOptions方法响应Servlet支持的HTTP方法。doTrace方法产生了一个响应,其包含了TRACE请求的数据头的所有实例。


          2.1.3 支持有条件的GET

                        HttpServlet接口定义了getLastModified方法来支持有条件的GET操作。一个有条件的GET操作请求一个资源,其在一个指定的时间内发送。在是当地条件下,这个方法的实现可能有助于网络资源的有效利用。


           2.1.4  实例的数量

             Servlet声明通过第八章“Annotions and pluggablity”或者是web 应用程序的包含的Servlet的部署描述符,如同第十四章描述的,“Deployment Descriptor”,控制Servlet容器提供的Servlet实例的数量。

             对于一个不是部署在于分布式环境中的Servlet,Servlet容器必须仅仅使用一个Servlet的实例。然而,对于对于实现了SingleThreadModel接口的Servlet,Servlet容器可能实例化多个实例处理大量请求加载和序列化一个特殊实例的请求。

             部署一个Servlet作为一个应用程序的一部分,一个容器对应JVM 只有一个Servlet声明的实例。然而,如果在分布式应用程序中的Servlet实现了SingleThreadModel接口,容器可能在其每个JVM中安装Servlet的多个实例。



        2.2.1   Single Thread Model

          SingleThreadModel接口保证一次只有一个线程执行给定Servlet实例的service方法。注意此仅仅适用于单个servlet实例,因为容器可能选择池化这些对象。能够在同一时间访问多个servlet实例的对象,比如HttpSession的实例,在任何特别的时间,对于多个servlet都能访问,包括实现了SingleThreadModel的那些。

          鼓励开发人员使用其他方式解决那些事情,来替换这个接口的实现,比如一个实例变量的使用或者同步代码块来访问那些资源。SingleThreadModel接口在现有规范中的已经过时了。


   2.3  Servlet的生命周期

             一个Servlet由生命周期来管理。其定义了如何加载和安装Servlet,处理客户端的请求,和从service中移除。生命周期由API中的javax.servlet.servlet接口中的init,service和destory方法表示。所有其他接口必须直接或者间接实现GenericServlet和HttpServlet这些抽象类。

            

           2.3.1  加载和安装

              Servlet容器负责加载和安装Servlets。当容器启动或者一直延迟 直到容器决定Servlet需要一个Servlet来处理一个请求的时候,就会执行加载和执行操作。

              当启动Servlet引擎的时候,所需的Servlet类必须放置于Servlet容器中。Servlet容器使用普通的Java类加载方式来加载Servlet类。这种加载可能是从本地文件系统,一个远程文件系统,或者其他网络服务。


             在加载Servlet类后,容器安装它后使用。


          2.3.2 安装

               在安装完Servlet对象后,容器必须在处理客户端请求前初始化这个Servlet。初始化后Servlet可以读取持续化的配置数据,初始代价昂贵的资源(比如基于JDBC的数据库连接),和执行其他的一次性操作。容器通过调用Servlet接口的init方法来初始化servlet实例,期间还有一个唯一的对象,实现了ServletConfig接口。这个配置对象允许servlet访问web应用程序的配置信息名-值得初始化参数。这个配置对象也使得servlet可以访问一个对象(实现了ServletContext接口),其描述了servlet的运行环境。详情看第四章“Servlet Context”。


           2.3.2.1 初始化时的错误条件

           在初始化期间,Servlet实例会抛出UnavailableException 或者ServletException。在这时,这个Servlet不必放置于活动的service并且必须由Servlet容器释放。当没有成功的初始化的时候destory方法就不必调用了。

           在一个失败的初始化后,容器会安装和初始化一个新的实例。适合此条规则的异常是当UnavailableException指明一段最低的不可访问的时间,在创建和初始化一个新的Servlet实例前容器必须等待一段时间来传递。


          2.3.2.2 工具事项

           当一个工具加载web应用程序的时候,静态初始化方法的触发与调用init方法是分开的。开发者不应该假设一个Servlet在一个活动的容器运行期间,直到Servlet接口的init方法调用。例如,Servlet不应该试着去建立数据库的连接或者ejb容器的连接,当静态初始化方法被调用的时候。


       2.3.3 请求处理

         一个Servlet在合理的初始化,Servlet容器可能使用它来处理客户端请求。请求由ServletRequest类型对象表示。Servlet返回请求的响应 是通过调用ServletResponse类型对象提供的方法。这些对象都是作为Servlet接口中的service方法的参数传递的。

         在一个HTTP请求中,由容器提供的对象是HttpServletRequest和HttpServletResponse。

         注意在servlet容器的service中放置的servlet实例,可能在整个生命周期期间不处理任何请求。


        2.3.3.1 多线程问题

          一个servlet容器可能通过servlet的service方法发送当前的请求。为处理这些请求,servlet开发者必须做足准备来处理service方法中的多线程问题。

        

          虽然这样不鼓励,对于开发者由另外一种选择是实现SingleThreadModel接口,其要求容器保证在service方法中每次只有一个请求线程。一个servlet容器可能通过序列化一个servlet的请求来满足这个,或者保有一个池化的servlet实例。如果这个servlet是web应用程序的一部分,已经标示为可分配的,容器可能在每个JVM(应用程序所分布的地方)中持有池化的servlet实例。


         对于没有实现SingleThreadModel接口的servlet,如果service方法(诸如doGet或者doPost方法分发到HttpServlet抽象类的service方法中)已经用synchronized关键自定义,虽然servlet容器不使用池化的实例,但是必须通过容器序列化请求。强烈建议开发者在这些环境中不要同步service方法(或者转发给他的方法),因为会降低性能。


        2.3.3.2  请求处理时的异常

        一个servlet在一个请求业务中可能抛出ServletException或者一个UnavailableException异常。一个ServletException异常表明在处理请求期间一些错误发生了,并且容器应该果断清除这个请求。

        一个UnavailableException异常表示这个Servlet不能处理请求,也许是临时的或者持久性的。

       如果UnavailableException表明了一个永久无效,Servlet容器必须从service中移除这个Servlet,调用destory方法并释放Servlet实例。一些被容器拒绝的请求必须返回SC_NOT_FOUNT(404)响应。

      

       如果UnavailableException指明的是临时无效,容器可能选择不去根据请求路径访问Servlet,被容器拒绝的请求在这段期间必须返回SC_SERVICE_UNAVALIABLE(503)的响应状态,并返回一个Retry-After数据头,来指明不可用将终止。

       容器可能选择忽略临时和永久不可用之间的差距并将所有的UnavailableException以永久性对待,因此移除一个Servlet将从service中抛出UnavailableException。


       2.3.3.3 异步处理

         有时候一个过滤器和/或者一个Servlet 在响应返回之前由于没有返回一个资源或者事件,是不能完成一个请求的处理的。例如,一个Servlet可能在返回一个响应之前需要等待一个可用的JDBC连接,为了从远程web业务中返回一个响应,为了一个JMS消息,或者为了一个应用事件。Servlet中的等待是一个低性能操作,因为它是一个阻塞操作,消耗了一个线程和其他限制性资源。经常地,一个缓慢的资源,比如一个数据库也许有许多线程阻塞等待访问并且会引起线程饥饿和整个web容器低质量的服务。

        

         Servlet3.0提供了异步操作,这样那个线程可以返回容器并执行其他的任务。当请求执行异步操作的时候,另一个线程或者回调可能创建响应并且调用complete或者分发请求。这样了它可能使用AsyncContext.dispatch方法运行在容器的上下文中。异步处理的典型顺序如下:


         异步处理这块单独拿出处理


0 0
原创粉丝点击