Servlet浅识

来源:互联网 发布:2017美工电脑配置要求 编辑:程序博客网 时间:2024/06/10 05:28

    Servlet学习的开始我们先要明白什么是Servlet,它是运行在服务器端的程序,它是被容器调用的(如tomcat),用于处理及响应客户端的请求.

  J2EE定义的是一系列的标准,没有提供实现,没有提供jar包。Tomcat中的servlet-api.jar实现了J2EE的API标准。

  类结构图:

 

Servlet学习之Servlet类图

 

  GenericServlet是抽象类,其中定义了抽象方法service()。

  Servlet学习中碰到HttpServlet也是抽象类,它没有抽象方法,但它实现了service()方法,service()方法中又调用了doGet()和doPost()方法。doGet()和doPost()方法在HttpServlet类中都有默认的实现。而我们写的servlet程序一般都继承HttpServlet,重写doGet和doPost方法。Service()方法被调用时会自动调用我们重写的doGet或doPost方法,因此我们的Servlet程序主要任务就是重写这两个方法。

  问题:我们Servlet学习时候,当Servlet程序中重写了doGet()和doPost()方法,service()方法是怎么调用到我们写的doGet()和doPost()方法的?

  解答:这里面用到了多态,重写和继承都有了,那么父类引用指向子类对象是怎么体现的呢?service方法是被容器中我们写的Servlet类的实例调用的,而父类HttpServlet中又调用了this.doGet()和this.doPost()方法,这时就有了父类引用指向子类对象了:this(HttpServlet)-﹥我们的Servlet实例。附上一个图作为说明:

 

Servlet学习之Servlet实例图

 

  问题:Servlet学习时service()方法什么时候被调用?

  解答:当客户端发出请求的时候,容器调用service 方法并传递一个请求和响应对象。Servlet首先判断该请求是GET 操作还是POST 操作。然后它调用下面的一个方法:doGet 或 doPost。如果请求是GET就调用doGet方法,如果请求是POST就调用doPost方法。

  Servlet学习过程中要注意看看Servlet的生命周期:

  1、客户端发送一个请求(也就是一个servlet的访问URL)

  2、服务器端解析请求(通过web.xml里面的servlet配置解析)

  3、servlet容器创建servlet的一个实例

  4、容器调用该实例的init()方法

  5、如果容器对该servlet有请求,则调用此实例的service()方法

  6、返回响应消息给servlet容器

  7、返回响应消息给客户端

  8、容器在销毁本实例前调用它的destroy()方法

  9、销毁并标记该实例以供作为垃圾收集

  protected void doGet(HttpServletRequest req, HttpServletResponse resp)

  HttpServletRequest req封装了客户端到服务器端的请求,在服务器端(即我们编写的Servlet)中可以通过req获取这些请求信息。

  HttpServletResponse resp从服务器端返回给客户端的对象,也就是我们往resp中写消息就可以放松给客户端了。

  问题:Servlet学习中Servlet容器(如tomcat)怎样调用我们写的相应Servlet?

  解答:对了,在web.xml里面配置。如:

  ﹤servlet﹥ ﹤servlet-name﹥hw﹤/servlet-name﹥ ﹤servlet-class﹥com.dvnchina.test.HelloWorldServlet﹤/servlet-class﹥ ﹤/servlet﹥ ﹤servlet-mapping﹥ ﹤servlet-name﹥hw﹤/servlet-name﹥ ﹤url-pattern﹥/helloservlet﹤/url-pattern﹥ ﹤/servlet-mapping﹥

  这时客户端通过http://127.0.0.1:8080/ServletTest/helloservlet发送请求,就可以调用hw这个servlet,当hw被调用后就容器就自动调用hw的service()方法,而hw实例从HttpServlet继承的service()方法中又调用了doGet()和doPost()方法,此时根据多态就调用了我们servlet中写的doGet()和doPost()方法。

  Servlet学习时我们要明白通常一个Servlet在Servlet容器中只有一个实例。那么通过上面的对于Servlet学习中的各种问题的解答,希望你对Servlet学习充满信心。

 

Servlet生命周期

Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示。

Servlet的生命周期包含了下面4个阶段:

(1)加载和实例化

Servlet容器负责加载和实例化 Servlet。当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Servlet实例。当Servlet容器启动后,它必须要知道所需的Servlet类在什么位置,Servlet容器可以从本地文件系统、远程文件系统或者其他的网络服务中通过类加载器加载 Servlet类,成功加载后,容器创建Servlet的实例。因为容器是通过Java的反射API来创建Servlet实例,调用的是Servlet的默认构造方法(即不带参数的构造方法),所以我们在编写Servlet类的时候,不应该提供带参数的构造方法。

(2)初始化

在Servlet实例化之后,容器将调用 Servlet的init()方法初始化这个对象。初始化的目的是为了让Servlet对象在处理客户端请求前完成一些初始化的工作,如建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只被调用一次。在初始化期间,Servlet实例可以使用容器为它准备的 ServletConfig对象从Web应用程序的配置信息(在web.xml中配置)中获取初始化的参数信息。在初始化期间,如果发生错误,Servlet实例可以抛出ServletException异常或者UnavailableException异常来通知容器。 ServletException异常用于指明一般的初始化失败,例如没有找到初始化参数;而UnavailableException异常用于通知容器该Servlet实例不可用。例如,数据库服务器没有启动,数据库连接无法建立,Servlet就可以抛出UnavailableException异常向容器指出它暂时或永久不可用。

(3)请求处理

Servlet容器调用Servlet的 service()方法对请求进行处理。要注意的是,在service()方法调用之前,init()方法必须成功执行。在service()方法中,Servlet实例通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse 对象的方法设置响应信息。在service()方法执行期间,如果发生错误,Servlet实例可以抛出ServletException异常或者 UnavailableException异常。如果UnavailableException异常指示了该实例永久不可用,Servlet容器将调用实例的destroy()方法,释放该实例。此后对该实例的任何请求,都将收到容器发送的HTTP 404(请求的资源不可用)响应。如果UnavailableException异常指示了该实例暂时不可用,那么在暂时不可用的时间段内,对该实例的任何请求,都将收到容器发送的HTTP 503(服务器暂时忙,不能处理请求)响应。

(4)服务终止

当容器检测到一个Servlet实例应该从服务中被移除的时候,容器就会调用实例的destroy()方法,以便让该实例可以释放它所使用的资源,保存数据到持久存储设备中。当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被 Java的垃圾收集器所回收。如果再次需要这个Servlet处理请求,Servlet容器会创建一个新的Servlet实例。

在整个Servlet的生命周期过程中,创建Servlet实例、调用实例的init()和destroy()方法都只进行一次,当初始化完成后,Servlet容器会将该实例保存在内存中,通过调用它的service()方法,为接收到的请求服务。

Servlet 如何被加载(Load)、被实例化(Instantiated)

  Servlet Engine 负责实例化和加载Servlet,这个过程可以在Servlet Engine 加载时执行,可以在Servlet 响应请求时执行,也可以在两者之间的任何时候执行。

  Servlet如何被初始化(Initialized)

  Servlet Engine 加载好Servlet 后,必须要初始化它。初始化时Servlet 可以从数据库里读取初始数据,建立JDBC Connection,或者建立对其他有价值的资源的引用。

  在初始化阶段,Init( )方法被调用。这个方法在javax.servlet.Serlet接口中定义。Init( )方法以一个Servlet 配置文件(ServletConfig 型)为参数。Servlet configuration 对象由Servlet Engine 实现,可以让Servlet 从中读取一些name-value对的参数值。ServletConfig对象还可以让Servlet接受一个Servlet Context对象。

  Servlet 如何处理请求

  Servlet 被初始化以后,就处于能响应请求的就绪状态。每个对Servlet 的请求由一个Servlet Request 对象代表。Servlet 给客户端的响应由一个Servlet Response对象代表。当客户端有一个请求时,Servlet Engine 将ServletRequest 和ServletResponse对象都转发给Servlet,这两个对象以参数的形式传给Service方法。这个方法由 javax.servlet.Servlet定义并由具体的Servlet 实现。

  Servlet还可以实现 ServletRequest 和ServletResponse接口。ServletRequest接口可以让Servlet 获取客户端请求中的参数,如form data、request信息、协议类型,等等。Servlet 可以从ServletInputStream流中读取request 数据。ServletResponse接口允许Servlet设置response headers和status codes。实现这个接口可以使Servlet能访问ServletOutputStream流用来向客户端返回数据。

  Servlet如何被释放

  Servlet Engine 没有必要在Servlet 生命周期的每一段时间内都保持Servlet的状态。Servlet Engine可以随时随意使用或释放Servlet。因此,你不能依赖Servlet class或其成员存储信息。当Servlet Engine判断一个Servlet应当被释放时(比如说Engine准备Shut down 或需要回收资源),Engine必须让Servlet 能释放其正在使用的任何资源,并保存持续性的状态信息。这些可以通过调用Servlet的destroy方法实现。     在Servlet Engine 释放一个Servlet 以前,必须让其完成当前实例的service方法或是等到timeout(如果Engine定义了timeout)。当Engine释放一个 Servlet以后,Engine将不能再将请求转发给它,Engine必须彻底释放该Servlet并将其标明为可回收的(给garbage collection)。

  在Servlet API中最重要的是Servlet interface。所有的Servlets执行这个interface的方式有很多种:或者是直接的,或者通过extending这个class执行它,如 HttpServlet。这个Servlet interface 提供并安排Servlet与客户端联系的方法。Servlet 编写者可以在他们开发Servlet程序时提供更多一些或所有这样的方法。

  当一个Servlet接收来自客户端的调用请求时,它接收两个对象:一个是 ServletRequest,另外一个是ServletResponse。这个ServletRequest class 概括从客户端到服务器之间的联系,而 ServletResponse class 概括从Servlet返回客户端的联系。

  ServletRequest interface 可以获取到这样一些信息,如由客户端传送的参数名称,客户端正在使用的协议,产生请求并且接收请求的服务器远端主机名。它也提供获取数据流的 Servlet、ServletInputStream,这些数据是客户端引用中使用HTTP POST和PUT方法递交的。一个ServletRequest的子类可以让Servlet获取更多的协议特性数据。

 

原创粉丝点击