tomcat学习笔记CH6

本文通过绘制时序图并结合《howtomcatworks》第六章的内容,详细解析了Tomcat中Servlet的加载过程。重点介绍了Lifecycle组件的事件处理机制、SimpleWrapperValve的作用及其如何实现对Servlet实例的调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在看《how tomcat works》。看完第6章,对整个时序流程还是感觉有点模糊,所以画了一个时序图总结下。
这里写图片描述
其中省略了一部分内容:

  • 生命周期管理,事件发生调用fireLifecycleEvent,相关listener会有动作,省略了
  • 管道的逐级调用省略了
    Lifecycle

    生命周期时间发生时,调用fireLifecycleEvent,被注册的listener会逐个触发,在listener内部检测事件类型,进行相应的处理,fireLifecycleEvent方法的代码如下:

public void fireLifecycleEvent(String type, Object data) 

{   

     LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);   

     LifecycleListener interested[] = null;    

    synchronized (listeners) {     

           interested = (LifecycleListener[]) listeners.clone();   

     }   

     for (int i = 0; i < interested.length; i++)       

        interested[i].lifecycleEvent(event);

}
LifecycleListener在lifecycleEvent方法中对事件类型进行检查,并做出相应的响应。

Servlet的载入

Serlet的载入是在pipline的逐级调用中完成的。查看bootstrap的代码:
Wrapper wrapper1 = new SimpleWrapper();

wrapper1.setName("Primitive");

wrapper1.setServletClass("PrimitiveServlet");

Wrapper wrapper2 = new SimpleWrapper();

wrapper2.setName("Modern");

wrapper2.setServletClass("ModernServlet");{% endcodeblock %}
可以看到Serlvlet跟SimpleWrapper相关,而SimpleWrapper的构造器有如下代码:
public SimpleWrapper() 

{  

    pipeline.setBasic(new SimpleWrapperValve());

}
可以看到SimpleWrapperValve被设置为基础阀。在查看SimpleWrapperValve的invoke方法代码:
public void invoke(Request request, Response response, ValveContext valveContext)  throws IOException, ServletException { 

    SimpleWrapper wrapper = (SimpleWrapper) getContainer(); 

     ServletRequest sreq = request.getRequest();  

    ServletResponse sres = response.getResponse(); 

     Servlet servlet = null;  

    HttpServletRequest hreq = null;  

    if (sreq instanceof HttpServletRequest)   

         hreq = (HttpServletRequest) sreq; 

     HttpServletResponse hres = null; 

     if (sres instanceof HttpServletResponse)    

        hres = (HttpServletResponse) sres;

      // Allocate a servlet instance to process this request  

    try {  

          servlet = wrapper.allocate();  

          if (hres!=null && hreq!=null) {     

             servlet.service(hreq, hres);   

         }    else {   

             servlet.service(sreq, sres);  

          }  

    }  catch (ServletException e) {

      }

}
可以看到servlet的载入。

那么SimpleWrapperValve是怎么找到对应的Wrapper的呢?

从代码SimpleWrapper wrapper = (SimpleWrapper) getContainer(); 看到是调用getContainer方法得到的。而setContainer()发生在addValve和setBasic方法中。

值得一提的是,SimpleWrapperValve在SimpleWrapper的pipeline实例中被设置为基础阀,而SimpleContext的pipeline实例中对应的基础阀则是SimpleContextValve,在SimpleContextValve的invoke方法中有获取Wrapper实例的代码,正是这样实现的从Context调用的子容器Wrapper

SimpleWrapperValve的invoke方法如下:
public void invoke(Request request, Response response, ValveContext valveContext)  throws IOException, ServletException {

      // Validate the request and response object types 

     if (!(request.getRequest() instanceof HttpServletRequest)

         ||    !(response.getResponse() instanceof HttpServletResponse)) 

    { 

       return;  

       // NOTE - Not much else we can do generically 

    }  

    // Disallow any direct access to resources under WEB-INF or META-INF

      HttpServletRequest hreq = (HttpServletRequest) request.getRequest(); 

     String contextPath = hreq.getContextPath();  

    String requestURI = ((HttpRequest) request).getDecodedRequestURI(); 

     String relativeURI =    requestURI.substring(contextPath.length()).toUpperCase();  

    Context context = (Context) getContainer(); 

     // Select the Wrapper to be used for this Request 

     Wrapper wrapper = null; 

     try {   

         wrapper = (Wrapper) context.map(request, true); 

     }  catch (IllegalArgumentException e) {   

         badRequest(requestURI, (HttpServletResponse) response.getResponse());   

         return; 

     }  if (wrapper == null) 

        {  

              notFound(requestURI, (HttpServletResponse) response.getResponse());   

             return; 

         } 

     // Ask this Wrapper to process this Request  

    response.setContext(context); 

     wrapper.invoke(request, response);

}
总结起来就是httpProcessor在process()方法中调用connector.getcontainer().invoke(),使得SimpleContext中的pipeline逐个调用阀,而SimpleContextValve这个基础阀调用了Wrapper,从而实现servlet的载入调用 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值