问题
说说对servlet的理解?
什么是servlet的生命周期?
回答
Servlet是什么?
selvet(server applet),全称Java Servlet,使用Java语言编写的服务端程序,这些servlet都需要继承HttpServlet这个抽象类,重写的doGet()和doPost()这两个方法,或者主动重写service()方法。HttpServlet最终实现的是Servlet这个接口。
其主要的功能是在于交互的浏览和修改数据,生成动态的web内容,servlet运行于支持Java的应用服务器中。
servlet是可以单例多线程,多个用户在页面进行请求的时候,实际只有一个Servlet对象,因为这些操作都是统一的,没有必要生产多个对象造成资源浪费。具体可以了解一下单例模式的相关知识。
Serlvet的生命周期
首先看一下我们自定义的MySerlvet的继承关系图
再看一下Servlet接口中定义的方法,这里实际是定义了servlet的声明周期
package javax.servlet;
import java.io.IOException;
public interface Servlet {
//初始化方法
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
//执行方法
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
//销毁的方法
void destroy();
}
运行的过程大致如下:
- servlet启动时,开始加载servet,生命周期开始,看一下源码,两个被继承的类在被继承的时候,都会加载相关的静态资源,所以自定义的类一旦被创建,就会在编译器自动加载静态资源。
public abstract class HttpServlet extends GenericServlet implements Serializable {
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String HEADER_LASTMOD = "Last-Modified";
private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
//静态资源在编译器就会被加载
private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");
// GenericServlet类
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
private transient ServletConfig config;
- servlet被服务器实例化后,容器运行init()方法,我们可以对init()方法进行自己的实现。 **在一个Servlet的生命周期中,init方法只会被执行一次,**之后无论用户执行多少次请求,都不会在调用该方法。
关于init方法的执行时机,有两种方式可选,一般的是在服务器启动后第一个用户请求改Servlet是调用,你也可以设置该Servlet在服务器启动后自动执行。
init方法负责简单的创建或者加载一些数据,这些数据将用于该Servlet的整个生命周期中。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
...................
初始化方法
public void init() throws ServletException {
}
....................
}
- 请求到达时运行其service()方法,service方法自动派遣运行对应的doGet()或者doPost()方法, 每一次请求服务器都会开启一个新的线程并执行一次service方法。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
...................
//在这里定义抽象的service()方法
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
....................
//httpServlet类
public abstract class HttpServlet extends GenericServlet implements Serializable {
................
//service方法做了一系列的方法判断,按照子类的相关信息给出对应的类
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
...................
}
- 当服务器服务器决定将其实例销毁的时候,会调用destroy()方法,这个方法和init()方法的实现位置和类型一样,父类中定义了空方法,可以自己重写。该方法在整个生命周期中,也是只会被调用一次,在Servlet对象被销毁是调用,在servlet中,我们可以做一些资源的释放等操作,执行destory()方法之后的servlet对象,会等待jvm虚拟机的垃圾回收机制择时回收。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
...................
销毁的方法
public void destroy() throws ServletException {
}
....................
}