1. 程式人生 > >Servlet容器的啟動(Tomcat為例)

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