【Servlet】Servlet生命周期

Servlet的生命周期:
1.当Servelt被装载到容器中后,创建一个Servlet实例,并调用init()方法进行初始化。

2.初始化后的实例调用service()方法处理用户请求。

3.调用destroy()方法,销毁Servlet实例。

       Init()方法只会被调用一次,在Servlet被第一次请求加载时调用该方法,此后再有用户请求访问Servelt时,服务器会启动一个新的线程调用service()方法响应用户的请求,所以说每个用户的每一次请求都会使service()方法被调用,它们的执行过程是在不同的线程中进行的。因此,一个Servlet的init()方法只会被调用一次,而service()会被多次调用。

       Servlet本身是一个接口,而大家平时在创建Servlet的时候是继承HttpServlet类的,而且有一件事情很奇怪,关于Servlet的生命周期,提到实例是调用service()方法处理用户请求的,但在实际编码中,我们是通过调用HttpServlet的doGet()和doPost()方法处理用户请求,这就奇怪了,到底Servlet是怎样进行调用的?

       其实HttpServlet是有service()方法的,还记得刚开始学习Servlet的时候,老师跟我们说了这样一句话,我现在想想都觉得好笑,他说写Servlet的时候,doPost()、doGet()方法不能同时跟service()方法一起写。虽然是好笑,但是从表面看来他也没说错,那到底是怎么一回事呢?实际上,HttpServelt与Servlet接口是没有直接关系的,HttpServlet继承了GenericServlet类,而GenericServlet类是一个实现了Servlet接口的抽象类,他们的关系如下:


Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,如上图所示,我们除了继承HttpServlet类之外,还可以通过继承GenericServlet抽象类编写Servlet类。Servlet接口定义了5个方法,包括关系Servlet生命周期的3个重要方法,GenericServlet抽象类中也有这3个方法。虽然平时我们写Servlet类用得比较多的方法是HttpServlet的doPost()和doGet()方法。但实际上在HttpServlet类中有两个service()方法,一个是重写GenericServlet类的,一个是HttpServlet自己定义的。在实际的调用中,Servlet初始化后是调用源自Servlet接口的service()方法,在HttpServlet中,该方法将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse。在方法的最后调用HttpServlet自定义的service()方法,在自定义的service()方法中根据方法名去调用具体的处理方法,也就是在service()方法中经过判断调用doPost()或doGet()等方法。

这两个方法的源码如下:

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 = req.getDateHeader(HEADER_IFMODSINCE);
                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类时,一般重写doPost()和doGet()方法,如果重写了service()方法,那么就不能调用doPost和doGet()方法,除非你重写service()方法的时候对doPost和doGet()方法进行调用。所以没必要那样写,不过也不是说不能同时写,了解了这个调用过程,我们就知道是怎么回事了。


Author:立礼

Sign:人生不要有太多的幻想,而要有更多的行动。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值