到目前为止,您已经学习到了如何撰写、编译与执行Servlet。由于所有的Servlet都必须执行于Servlet容器中,因此我们必须了解Servlet容器如何进行下列工作: n 何时载入Servlet,并予以实体化(instantiated) n 如何回应用户的请求 n 何时该卸载Servlet的服务 上述三个阶段即构成Servlet的“生命周期”(life cycle)。值得注意的是,Servlet生命周期并不由程序员控制,而是由Servlet容器掌管。 在javax.servlet.Servlet接口内定义了下面三个方法: n init() n service() n destroy() 这意味着所有的Servlet都会实现这三个方法,而Servlet容器可由此控制其生命周期。本节将深入探讨这些方法的用途及使用时机。 2.4.1 service()方法 在某些情况下,Servlet容器需要将Servlet实体化(例如:Servlet容器接收到某个HTTP请求)。简单地说,实体化的过程就是建立一个新的Servlet,可简单地概分为下列两个阶段。 (1) 在实体化Servlet以前,Servlet容器必须确认与Servlet有关的类位于何处,再以“类载入器”(ClassLoader)将Servlet类载入存储器。 (2) 当Servlet被调用时,Servlet容器将会调用该Servlet的默认构造函数(default constructor),然后建立一个Servlet实体。 因为Servlet的构造函数是由Servlet容器调用的,所以Servlet类不应该包含“非默认构造函数”(non-default constructor)。所谓的“非默认构造函数”是指可以传递参数的构造函数。此时您可能产生一个疑问:如果Servlet没有“非默认构造函数”,如何将起始参数传递给Servlet呢?这问题问得好,在回答前,笔者先说明何时需要将起始参数传递给Servlet。 试想下列情境:某个Servlet需要通过JDBC存取数据库。依照标准程序,您必须指定JDBC驱动程序的种类、目的数据库位置以及登录数据库所使用的账号与密码,然后利用这些信息建立与数据库的连接。然而将这些信息全部撰写在每个Servlet里面将造成一个潜在问题:万一后端数据库需要更换,所有Servlet程序码岂不是要全部改写!由此可见,比较妥善的方式应该是将所有Servlet都会存取的数据统一存放在某个位置,以便后续管理与维护。 在Java Servlet技术所建构的Web应用程序中,每个Web应用程序均可定义一个部署描述文件:web.xml。该文件可存放Servlet所需要的起始参数(例如刚才提及的数据库目的位置与用户密码)以及Web应用程序的结构数据。当Servlet容器读取web.xml文件内容后,可以将这些起始参数封装成一个对象,并在调用init()方法时传递给Servlet,这个做法即可达到初始化Servlet起始参数的目的。 以下是javax.servlet.Servlet类内定义的init()方法: public void init(ServletConfig config) throws ServletException{ } 由此可知:Servlet容器调用init()方法时,将会传入一个ServletConfig对象。因此我们可以在Servlet内覆写init()方法,并通过ServletConfig对象来取得某些起始参数。关于如何定义与存取Servlet起始参数,将留待第3章再做说明。 n 如何覆写init()方法如果您仔细研究了Servlet API的定义,也许会发现一个奇怪的现象:javax.servlet接口只定义了一个init()方法,但是javax.servlet.GenericServlet类(继承自javax.servlet)内却定义了两个init()方法(参考图2-13),这个问题倒是值得我们研究。 由于javax.servlet接口内定义的init(ServletConfig config)方法必须传入一个ServletConfig对象,因此在覆写该方法时,必须再以super.init(config) 调用父类的init()方法,这个步骤稍嫌繁琐。为了简化init()方法的覆写方式,javax.servlet.GenericServlet类另外定义了一个不需传递参数的init方法,以便程序员直接覆写init()方法。当Servlet容器调用init(ServletConfig config)方法时,该方法也会自动调用您所覆写的init()方法。 提示: 在GenericServlet类内定义的init()方法并未传入ServletConfig对象。如果在此方法内须要存取ServletConfig对象,可直接调用getServletConfig()方法。 图2-13 GenericaServlet类与Servlet接口 2.4.2 service()方法 当Servlet实体经过初始化程序后,只要Servlet 容器接收到用户传送的请求,就会将这个请求封装成ServletRequest对象,然后调用service()方法。以下是javax.servlet.Servlet接口所定义的service()方法。 public void service(ServletRequest req, ServletResponse res) throws ServletException,java.io.IOException 如果用户传送的是HTTP请求,Servlet容器就会将HTTP请求封装成HttpServletRequest对象,然后调用service()方法。以下是在javax.servlet.http.HttpServlet类中定义的service()方法: protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException,java.io.IOException 针对HTTP请求,service()方法会根据HTTP请求形式(GET、POST、HEAD等)来决定应该执行哪种doXXX()方法。如前所述,如果HTTP请求形式为POST,service()方法将会自动调用doPost()方法。因此在一般情况下,程序员无须去覆写service()方法,只须根据用户可能传送的HTTP形式去覆写doGet()与doPost()等方法即可。
Servlet的生命周期((life cycle)
最新推荐文章于 2022-06-15 08:23:05 发布