Servlet工作原理解析

概述:Tomcat是如何工作的?一个Web工程在Tomcat中是如何启动的?Tomcat如何解析你在web.xml中定义的Servlet;用户的请求是如何被分配给指定的Servlet的;Servlet容器是如何管理Servlet的生命周期的;

从Servlet容器(Tomcat)说起

       Servlet和Servlet容器通过标准化接口来互相协作;我们就先这些接口说起;

       在Tomcat的容器模型中,Context容器直接管理Servlet在容器中的包装类Wapper,所以Context容器将直接影响Servlet的工作方式;


       从上图可以看出,Tomcat的容器分为4个等级,真正管理Servlet的容器是Context容器,一个Context对应一个Web工程,在Tomcat配置文件中就可以发现这一点;

<Context path="/projectOne " docBase="D\projects\projectOne" reloadable="true"/>

Servlet容器的启动过程

      Tomcat有个启动类org.apache.catalina.startup.Tomcat,创建一个实例对象并调用start方法就可以很容易地启动Tomcat;我们可以通过这个对象来增加和修改Tomcat的配置参数,如可以动态增加Context,Servlet等;

Tomcat tomcat = getTomcatInstance();       //1.创建Tomcat实例

File appDir = new File(getBuildDirectory(),"webapps/example");  //example是一个Web工程
tomcat.addWebapp(null,"/examples",appDir.getAbsolutePath());    //2.新增example这个Web工程

tomcat.start();    //3.启动Tomcat

ByteChunk res = getUrl("http://localhost:"+getPort()+"examples/servlets/setvlet/HelloWordExample");
//4.调用其中的一个HelloWorldExample这个Servlet,看有没有返回正确的数据
assertTrue(res.toString().indexOf("<h1>Hello World!</h1>") > 0); 
//Tomcat的addWebapp()
//一个Web应用对应一个Context容器(StandardContext),也就是Servlet运行时的Context容器
public Context addWebapp(Host host,String url,String path){
    silence(url);

    //1.创建一个StandardContext容器,并给做个容器设置参数
    Context ctx = new StandardContext();
    ctx.setPath(url);     //url是这个web应用在Tomcat中的访问路径
    ctx.setDocBase(path); //path是这个web应用的实际物理地址

    if(defaultRealm == null){
        initSimpleAuth();
    }  
    ctx.setRealm(defaultRealm);
    ctx.addLifecycleListener(new DefaultWebXmlLISTENER());  

    //2.ContextConfig将负责整个Web应用配置参数的解析
    ContextConfig ctxCfg = new ContextConfig();
    ctx.addLifecycleListener(ctxCfg);
    ctx.setDefaultWebXml("org/apache/catalina/startup/NO_DEFAULT_XML");

    //3.将这个Context容器添加到父容器Host中
    if(host == null){
        getHost().addChild(ctx);
    } else {
        host.addChild(ctx);
    }
    return ctx;
}

    Context容器(StandardContext)初始化时,添加到Context容器的Listener将会被调用;ContextConfig继承了LifecycleListener接口,它是在调用Tomcat.addWebapp时被加入到StandardContext容器中的;

       ContextConfig类会负责整个Web应用的配置文件的解析工作;它的init方法将完成以下工作:

       1.创建用于解析XML配置文件的contextDigester对象;

       2.读取默认的context.xml配置文件;

       3.读取默认的Host配置文件;

       4.读取默认的Context自身的配置文件;

       5.设置Context的DocBase;

       之后,Context容器就会执行startInternal方法,主要完成以下几部分:

       1.创建读取资源文件的对象;

       2.创建ClassLoader对象;

       3.设置应用的工作目录;

       4.启动相关的辅助类,如logger。resource等;

       5.修改启动状态,通知观察者;

       6.子容器的初始化;

       7.获取ServletContext并设置必要的参数;

       8.初始化“load on startup”的Servlet;

Web应用的初始化工作

       Web应用的初始化工作是在ContextConfig的configureStart()方法中实现的,应用的初始化主要是解析web.xml文件,这个文件描述了一个Web应用的关键信息,也是一个Web应用的入口;

       为什么要把Servlet包装成Context容器中的Wrapper(StandardWrapper)而不直接包装成Servlet对象?

       StandardWapper是Tomcat容器中的一部分,它具有容器的特征,而Servlet作为作为一个独立的Web开发标准,不应该强耦合在Tomcat中;

       除了将Servlet包装成StandardWrapper并作为子容器添加到Context中外,其他所有的web.xml属性都被解析到Context中,所以Context容器才是真正运行Servlet的Servlet容器;一个Web应用对应一个Context容器,容器的配置属性由应用的web.xml指定;

创建Servlet实例

       到这里为止,我们已经完成了Servlet的解析工作了,并且被包装成StandardWrapper添加在Context容器中;我们还需要实例化Servlet,才能工作;

创建Servlet对象

       如果Servlet的load-on-startup的配置项大于0,那么Context容器启动时就会被实例化;

    创建Servlet实例的方法是从Wrapper.loadServlet开始的,loadServlet方法先获取servletClass,然后把它交给InstanceManager去创建一个基于servletClass.class的对象;

初始化Servlet

       初始化Servlet在StandardWrapper的initServlet方法中,就是调用Servlet的init方法,同时把包装了StandardWrapper对象的StandardWrapperFacade作为ServletConfig传给Servlet;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值