2.2.1.1 Servlet生命周期
所谓XXX的生命周期,就是说XXX出生、服务以及死亡的全过程。与Servlet生命周期相关的方法(有3个):
(1) void init(SevletConfig) throws ServletException:实例化Servlet后紧接着调用(一次)
(2) void service(ServletRequest, ServletResponse) throws ServletException, IOException:每次处理请求时都会被调用
(3) void destroy():销毁(一次)
实现Servlet接口后的代码:
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class LoginServlet implements Servlet {
/**
* 无参构造函数
*/
public LoginServlet() {
System.out.println("LoginServlet()...");
}
/**
* destroy()是生命周期方法_3,该方法几乎不用!!
* 它会在Servlet销毁之前调用,当且仅当只被调用一次
*/
@Override
public void destroy() {
System.out.println("destroy()...");
}
/**
* 可以用来获取Servlet的配置信息
*/
@Override
public ServletConfig getServletConfig() {
System.out.println("getServletConfig()...");
return null;
}
/**
* 获取Servlet的信息,该方法几乎不用!
*/
@Override
public String getServletInfo() {
System.out.println("getServletInfo()...");
return null;
}
/**
* init()是生命周期方法_1
* 它会在Servlet创建之后马上执行,当且仅当只执行一次(出生之后)
*/
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init()...");
}
/**
* service()是生命周期方法_2
* 它会被调用多次!每次处理请求都是在调用该方法。
*/
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("service()...");
}
}
2.2.1.2 UML描述Servlet生命周期全过程
2.2.1.3 Servlet创建时机
服务器会在Servlet第一次被访问、或者服务器启动时创建Servlet;如果服务器启动时就创建Servlet,那么还需要在web.xml文件中配置(后文再讲述)。也就是说默认情况下,Servlet是在第一次被访问时由服务器创建的。
一个servlet类,服务器只创建一个实例对象(例如在我们首次访问http://localhost:8080/helloServlet/HelloServlet时,服务器通过“/HelloServlet”找到了绑定的Servlet名称为com.zhb.web.servlet.HelloServlet,然后服务器查看这个类型的Servlet是否已经创建过,如果没有创建过,那么服务器才会通过反射来创建HelloServlet的实例。当我们再次访问http://localhost:8080/helloServlet/HelloServlet时,服务器就不会再次创建HelloServlet实例了,而是直接使用上次创建的实例。
2.2.1.4 init()和service()
在Servlet实例被创建后,服务器会马上调用它的init()方法。请记住, servlet实例被创建后马上就会调用init()方法,而且只调用这一次。我们可以把一些对servlet的初始化工作放到init()方法中!
当服务器每次接收到请求时,都会去调用sevlet的service()方法来处理请求。服务器接收到一次请求,就会调用service()方法一次,所以service()方法是会被调用多次的。正因为如此,所以我们才需要把处理请求的代码写到service()方法中。
2.2.1.5 destroy()
在服务器被关闭时,服务器会去销毁servlet,在销毁servlet之前服务器会先去调用servlet的destroy()方法,例如对某些资源的释放等代码放到destroy()方法中。(基本用不到该方法!!)
在Servlet接口中还存在以下三个对象类型:
(1) ServletRequest:service()方法的参数,它表示请求对象,封装了所有与请求相关的数据,由服务器创建;
(2) ServletResponse:service()方法的参数,它表示相应对象,在service()方法中完成对客户端的响应时需要使用这个对象。
(3) ServletConfig:init()方法的参数,它表示Servlet配置对象,对应Servlet的配置信息,即web.xml文件中有关Servlet配置信息。
2.2.1.7 ServletConfig
ServletConfig对象,对应web.xml文件中的<servlet>元素(即Servlet的配置信息)。例如你想获取当前Servlet在web.xml文件中的配置名称,就可以使用servletConfig.getServletName()方法获取。
ServletConfig对象由服务器创建,然后传递给Servlet的init()方法,你可以在init()方法中使用它。ServletConfig接口中定义了四个方法:
(1) String getServletName():获取Servlet在web.xml文件中的配置名称,即<servlet-name>中的内容
(2) **ServletContext getServletContext():获取Servlet上下文对象(ServletContext),后文详细介绍
(3) String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值
(4) Enumeration getInitParameterNames():获取所有初始化参数的名称
示例代码:
<servlet>
<servlet-name>aa</servlet-name>
<servlet-class>HelloServlet</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123</param-value>
</init-param>
</servlet>
public void init(ServletConfig config) throws ServletException {
System.out.println("servletName: " + config.getServletName()); // aa
System.out.println("value1: " + config.getInitParameter("username")); //admin
Enumeration<String> paramNames = config.getInitParameterNames();
while (paramNames.hasMoreElements()) {
String name = paramNames.nextElement();
System.out.println(name); // username password
}
}
2.2.1.8 ServletRequest和ServletResponse
ServletRequest和ServletResponse是Servlet#service()方法的两个参数,一个是请求对象,一个是响应对象,可以从ServletRequest对象中获取请求数据,使用ServletResponse对象完成响应。它们总是成对出现的。
ServletRequest和ServletResponse的实例由服务器创建,然后传递给service()方法。如果在service()方法中希望使用HTTP相关的功能,那么可以把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse。这也说明我们经常需要在service()方法中对ServletRequest和ServletResponse进行强转。