servlet與tomcat

1、servlet與servlet容器

 (1)servlet本質

   前方高能,請注意、注意、注意。。。重要的事情說三遍,servlet本質就是一個Java接口 ,目的在於定義一套處理網絡請求的規範,如下所示:

package javax.servlet;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public interface Servlet {
    void init(ServletConfig arg0) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

 

  所有實現servlet接口的類,都要實現接口中的五個方法,其中最主要的是兩個生命週期方法 init()和destroy()、處理請求的service(),即:

  • 初始化的作用;
  • 銷燬後的作用;
  • 收到請求後需要做什麼。

 init() 和 destroy()方法只執行一次, 即servlet的生命週期---創建和銷燬,而service()方法每次有新請求到達時都會調用,即處理處理實際業務。

(2)servlet容器

  全稱server applet,意爲服務程序。主要作用是給上級容器(Tomcat)提供doGet()和doPost()等方法。其生命週期實例化、初始化、調用、銷燬受控於Tomcat容器。

 (3)request/response

  request:瀏覽器發起http請求,請求到達tomcat,經tomcat封裝成了request對象(將請求頭、請求地址、請求參數等進行了封裝);

  response:瀏覽器發起http請求到達tomcat容器時,產生一個空的response對象,http請求數據經過servlet處理,將處理後結果封裝成response對象,經過tomcat處理後,組裝成HTTP響應返回給瀏覽器。

 (4)web容器

  可以部署多個WEB應用程序的環境。Tomcat容器屬於web容器的一種,web容器還包括weblogic容器、JBoss容器等;而Tcomcat、webLogic等包含servlet容器。

  

  注:三層架構實質是對servlet的拆分,目的在於解耦合。

 

2、tomcat

(1)tomcat程序入口main()

  main方法是啓動一個java程序的入口,任何程序都會有自己的main方法,tomcat是一個WEB容器,也不例外:

//TODO 以下爲僞代碼,目的在於說明tomcat執行原理
public static void main(String args[]) {
       //TODO 初始化運行環境,載入需要的jar包,讀取conf/server.xml,生成相應的運行對象:
        if (daemon == null) {
            Bootstrap bootstrap = new Bootstrap();
            try {
                bootstrap.init();//初始化守護進程
            } catch (Throwable t) {
                return;
            }
            daemon = bootstrap;
        } 
   //TODO 裝載,開始運行。
        try {
            String command = "start";
            if (command.equals("startd")) {
                daemon.load(args);
                daemon.start();//啓動Tomcat
            } else if (command.equals("stopd")) {
                args[args.length - 1] = "stop";
                daemon.stop();//停止Tomcat守護進程
            } 
        } catch (Throwable t) {
        }
    }

(2)tomcat創建的resques和response

 

(3)tomcat對servlet接口的實現

   邏輯層級關係:

    abstract class GenericServlet implements Servlet, ServletConfig,Serializable

    abstract class HttpServlet extends GenericServlet

public abstract class HttpServlet extends GenericServlet {

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }
    }
    
    //TODO doHead doPut doDelete

    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }
    }

    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String method = req.getMethod();
        long errMsg;
        if (method.equals("GET")) {
            errMsg = this.getLastModified(req);
            if (errMsg == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException arg8) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < errMsg / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, errMsg);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        }  else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else {
            String errMsg1 = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[] { method };
            errMsg1 = MessageFormat.format(errMsg1, errArgs);
            resp.sendError(501, errMsg1);
        }
    }

    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException arg5) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }

        this.service(request, response);
    }
}

 

(4)web容器的部署

  部署的過程其實就是解析 xml 實例化對象,並觸發和處理容器及組件對應生命週期事件的過程。在 Tomcat 中,一個 Context 實例就代表一個 Web 應用程序,所以部署的第一步就是創建一個 StandardContext 對象。在創建時 HostConfig 首先會查找 Context 描述符,它可能在兩個位置:

  • $CATALINA_BASE/conf/<engine>/<host>/[webappname].xml
  • $CATALINA_BASE/webapps/webappname/META_INF/context.xml

  如果兩個位置都不存在此文件,則使用 conf/context.xml 默認配置。

  Context 實例化後會觸發 init 和 start 生命週期事件:

  • init - 會創建用於解析 context.xml 和 web.xml 的工具 Digester 的實例,並解析context.xml
  • start - 則會根據 web.xml 部署描述符實例化 Servlet、Filter、Listener 等 Web 組件

 

  感謝閱讀,參考了不少大佬資料,如需轉載,請註明出處 https://www.cnblogs.com/huyangshu-fs/p/13173474.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章