Java基础面试题(11)----Servlet的理解和生命周期

问题

说说对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 {
    }
....................
}

猜你喜欢

转载自blog.csdn.net/weixin_42229056/article/details/82924776