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 (上面的部分)

时间: 2024-08-03 08:00:04

Servlet容器的启动(Tomcat为例)的相关文章

容器配置jndi Tomcat为例

context.xml 文件 <Resource name="spring/sjpt" auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" maxActive="20" maxIdle="10" maxWait="10000" password="spsj" type="

配置嵌入式Servlet容器

SpringBoot默认是用的是Tomcat作为嵌入式的Servlet容器:问题?1).如何定制和修改Servlet容器的相关配置:1.修改和server有关的配置(ServerProperties): server.port=8081 server.context-path=/crud server.tomcat.uri-encoding=UTF-8 //通用的Servlet容器设置 server.xxx //Tomcat的设置 server.tomcat.xxx 2.编写一个Embedded

SpringBoot(七) -- 嵌入式Servlet容器

一.嵌入式Servlet容器 在传统的开发中,我们在完成开发后需要将项目打成war包,在外部配置好TomCat容器,而这个TomCat就是Servlet容器.在使用SpringBoot开发时,我们无需再外部配置Servlet容器,使用的是嵌入式的Servlet容器(TomCat).如果我们使用嵌入式的Servlet容器,存在以下问题: 1.如果我们是在外部安装了TomCat,如果我们想要进行自定义的配置优化,可以在其conf文件夹下修改配置文件来实现.在使用内置Servlet容器时,我们可以使用

SpringBoot-配置嵌入式Servlet容器(十三)

SpringBoot默认使用Tomcat作为嵌入式的Servlet容器: 如何定制和修改Servlet容器的相关配置 1.修改和server有关的配置(ServerProperties[也是EmbeddedServletContainerCustomizer]): server.port=8081 server.context-path=/crud server.tomcat.uri-encoding=UTF-8 //通用的Servlet容器设置 server.xxx //Tomcat的设置 s

在eclipse中启动Tomcat报端口被占用的错误

安装配置好Tomcat之后,在浏览器中输入localhost,能正取打开页面.然后在eclipse中建立项目,创建Servlet之后,启动Tomcat,报端口被占用的错误.如图: 原因:原来已经启动了apache-tomcat-6.0.47\bin\startup.bat,没有关闭,所以导致端口被占用. 解决方法:在eclipse中启动Tomcat,需要先把原先启动apache-tomcat-6.0.47\bin\startup.bat服务关闭.

Servlet 容器

Servlet容器主要是JavaWeb应用提供运行时环境,所以也可以称之为JavaWeb应用容器,或者Servlet/JSP容器.Servlet容器主要负责管理Servlet.JSP的生命周期以及它们的共享数据. Servlet容器有哪些: 目前最流行的Servlet容器软件包括: Tomcat.Jetty.Jboss等. Tomcat Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式.

springboot(八) 嵌入式Servlet容器自动配置原理和容器启动原理

1.嵌入式Servlet容器自动配置原理 1.1 在spring-boot-autoconfigure-1.5.9.RELEASE.jar => springboot自动配置依赖 jar包下,EmbeddedServletContainerAutoConfiguration => 嵌入式servlet容器自动配置类 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnWebApplicatio

tomcat(5)servlet容器

[0]README 0.0)本文部分文字描述转自:“深入剖析tomcat”,旨在学习 tomcat(5)servlet容器 的基础知识: 0.1)intro to servlet容器:servlet容器是用来处理请求servlet资源,并为web客户端填充response 对象的模块: 0.1.1)servlet容器:是 org.apache.catalina.Container接口的实例: 0.1.2)在Tomcat中,共有四种容器(types): t1)Engine: t2)Host: t3

how tomcat works 五 servlet容器 上

servlet容器是用来处理请求servlet资源,并为Web客户端填充response对象的模块.在上一篇文章(也就是书的第四章)我们设计了SimpleContainer类,让他实现Container接口,也基本完成了容器的作用.但是我们得知道在实际的tomcat中有4类容器: Engine: 表示整个Catalina servlet引擎; Host: 包含一个或多个Context容器的虚拟主机; Context:表示一个Web应用程序,一个Context可以包含多个Wrapper Wrapp