Servlet程序时运行在服务器端的java程序,生命周期收到web容器的控制。
生命周期有5部分:加载,初始化,服务,销毁,卸载
其生命周期都可以在HttpServlet和GenericServlet中找到对应的方法。
1、加载Servlet
Web容器负责加载Servlet,当web容器启东时或者在第一次使用这个Servlet的时候,容器会负责创建Servlet实例,但是用户必须通过web.xml指定Servlet的位置,成功加载后,Web容器会通过反射的方式对Servlet进行实例化。
2、初始化
当一个servlet被实例化之后,容器将调用init()方法初始化这个对象,以便在处理请求之前完成一些动作。
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
// NOOP by default
}
在GenericServlet 中init方法有两个重载版本,第一个版本可以接受web.xml中配置的初始化参数。都是钩子方法。
3、服务
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
当有请求提交时,将会先调用Servlet的service方法进行处理,然后service通过反射获取请求方法,转发到相应的doGet()或者其他方法。当自己实现service方法时,如果想直接在service方法里实现逻辑,就不用调用父类的方法。否则,还会先转发到相应的get/post方法里执行后在调用service方法里自己的逻辑。
4、销毁
大部分web容器关闭或者检测到一个servlet要从容器中被删除时,会自动调用destory方法。
@Override
public void destroy() {
// NOOP by default
}
5、卸载
但一个servlet调用玩destory后,此实例将被垃圾回收,当需要再次使用时,将会重新调用init方法。需要注意的是,在正常情况下,Servlet只会初始化一次,但是当Servlet长时间不使用的话,也会被容器自动销毁,而如果需要再次使用时,会重新进行初始化操作,即在特殊情况下初始化操作和销毁操作也会执行多次。