Servlet容器的啟動(Tomcat為例)
一.容器簡介
在tomcat容器等級中,context容器直接管理servlet在容器中的包裝類Wrapper,所以Context容器如何執行將直接影響servlet的工作方式。
tomcat容器模型如下:
一個context對應一個web工程,在tomcat的配置檔案server.xml中,可以發現context的配置(在eclipse工程中,可在部署路徑的conf資料夾zhoing找到)
1 Context docBase="/Users/wongrobin/all/projects/tech-test/java-test/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/base-webapp" path="/base-webapp" reloadable="true" source="org.eclipse.jst.j2ee.server:base-webapp"/>
二.啟動servlet
Tomcat7增加了一個啟動類:
1 org.apache.catalina.startup.Tomcat
建立一個Tomcat的一個例項物件並呼叫start方法就可以啟動tomcat。
還可以通過這個物件來增加和修改tomcat的配置引數,如可以動態增加context,servlet等。
在tomcat7中提供的example中,看是如何新增到context容器中:
1 Tomcat tomcat = getTomcatInstance(); 2 File appDir = new File(getBuildDirectory(), "webapps/examples");3 tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath()); 4 tomcat.start(); 5 ByteChunk res = getUrl("http://localhost:" + getPort() + 6 "/examples/servlets/servlet/HelloWorldExample"); 7 assertTrue(res.toString().indexOf("<h1>Hello World!</h1>") > 0);
這段程式碼建立了一個Tomcat例項並新增了一個WEB應用,然後啟動Tomcat並呼叫其中的一個HelloWorldExampleServlet。
Tomcat的addWebap方法的程式碼如下:
1 public Context addWebapp(Host host, String url, String path) { 2 silence(url); 3 Context ctx = new StandardContext(); 4 ctx.setPath( url ); 5 ctx.setDocBase(path); 6 if (defaultRealm == null) { 7 initSimpleAuth(); 8 } 9 ctx.setRealm(defaultRealm); 10 ctx.addLifecycleListener(new DefaultWebXmlListener()); 11 ContextConfig ctxCfg = new ContextConfig(); 12 ctx.addLifecycleListener(ctxCfg); 13 ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML"); 14 if (host == null) { 15 getHost().addChild(ctx); 16 } else { 17 host.addChild(ctx); 18 } 19 return ctx; 20 }
一個WEB應用對應一個context容器,也就是servlet執行時的servlet容器。新增一個web應用時將會建立一個StandardContext容器,並且給這個context容器設定必要的引數,url和path分別代表這個應用在tomcat中的訪問路徑和這個應用實際的物理路徑,這兩個引數與tomcat配置中的兩個引數是一致的。其中一個最重要的一個配置是ContextConfig,這個類會負責整個web應用配置的解析工作。
最後將這個context容器加入到父容器host中。
接下來會呼叫tomcat的start方法啟動tomcat。
Tomcat的啟動邏輯是基於觀察者模式的,所有的容器都會繼承Lifecycle介面,它管理著容器的整個生命週期,所有容器的修改和狀態改變都會由它通知已經註冊的觀察者。
Tomcat啟動的時序如下:
當context容器初始狀態設定Init時,新增到context容器的listener將會被呼叫。ContextConfig繼承了LifecycleListener介面,它是在呼叫Tomcat.addWebapp時被加入到StandardContext容器中的。ContextConfig類會負責整個WEB應用的配置檔案的解析工作。
ContextConfig的init方法將會主要完成一下工作:
- 建立用於解析XML配置檔案的contextDigester物件
- 讀取預設的context.xml檔案,如果存在則解析它
- 讀取預設的Host配置檔案,如果存在則解析它
- 讀取預設的Context自身的配置檔案,如果存在則解析它
- 設定Context的DocBase
ContextConfig的init方法完成後,Context容器會執行startInternal方法,這個方法包括如下幾個部分:
- 建立讀取資原始檔的物件
- 建立ClassLoader物件
- 設定應用的工作目錄
- 啟動相關的輔助類,如logger,realm,resources等
- 修改啟動狀態,通知感興趣的觀察者
- 子容器的初始化
- 獲取ServletContext並設定必要的引數
- 初始化“load on startuo”的Servlet
三.Web應用的初始化
WEB應用的初始化工作是在ContextConfig的configureStart方法中實現的,應用的初始化工作主要是解析web.xml檔案,這個檔案是一個WEB應用的入口。
Tomcat首先會找globalWebXml,這個檔案的搜尋路徑是engine的工作目錄下的org/apache/catalina/startup/NO-DEFAULT_XML或conf/web.xml。接著會找hostWebXml,這個檔案可能會在System.getProperty("catalina.base")/conf/${EngineName}/${HostName}/web.xml.default中。接著尋找應用的配置檔案examples/WEB-INF/web.xml,web.xml檔案中的各個配置項將會被解析成相應的屬性儲存在WebXml物件中。接下來會講WebXml物件中的屬性設定到context容器中,這裡包括建立servlet物件,filter,listerner等,這些在WebXml的configureContext方法中。
下面是解析servlet的程式碼物件:
1 for (ServletDef servlet : servlets.values()) { 2 Wrapper wrapper = context.createWrapper(); 3 String jspFile = servlet.getJspFile(); 4 if (jspFile != null) { 5 wrapper.setJspFile(jspFile); 6 } 7 if (servlet.getLoadOnStartup() != null) { 8 wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue()); 9 } 10 if (servlet.getEnabled() != null) { 11 wrapper.setEnabled(servlet.getEnabled().booleanValue()); 12 } 13 wrapper.setName(servlet.getServletName()); 14 Map<String,String> params = servlet.getParameterMap(); 15 for (Entry<String, String> entry : params.entrySet()) { 16 wrapper.addInitParameter(entry.getKey(), entry.getValue()); 17 } 18 wrapper.setRunAs(servlet.getRunAs()); 19 Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs(); 20 for (SecurityRoleRef roleRef : roleRefs) { 21 wrapper.addSecurityReference(roleRef.getName(), roleRef.getLink()); 22 } 23 wrapper.setServletClass(servlet.getServletClass()); 24 MultipartDef multipartdef = servlet.getMultipartDef(); 25 if (multipartdef != null) { 26 if (multipartdef.getMaxFileSize() != null && 27 multipartdef.getMaxRequestSize()!= null && 28 multipartdef.getFileSizeThreshold() != null) { 29 wrapper.setMultipartConfigElement(new MultipartConfigElement( 30 multipartdef.getLocation(), 31 Long.parseLong(multipartdef.getMaxFileSize()), 32 Long.parseLong(multipartdef.getMaxRequestSize()), 33 Integer.parseInt( 34 multipartdef.getFileSizeThreshold()))); 35 } else { 36 wrapper.setMultipartConfigElement(new MultipartConfigElement( 37 multipartdef.getLocation())); 38 } 39 } 40 if (servlet.getAsyncSupported() != null) { 41 wrapper.setAsyncSupported( 42 servlet.getAsyncSupported().booleanValue()); 43 } 44 context.addChild(wrapper); 45 }
上面的程式碼將servlet容器包裝成context容器中的StandardWrapper。StandardWrapper是tomcat容器中的一部分,它具有容器的特徵,而Servlet作為一個獨立的web開發標準,不應該強制耦合在tomcat中。
除了將Servlet包裝成StandardWrapper並作為子容器新增到Context中外,其他所有的web.xml屬性都被解析到Context中。
四.建立Servlet例項
前面完成了servlet的解析工作,並且被包裝成了StandardWrapper新增到Context容器中,但是它仍然不能為我們工作,它還沒有被例項化。
1.建立
如果Servlet的load-on-startup配置項大於0,那麼在Context容器啟動時就會被例項化。
前面提到的在解析配置檔案時會讀取預設的globalWebXml,在conf下的web.xml檔案中定義了一些預設的配置項,其中定義了兩個Servlet,分別是org.apache.catalina.servlets.DefaultServlet和org.apache.jsper.servlet.JspServelt,它們的load-on-startup分別是1和3,也就是當tomcat啟動時這兩個servlet就會被啟動。
建立Servlet例項的方式是從Wrapper.loadServlet開始的,loadServlet方法要完成的就是獲取servletClass,然後把它交給InstanceManager去建立一個基於servletClass.class的物件。如果這個Servlet配置了jsp-file,那麼這個servletClass就是在conf/web.xml中定義的org.apache.jasper.servlet.JspServlet。
2.初始化
初始化Servlet在StandardWrapper的initServlet方法中,這個方法很簡單,就是呼叫Servlet的init()方法,同時把包裝了StandardWrapper物件的StandardWrapperFacade作為ServletConfig傳給Servlet。
如果該Servlet關聯的是一個JSP檔案,那麼前面初始化的就是JspServlet,接下來會模擬一次簡單請求,請求呼叫這個JSP檔案,以便編譯這個JSP檔案為類,並初始化這個類。
這樣Servlet物件的初始化就完成了。
3.容器預設Servlet
每個servlet容器都有一個預設的servlet,一般都叫做default。
例如:tomcat中的 DefaultServlet 和 JspServlet (上面的部分)
相關推薦
26 外接Servlet容器(以Tomcat為例)使用
1 步驟 1.1 建立war專案 1.2 將內建Tomcat指定為provided <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.
Servlet容器的啟動(Tomcat為例)
一.容器簡介 在tomcat容器等級中,context容器直接管理servlet在容器中的包裝類Wrapper,所以Context容器如何執行將直接影響servlet的工作方式。 tomcat容器模型如下: 一個context對應一個web工程,在tomcat的配置檔案server.xml中,可以發
Servlet容器啟動過程(以Tomcat中啟動Servlet容器為例)
一、Tomcat的總體結構中的Service模組及Container容器(引入) tomcat啟動server伺服器(包含多個服務模組)對外提供Service服務,Service模組由Container元件連線多個Connector構成。 Service
22 配置嵌入式Servlet容器(Tomcat為例)
SpringBoot預設使用Tomcat作為嵌入式的Servlet容器 1 自定義Server相關配置 1.1 通過application.properties自定義 # 通用的Servlet容器設定 server.port=8081 # Tomcat的設定
Java技術_基礎技術(0002)_中介軟體啟動class載入順序(以tomcat為例)
基礎技術: Tomcat的class載入的優先順序一覽 1.$JAVA_HOME/jre/lib/ext/下的jar檔案。 2.環境變數CLASSPATH中的jar和class檔案。
Servlet執行原理(Tomcat為例)
Servlet 一、首先servlet是一個java應用程式,執行在伺服器端,用來處理客戶端請求(http請求)並作出響應的程式。 二、http定義了與伺服器互動的幾種方式最基本常用的有:GET、POST、PUT、DELETE。使用頻率最高的就是GET、還有POST 1
docker容器操作步驟及常用命令已tomcat為例
第一步:搜尋需要用的映象。比如需要tomcat # docker search tomcat index 是序列號,name 映象的名稱,description 映象的一些資訊,stars 關注度多少人,official 是不是官方的,autmomated是不是私有
war包的安裝與部署(以兩個Tomcat為例,詳細)
1 首先匯入資料庫(資料庫中要有該war包的資料庫) 2 執行 jzsales-manager-web.war 在8080埠上 2.1 將 jzsales-manager-web.war複製到Tomcat下的webapps資料
將Maven工程匯出war包(匯出可執行檔案) war包的安裝與部署(以兩個Tomcat為例,詳細)請到:
1 開啟war工程的pom.xml,將如下內容複製到配置Tomcat的程式碼中 &l
SpringBoot嵌入式servlet容器啟動原理
轉載自caychen的部落格SpringBoot嵌入式servlet容器啟動原理 從原始碼的角度分析SpringBoot內嵌的servlet容器是怎麼啟動的 Spring Boot應用啟動執行run方法: public ConfigurableApplicationCo
Spring Boot 嵌入式 Servlet 容器啟動原理
什麼時候建立嵌入式 Servlet 容器工廠? 什麼時候獲取嵌入式 Servlet 容器並啟動服務? 1)、Spring Boot 應用啟動執行 run(); 方法 2)、refreshContext
修改網站的圖示,以tomcat為例! (修改tomcat中的網站圖示)
在用瀏覽器開啟網站的時候,瀏覽器標籤頁上面有網站的圖示,類似於logo小圖示,如下圖: 原來這個是tomcat的一個小貓圖示,現在我們替換成我們自己的logo小圖示! 步驟1:開啟你的tomca
25 Servlet容器啟動原理
1 SpringBoot專案啟動 1.1 SpringBoot應用啟動執行run方法 Springboot21Application @SpringBootApplication public class Springboot21Application {
SpringBoot中嵌入式Servlet容器啟動原理;
什麼時候建立嵌入式的Servlet容器工廠?什麼時候獲取嵌入式的Servlet容器並啟動Tomcat; 獲取嵌入式的Servlet容器工廠: 1)、SpringBoot應用啟動執行run方法 2)、refreshContext(context);SpringBo
技術乾貨丨Java Web本地提權以及資料劫持思路(以Tomcat為例)
最近偶然接觸到一個Java的不常用的特性:instrument。簡單來說,這個特性允許你在程式執行之前改變任意類檔案的位元組碼。 簡單的instrument例子大家可以百度,相當多。 而在執行Java程式的時候,只需要加上一個選項即可執行寫好的instrument jar包,如:java -javaa
Servlet容器(Tomcat)中釋出並實現jax-ws應用 webservice 理論與實踐步驟
以上為web.xml,web應用部署描述符檔案的相關與Spring和CXF框架整合的配置 其中hello_world_servlet為專案根目錄,即tomcat的webapp 下的名為hello_world_servlet這個webservice專案的根目錄
關於JNDI淺談(tomcat為例)
本文算我寫的一個筆記,參考瞭如下部落格: http://gearever.iteye.com/blog/1560135 http://gearever.iteye.com/blog/1554295 http://blog.sina.com.cn/s/blog_542200
SpringBoot系列之外部Servlet容器啟動原理
外部Servlet容器啟動springboot應用原理 瞭解外部Servlet容器啟動springboot的原理,需要先了解一個規則,這個規則可以參考servlet3.0規範的8.2.4章 Shared libraries / runtimes pluggability:
SpringBoot系列之嵌入式servlet容器啟動原理
嵌入式servlet容器啟動原理 本文將探討以下問題: 什麼時候建立嵌入式的Servlet容器工廠?什麼時候獲取嵌入式的Servlet容器並啟動Tomcat; 1)、SpringBoot應用啟動執行run方法 2)、refreshContext(context);S
Android情景分析之詳解init程序(以啟動zygote為例)
概述 init是linux系統中使用者空間的第一個程序。由於Android是基於linux核心的,所以init也是Android系統中使用者空間的第一個程序,它的程序號為1。 作為系統中的第一個使用者空間程序,init程序被賦予了很多及其重要的工作職責。 1. i