Tomcat是实现了http协议的web服务器。

      HttpServlet是整个J2EE体系的核心类。来自客户端的全部请求均有该类进行处理和转发。它由Tomcat根据web.xml中的servlet配置标记进行装载和管理。

      以下是servlet继承结构。

 javax.servlet.http
Class HttpServlet

java.lang.Object
  javax.servlet.GenericServlet
      javax.servlet.http.HttpServlet

      Servlet生命周期从init()开始(启动Tomcat时候自动调用),当客户端发来Http请求时候,调用service()处理方法,service方法中含有很多Http请求方法,如post,get,delete,option,put,delete,trace,head。这些方法的实现在http报文中请求方法一栏。最后关闭Tomcat时候调用destroy()方法。(servlet是单例)

wKioL1THNfahGAkDAAFu--59S3M173.jpg

      下面来看Tomcat源码中三个方法的实现:

     //初始化配置信息,在web.xml中

  public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
    }

       //service()主要调用doXXX方法,XXX对于Http协议中的请求方法。

   protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        //从Req请求中取出方法,并判断方法类型
        String method = req.getMethod();
        if (method.equals(METHOD_GET)) {
                //获取服务器资源最后修改时间lastModified(缓存机制的一种)
            long lastModified = getLastModified(req);
            //-1的话不支持if-modified-since
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
            //响应头中返回lastModified,再次请求时候请求头增加一个
            //ifModifiedSince,询问当前页面是否是最新的。
                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);
        }
    }
    //总的逻辑就是先去缓存中的数据,再去调用相应的方法。

     //一次请求生命周期结束,而不是销毁容器,销毁容器是Catalina类中的stopServer()方法。没找到destroy的具体方法。就这么销毁了?对应gc吗?一个疑问?求评论。

 public void destroy() {
    }

       下面是HttpServlet中的一些方法与属性:

        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(LSTRING_FILE);

        protected void doGet(HttpServletRequest req, HttpServletResponse resp)

        protected void doHead(HttpServletRequest req, HttpServletResponse resp)

        protected void doPost(HttpServletRequest req, HttpServletResponse resp)

        protected void doPut(HttpServletRequest req, HttpServletResponse resp)

       protected void doDelete(HttpServletRequest req, HttpServletResponse resp).............

      

        这就是Http协议中请求方法对应的Tomcat实现。换个提法:Tomcat中有几种请求类型?其实质再问Htpp协议中的方法理解。每个方法都有其特性。为什么Http协议需要这么方法?比如哪些方法是安全的,哪些方法是等幂方法?(具体区别详见--Http协议RFC2616 9.1节)。也许知道这些背后的原理,才可以知道Http协议的精髓。我觉得一个苹果砸醒了牛顿,而一个协议带领人类走向互联网时代。堪比计算机届的E=MC^2!!!

       附HttpRFC2616协议。