码迷,mamicode.com
首页 > Windows程序 > 详细

ServletAPI --- Servlet接口

时间:2016-04-01 18:22:00      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:

Servlet

大部分来源:http://jinnianshilongnian.iteye.com/blog/1910981

Servlet接口是Java Servlet API的核心抽象。所有Servlet类必须直接或间接的实现该接口,或者更通常做法是通过继承一个实现了该接口的类从而复用许多共性功能。目前有GenericServlet和HttpServlet这两个类实现了Servlet接口。大多数情况下,开发者只需要继承HttpServlet去实现自己的Servlet即可。
个人:我们一般编译一个Servlet继承HttpServlet

2.1 请求处理方法

Servlet基础接口定义了用于客户端请求处理的service方法。当有请求到达时,该方法由servlet容器路由到一个servlet实例。
Web应用程序的并发请求处理通常需要Web开发人员去设计适合多线程执行的Servlet,从而保证service方法能在一个特定时间点处理多线程并发执行。(注:即Servlet默认是线程不安全的,需要开发人员处理多线程问题)
通常Web容器对于并发请求将使用同一个servlet处理,并且在不同的线程中并发执行service方法。
个人:重写doGet或doPost方法就相当于间接的实现service方法来提供请求相应逻辑。那么doGet或doPost方法是多线程并发执行的。即Servlet默认是线程不安全的。

2.1.1 基于Http规范的请求处理方法

HttpServlet抽象子类在Servlet接口基础之上添加了些协议相关的方法,并且这些方法能根据HTTP请求类型自动的由HttpServlet中实现的service方法转发到相应的协议相关的处理方法上。这些方法是:

■ 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编程都是类似。
个人:Servlet开发人员,继承HttpServlet抽象子类,仅去实现doGet 和 doPost请求处理方法即可。

2.1.2 附加的方法

doPut和doDelete方法允许Servlet开发人员让支持HTTP/1.1的客户端使用这些功能。HttpServlet中的doHead方法可以认为是doGet方法的一个特殊形式,它仅返回由doGet方法产生的header信息。doOptions方法返回当前servlet支持的HTTP方法(译者注:通过Allow响应头返回支持的HTTP操作,如GET、POST)。doTrace方法返回的响应包含TRACE请求的所有头信息。
个人:附加的方法根据是否需要来使用。比如仅仅返回header信息,则使用doHead方法

2.1.3 有条件GET支持

HttpServlet定义了用于支持有条件GET操作的getLastModified方法。所谓的有条件GET操作是指客户端通过GET请求获取资源时,当资源自第一次获取那个时间点发生更改后才再次发生数据,否则将使用客户端缓存的数据。在一些适当的场合,实现此方法可以更有效的利用网络资源,减少不必要的数据发送。
个人:对于GET请求,可以实现getLastModified()方法(默认返回-1,也就是默认不支持if-modified-since标头),返回子1970.1.1 0:00:00至资源最后一次更新期间所经过的毫秒数,如果说getLastModified()返回的最后修改的时间在请求标示的时间之前则不会使用GET方法即不调用doGet直接从缓存中取得。


2.2 实例数量

通过注解描述的(第8章 注解和可插拔性)或者在Web应用程序的部署描述符(第14章 部署描述符)中描述的servlet声明,控制着servlet容器如何提供servlet实例。

对于未托管在分布式环境中(默认)的servlet而言,servlet容器对于每一个Servlet声明必须且只能产生一个实例。不过,如果Servlet实现了SingleThreadModel接口,servlet容器可以选择实例化多个实例以便处理高负荷请求或者串行化请求到一个特定实例。

如果servlet以分布式方式进行部署,容器可以为每个虚拟机(JVM)的每个Servlet声明产生一个实例。但是,如果在分布式环境中servlet实现了SingleThreadModel接口,此时容器可以为每个容器的JVM实例化多个Servlet实例。
个人:servlet容器对于每一个Servlet声明必须且只能产生一个实例。仅有一个Servlet实例。单例模式,但是是多线程访问。

2.2.1 关于 Single Thread Model

SingleThreadModel 接口的作用是保证一个特定servlet实例的service方法在一个时刻仅能被一个线程执行,一定要注意,此保证仅适用于每一个servlet实例,因此容器可以选择池化这些对象。有些对象可以在同一时刻被多个servlet实例访问,如HttpSession实例,可以在一个特定的时间对多个Servlet可用,包括那些实现了SingleThreadModel接口的Servlet。

个人:3.0已经标记为过期。SingleThreadModel应该时线程不安全,不能保证一个特定servlet实例的service方法在一个时刻仅能被一个线程执行

2.3 Servlet生命周期

Servlet是按照一个严格定义的生命周期被管理,该生命周期规定了Servlet如何被加载、实例化、初始化、处理客户端请求,以及何时结束服务。该声明周期可以通过javax.servlet.Servlet 接口中的init、service和destroy这些API来表示,所有Servlet必须直接或间接的实现GenericServlet或HttpServlet抽象类。

个人:Servlet生命周期的几个阶段:加载、实例化、初始化、处理客户端请求,以及何时结束服务
 
2.3.1 加载和实例化

Servlet容器负责加载和实例化Servlet。加载和实例化可以发生在容器启动时,或者延迟初始化直到容器决定有请求需要处理时。当Servlet引擎启动后,servlet容器必须定位所需要的Servlet类。Servlet容器使用普通的Java类加载设施加载Servlet类。可以从本地文件系统或远程文件系统或者其他网络服务加载。加载完Servlet类后,容器就可以实例化它并使用了。
个人:启动后,容器定位Servlet类,加载Servlet类,实例化它。可以在容器启动时加载,或延迟加载<load-on-startup></load-on-startup>
 
2.3.2 初始化

一旦一个Servlet对象实例化完毕,容器接下来必须在处理客户端请求之前初始化该Servlet实例。初始化的目的是以便Servlet能读取持久化配置数据,初始化一些代价高的资源(比如JDBC API 连接),或者执行一些一次性的动作。容器通过调用Servlet实例的init方法完成初始化,init方法定义在Servlet接口中,并且提供一个唯一的ServletConfig接口实现的对象作为参数,该对象每个Servlet实例一个。

配置对象允许Servlet访问由Web应用配置信息提供的键-值对的初始化参数。该配置对象也提供给Servlet去访问一个ServletContext对象,ServletContext描述了Servlet的运行时环境。请参考第4章,“Servlet Context”获取ServletContext接口的更多信息。

个人:初始化一些代价高的资源(比如JDBC API 连接),或者执行一些一次性的动作
  ServletContext初始化参数:
    <context-param>
        <param-name>my_param</param-name>
        <param-value>hello</param-value>
    </context-param>
  Servlet的初始化参数:
        <init-param>
              <param-name>initkey</param-name>
              <param-value>initvalue</param-value>
          </init-param>

2.3.2.1 初始化时的错误条件

在初始化阶段,servlet实现可能抛出UnavailableException或ServletException异常。在这种情况下,Servlet不能放置到活动服务中,而且Servlet容器必须释放它。如果初始化没有成功,destroy方法不应该被调用。

在实例初始化失败后容器可能再实例化和初始化一个新的实例。此规则的例外是,当抛出的UnavailableException表示一个不可用的最小时间,容器在创建和初始化一个新的servlet实例之前必须等待一段时间。

2.3.2.2使用工具时的注意事项

当一个工具加载并内省某个Web应用程序时触发的静态初始化,这种用法与调用init初始化方法是有区别的。在Servlet的init方法没被调用,开发人员不应该假定其处于活动的容器环境内。比如,当某个Servlet仅有静态方法被调用时,不应该与数据库或企业级JavaBean(EJB)容器建立连接。

2.3.3 请求处理

Servlet完成初始化后,Servlet容器就可以使用它处理客户端请求了。客户端请求由ServletRequest类型的request对象表示。Servlet封装响应并返回给请求的客户端,该响应由ServletResponse类型的response对象表示。这两个对象(request和response)是由容器通过参数传递到Servlet接口的service方法的。

在HTTP请求的场景下,容器提供的请求和响应对象具体类型分别是HttpServletRequest 和 HttpServletResponse。

需要注意的是,由Servlet容器初始化的某个Servlet 实例在服务期间,可以在其生命周期中不处理任何请求。

2.3.3.1 多线程问题

Servlet容器可以并发的发送多个请求到Servlet的service方法。为了处理这些请求,Servlet开发者必须为service方法的多线程并发处理做好充足的准备。一个替代的方案是开发人员实现SingleThreadModel接口,由容器保证一个service方法在同一个时间点仅被一个请求线程调用,但是此方案是不推荐的。Servlet容器可以通过串行化访问Servlet的请求,或者维护一个Servlet实例池完成该需求。如果Web应用中的Servlet被标注为分布式的,容器应该为每一个分布式应用程序的JVM维护一个Servlet实例池。

对于那些没有实现SingleThreadModel 接口的Servlet,但是它的service方法(或者是那些HttpServlet中通过service方法分派的doGet、doPost等分派方法)是通过synchronized关键词定义的,Servlet容器不能使用实例池方案,并且只能使用序列化请求进行处理。强烈推荐开发人员不要去通过service方法(或者那些由Service分派的方法),因为这将严重影响性能。

2.3.3.2 请求处理时的异常

Servlet在处理一个请求时可能抛出ServletException或UnavailableException异常。ServletException表示在处理请求时出现了一些错误,容器应该采取适当的措施清理掉这个请求。

UnavailableException表示servlet目前无法处理请求,或者临时性的或者永久性的。

如果UnavailableException表示的是一个永久性的不可用,Servlet容器必须从服务中移除这个Servlet,调用它的destroy方法,并释放Servlet实例。所有被容器拒绝的请求,都会返回一个SC_NOT_FOUND (404) 响应。

如果UnavailableException表示的是一个临时性的不可用,容器可以选择在临时不可用的这段时间内路由任何请求到Servlet。所以在这段时间内被容器拒绝的请求,都会返回一个SC_SERVICE_UNAVAILABLE (503)响应状态码,且同时会返回一个Retry-After头指示此Servlet什么时候可用。容器可以选择忽略永久性和临时性不可用的区别,并把UnavailableExceptions视为永久性的,从而Servlet抛出UnavailableException后需要把它从服务中移除。

2.3.4 终止服务(End of Service)

Servlet容器没必要保持装载的Servlet持续任何特定的一段时间。一个Servlet实例可能会在servlet容器内保持活跃(active)持续一段时间(以毫秒为单位),Servlet容器的寿命可能是几天,几个月,或几年,或者是任何之间的时间。

当Servlet容器确定servlet应该从服务中移除时,将调用Servlet接口的destroy方法以允许Servlet释放它使用的任何资源和保存任何持久化的状态。例如,当想要节省内存资源或它被关闭时,容器可以做这个。

在servlet容器调用destroy方法之前,它必须让当前正在执行service方法的任何线程完成执行,或者超过了服务器定义的时间限制。

 

一旦调用了servlet实例的destroy方法,容器无法再路由其他请求到该servlet实例了。如果容器需要再次使用该servlet,它必须用该servlet类的一个新的实例。在destroy方法完成后,servlet容器必须释放servlet实例以便被垃圾回收。



ServletAPI --- Servlet接口

标签:

原文地址:http://blog.csdn.net/zghwaicsdn/article/details/51034257

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!