Servlet的生命周期

Servlet的生命周期:

web容器通过类路径找到Servlet,并加载。
调用默认构造函数实例化Servlet。
调用init(),初始化Servlet(下面会重点讲解这一步),只执行一次。
容器调用service()方法。此方法会根据HTTP方法,调用相应的doGet()和doPost()。
destroy() 此方法会杀死Servlet对象,或调用容器使用GC结束Servlet。至此Servlet使命结束。

1.Web容器是如何找到Servlet的路径的。2种方式。

方式1:

在THML页面中显示调用Servlet。也就说,在URL上显示标识出Servlet的路径,Web容器会根据此路径找到Servlet类,并加载。但是这种方式是非常不安全的,不建议使用。

方式2:通过在web.xml中配置

<servlet>
    <servlet-name>自定义名servlet-name>
    <servlet-class>Servlet路径servlet-class>
  servlet>
  <servlet-mapping>
    <servlet-name>自定义名servlet-name>
    <url-pattern>url资源路径url-pattern>
  servlet-mapping>

2.调用默认构造函数实例化Servlet。

现在做一个有意思的测试:假设我创建了一个MyServlet extends HttpServlet,构造函数不使用默认构造。

public MyServlet(int i) {
        super();
        // TODO Auto-generated constructor stub
    }

页面发过来一个请求后出现以下错误。

javax.servlet.ServletException: Error instantiating servlet class
java.lang.Class.newInstance(Unknown Source)

Web容器是通过反射机制来创建自定义Servlet的,Servlet开发者要求程序员必须使用默认的构造函数来创建自定义Servlet,否则就会出现上面的错误。
3. init()方法
大家都知道这个方法是用来初始化Servlet的,但是会有这样的疑问?构造函数不也初始化Servlet吗?为什么还使用它呢?
servlet的继承结构

接口:Servlet(定义了Serlvet声明周期),ServletConfig(使Servlet对象成为真正的能够处理用户请求的Servlet)
abstract class GenericServlet implements Servlet,ServletConfig,Serializable:实现了Servlet接口和ServletConfig接口。
abstract class HttpServlet extends GenericServlet
自定义的Servlet继承自HttpServlet

去看一下GenericServlet的源代码,里面有很多常用的方法如:getServletName()、getServletContext()、都需要ServletConfig的支持,ServletConfig实现类是Web容器提供的,不需要我们操心,public void init(ServletConfig config),Web容器调用这个方法并传递进一个ServletConfig对象,这样Generic的所有方法就能够使用。也即是说,构造函数只是使自定义Servlet实例化成为一个Java对象,而init()方法才是使自定义Servlet成为一个能够处理页面请求的真正的Servlet。

4.Service()

当一个HTTP请求到来时,Web容器怎么知道调用什么方法来处理这个请求呢?答案就是HttpServlet的service()方法,这个方法中有两个参数,HttpServletRequest和HttpServletResponse。HttpServletRequest对象封装了HTTP请求,通过这个对象的getMethod()方法就会知道HTTP请求方法是什么,才会调用doGet()、doPost()这些方法来处理请求。

5.destroy()

当一个请求结束后,可以显示调用destroy()方法,但是Servlet开发者并没有提供这个方法的实现,需要自己编写实现,但是不推荐自己编写,这和Java的垃圾回收机制一样,Servlet中也有自己的垃圾回收机制。所以不用我们担心。这个方法的意义可能就在于让程序员知道Servlet的声明周期(这是我猜测的),仅此而已。

注意:

Servlet的单线程的,每来一个请求都会单独的开启一个线程,并不是一个Servlet对象会开启一个线程,这一点很重要,这个线程可能会从线程池里调用,也可能单独创建。

你可能感兴趣的:(Servlet)