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); } }
部署的過程其實就是解析 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